001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.search;
016    
017    import com.liferay.portal.NoSuchResourceException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.search.BooleanClauseOccur;
022    import com.liferay.portal.kernel.search.BooleanQuery;
023    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
024    import com.liferay.portal.kernel.search.Document;
025    import com.liferay.portal.kernel.search.Field;
026    import com.liferay.portal.kernel.search.Indexer;
027    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
028    import com.liferay.portal.kernel.search.Query;
029    import com.liferay.portal.kernel.search.SearchContext;
030    import com.liferay.portal.kernel.search.SearchPermissionChecker;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.StringPool;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.model.Group;
035    import com.liferay.portal.model.GroupConstants;
036    import com.liferay.portal.model.Permission;
037    import com.liferay.portal.model.Resource;
038    import com.liferay.portal.model.ResourceConstants;
039    import com.liferay.portal.model.Role;
040    import com.liferay.portal.model.RoleConstants;
041    import com.liferay.portal.model.UserGroupRole;
042    import com.liferay.portal.security.permission.ActionKeys;
043    import com.liferay.portal.security.permission.AdvancedPermissionChecker;
044    import com.liferay.portal.security.permission.PermissionChecker;
045    import com.liferay.portal.security.permission.PermissionCheckerBag;
046    import com.liferay.portal.security.permission.PermissionThreadLocal;
047    import com.liferay.portal.security.permission.ResourceActionsUtil;
048    import com.liferay.portal.service.GroupLocalServiceUtil;
049    import com.liferay.portal.service.PermissionLocalServiceUtil;
050    import com.liferay.portal.service.ResourceLocalServiceUtil;
051    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
052    import com.liferay.portal.service.RoleLocalServiceUtil;
053    import com.liferay.portal.service.UserGroupRoleLocalServiceUtil;
054    import com.liferay.portal.util.PropsValues;
055    import com.liferay.util.UniqueList;
056    
057    import java.util.ArrayList;
058    import java.util.HashMap;
059    import java.util.List;
060    import java.util.Map;
061    
062    /**
063     * @author Allen Chiang
064     * @author Bruno Farache
065     * @author Raymond Augé
066     * @author Amos Fong
067     */
068    public class SearchPermissionCheckerImpl implements SearchPermissionChecker {
069    
070            public void addPermissionFields(long companyId, Document document) {
071                    try {
072                            long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID));
073    
074                            String className = document.get(Field.ENTRY_CLASS_NAME);
075    
076                            if (Validator.isNull(className)) {
077                                    return;
078                            }
079    
080                            String classPK = document.get(Field.ROOT_ENTRY_CLASS_PK);
081    
082                            if (Validator.isNull(classPK)) {
083                                    classPK = document.get(Field.ENTRY_CLASS_PK);
084                            }
085    
086                            if (Validator.isNull(classPK)) {
087                                    return;
088                            }
089    
090                            Indexer indexer = IndexerRegistryUtil.getIndexer(className);
091    
092                            if (!indexer.isFilterSearch()) {
093                                    return;
094                            }
095    
096                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
097                                    doAddPermissionFields_5(
098                                            companyId, groupId, className, classPK, document);
099                            }
100                            else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
101                                    doAddPermissionFields_6(
102                                            companyId, groupId, className, classPK, document);
103                            }
104                    }
105                    catch (NoSuchResourceException nsre) {
106                    }
107                    catch (Exception e) {
108                            _log.error(e, e);
109                    }
110            }
111    
112            public Query getPermissionQuery(
113                    long companyId, long[] groupIds, long userId, String className,
114                    Query query, SearchContext searchContext) {
115    
116                    try {
117                            query = doGetPermissionQuery(
118                                    companyId, groupIds, userId, className, query, searchContext);
119                    }
120                    catch (Exception e) {
121                            _log.error(e, e);
122                    }
123    
124                    return query;
125            }
126    
127            public void updatePermissionFields(long resourceId) {
128                    try {
129                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
130                                    doUpdatePermissionFields_5(resourceId);
131                            }
132                    }
133                    catch (Exception e) {
134                            _log.error(e, e);
135                    }
136            }
137    
138            public void updatePermissionFields(
139                    String resourceName, String resourceClassPK) {
140    
141                    try {
142                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
143                                    doUpdatePermissionFields_6(resourceName, resourceClassPK);
144                            }
145                    }
146                    catch (Exception e) {
147                            _log.error(e, e);
148                    }
149            }
150    
151            protected void addRequiredMemberRole(
152                            Group group, BooleanQuery permissionQuery)
153                    throws Exception {
154    
155                    if (group.isOrganization()) {
156                            Role organizationUserRole = RoleLocalServiceUtil.getRole(
157                                    group.getCompanyId(), RoleConstants.ORGANIZATION_USER);
158    
159                            permissionQuery.addTerm(
160                                    Field.GROUP_ROLE_ID,
161                                    group.getGroupId() + StringPool.DASH +
162                                            organizationUserRole.getRoleId());
163                    }
164    
165                    if (group.isSite()) {
166                            Role siteMemberRole = RoleLocalServiceUtil.getRole(
167                                    group.getCompanyId(), RoleConstants.SITE_MEMBER);
168    
169                            permissionQuery.addTerm(
170                                    Field.GROUP_ROLE_ID,
171                                    group.getGroupId() + StringPool.DASH +
172                                            siteMemberRole.getRoleId());
173                    }
174            }
175    
176            protected void doAddPermissionFields_5(
177                            long companyId, long groupId, String className, String classPK,
178                            Document document)
179                    throws Exception {
180    
181                    Resource resource = ResourceLocalServiceUtil.getResource(
182                            companyId, className, ResourceConstants.SCOPE_INDIVIDUAL,
183                            classPK);
184    
185                    Group group = null;
186    
187                    if (groupId > 0) {
188                            group = GroupLocalServiceUtil.getGroup(groupId);
189                    }
190    
191                    List<Role> roles = ResourceActionsUtil.getRoles(
192                            companyId, group, className, null);
193    
194                    List<Long> roleIds = new ArrayList<Long>();
195                    List<String> groupRoleIds = new ArrayList<String>();
196    
197                    for (Role role : roles) {
198                            long roleId = role.getRoleId();
199    
200                            if (hasPermission(roleId, resource.getResourceId())) {
201                                    if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
202                                            (role.getType() == RoleConstants.TYPE_SITE)) {
203    
204                                            groupRoleIds.add(groupId + StringPool.DASH + roleId);
205                                    }
206                                    else {
207                                            roleIds.add(roleId);
208                                    }
209                            }
210                    }
211    
212                    document.addKeyword(
213                            Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()]));
214                    document.addKeyword(
215                            Field.GROUP_ROLE_ID,
216                            groupRoleIds.toArray(new String[groupRoleIds.size()]));
217            }
218    
219            protected void doAddPermissionFields_6(
220                            long companyId, long groupId, String className, String classPK,
221                            Document doc)
222                    throws Exception {
223    
224                    Group group = null;
225    
226                    if (groupId > 0) {
227                            group = GroupLocalServiceUtil.getGroup(groupId);
228                    }
229    
230                    List<Role> roles = ResourceActionsUtil.getRoles(
231                            companyId, group, className, null);
232    
233                    List<Long> roleIds = new ArrayList<Long>();
234                    List<String> groupRoleIds = new ArrayList<String>();
235    
236                    for (Role role : roles) {
237                            long roleId = role.getRoleId();
238    
239                            if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
240                                            companyId, className, ResourceConstants.SCOPE_INDIVIDUAL,
241                                            classPK, roleId, ActionKeys.VIEW)) {
242    
243                                    if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
244                                            (role.getType() == RoleConstants.TYPE_SITE)) {
245    
246                                            groupRoleIds.add(groupId + StringPool.DASH + roleId);
247                                    }
248                                    else {
249                                            roleIds.add(roleId);
250                                    }
251                            }
252                    }
253    
254                    doc.addKeyword(
255                            Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()]));
256                    doc.addKeyword(
257                            Field.GROUP_ROLE_ID,
258                            groupRoleIds.toArray(new String[groupRoleIds.size()]));
259            }
260    
261            protected Query doGetPermissionQuery(
262                            long companyId, long[] groupIds, long userId, String className,
263                            Query query, SearchContext searchContext)
264                    throws Exception {
265    
266                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 5) &&
267                            (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6)) {
268    
269                            return query;
270                    }
271    
272                    PermissionChecker permissionChecker =
273                            PermissionThreadLocal.getPermissionChecker();
274    
275                    AdvancedPermissionChecker advancedPermissionChecker = null;
276    
277                    if ((permissionChecker != null) &&
278                            (permissionChecker instanceof AdvancedPermissionChecker)) {
279    
280                            advancedPermissionChecker =
281                                    (AdvancedPermissionChecker)permissionChecker;
282                    }
283    
284                    if (advancedPermissionChecker == null) {
285                            return query;
286                    }
287    
288                    PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag(
289                            advancedPermissionChecker, userId);
290    
291                    if (permissionCheckerBag == null) {
292                            return query;
293                    }
294    
295                    List<Group> groups = new UniqueList<Group>();
296                    List<Role> roles = new UniqueList<Role>();
297                    List<UserGroupRole> userGroupRoles =
298                            new UniqueList<UserGroupRole>();
299                    Map<Long, List<Role>> groupIdsToRoles =
300                            new HashMap<Long, List<Role>>();
301    
302                    roles.addAll(permissionCheckerBag.getRoles());
303    
304                    if ((groupIds == null) || (groupIds.length == 0)) {
305                            groups.addAll(GroupLocalServiceUtil.getUserGroups(userId, true));
306                            groups.addAll(permissionCheckerBag.getGroups());
307    
308                            userGroupRoles =
309                                    UserGroupRoleLocalServiceUtil.getUserGroupRoles(userId);
310                    }
311                    else {
312                            groups.addAll(permissionCheckerBag.getGroups());
313    
314                            for (long groupId : groupIds) {
315                                    if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
316                                            Group group = GroupLocalServiceUtil.getGroup(groupId);
317    
318                                            groups.add(group);
319                                    }
320    
321                                    userGroupRoles.addAll(
322                                            UserGroupRoleLocalServiceUtil.getUserGroupRoles(
323                                                    userId, groupId));
324                                    userGroupRoles.addAll(
325                                            UserGroupRoleLocalServiceUtil.
326                                                    getUserGroupRolesByUserUserGroupAndGroup(
327                                                            userId, groupId));
328                            }
329                    }
330    
331                    if (advancedPermissionChecker.isSignedIn()) {
332                            roles.add(
333                                    RoleLocalServiceUtil.getRole(
334                                            companyId, RoleConstants.GUEST));
335                    }
336    
337                    for (Group group : groups) {
338                            PermissionCheckerBag userBag = advancedPermissionChecker.getUserBag(
339                                    userId, group.getGroupId());
340    
341                            List<Role> groupRoles = userBag.getRoles();
342    
343                            groupIdsToRoles.put(group.getGroupId(), groupRoles);
344    
345                            roles.addAll(groupRoles);
346                    }
347    
348                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
349                            return doGetPermissionQuery_5(
350                                    companyId, groupIds, userId, className, query, searchContext,
351                                    advancedPermissionChecker, groups, roles, userGroupRoles,
352                                    groupIdsToRoles);
353                    }
354                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
355                            return doGetPermissionQuery_6(
356                                    companyId, groupIds, userId, className, query, searchContext,
357                                    advancedPermissionChecker, groups, roles, userGroupRoles,
358                                    groupIdsToRoles);
359                    }
360    
361                    return query;
362            }
363    
364            protected Query doGetPermissionQuery_5(
365                            long companyId, long[] groupIds, long userId, String className,
366                            Query query, SearchContext searchContext,
367                            AdvancedPermissionChecker advancedPermissionChecker,
368                            List<Group> groups, List<Role> roles,
369                            List<UserGroupRole> userGroupRoles,
370                            Map<Long, List<Role>> groupIdsToRoles)
371                    throws Exception {
372    
373                    long companyResourceId = 0;
374    
375                    try {
376                            Resource companyResource = ResourceLocalServiceUtil.getResource(
377                                    companyId, className, ResourceConstants.SCOPE_COMPANY,
378                                    String.valueOf(companyId));
379    
380                            companyResourceId = companyResource.getResourceId();
381                    }
382                    catch (NoSuchResourceException nsre) {
383                    }
384    
385                    long groupTemplateResourceId = 0;
386    
387                    try {
388                            Resource groupTemplateResource =
389                                    ResourceLocalServiceUtil.getResource(
390                                            companyId, className,
391                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
392                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID));
393    
394                            groupTemplateResourceId = groupTemplateResource.getResourceId();
395                    }
396                    catch (NoSuchResourceException nsre) {
397                    }
398    
399                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
400                            searchContext);
401    
402                    if (userId > 0) {
403                            permissionQuery.addTerm(Field.USER_ID, userId);
404                    }
405    
406                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
407                            searchContext);
408                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(
409                            searchContext);
410    
411                    for (Role role : roles) {
412                            String roleName = role.getName();
413    
414                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
415                                    return query;
416                            }
417    
418                            if (hasPermission(role.getRoleId(), companyResourceId)) {
419                                    return query;
420                            }
421    
422                            if (hasPermission(role.getRoleId(), groupTemplateResourceId)) {
423                                    return query;
424                            }
425    
426                            for (Group group : groups) {
427                                    try {
428                                            Resource groupResource =
429                                                    ResourceLocalServiceUtil.getResource(
430                                                            companyId, className, ResourceConstants.SCOPE_GROUP,
431                                                            String.valueOf(group.getGroupId()));
432    
433                                            if (hasPermission(
434                                                            role.getRoleId(), groupResource.getResourceId())) {
435    
436                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
437                                            }
438                                    }
439                                    catch (NoSuchResourceException nsre) {
440                                    }
441    
442                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
443                                            hasPermission(role.getRoleId(), groupTemplateResourceId)) {
444    
445                                            List<Role> groupRoles = groupIdsToRoles.get(
446                                                    group.getGroupId());
447    
448                                            if (groupRoles.contains(role)) {
449                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
450                                            }
451                                    }
452                            }
453    
454                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
455                    }
456    
457                    for (Group group : groups) {
458                            addRequiredMemberRole(group, rolesQuery);
459                    }
460    
461                    for (UserGroupRole userGroupRole : userGroupRoles) {
462                            rolesQuery.addTerm(
463                                    Field.GROUP_ROLE_ID,
464                                    userGroupRole.getGroupId() + StringPool.DASH +
465                                            userGroupRole.getRoleId());
466                    }
467    
468                    if (!groupsQuery.clauses().isEmpty()) {
469                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
470                    }
471    
472                    if (!rolesQuery.clauses().isEmpty()) {
473                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
474                    }
475    
476                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
477    
478                    fullQuery.add(query, BooleanClauseOccur.MUST);
479                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
480    
481                    return fullQuery;
482            }
483    
484            protected Query doGetPermissionQuery_6(
485                            long companyId, long[] groupIds, long userId, String className,
486                            Query query, SearchContext searchContext,
487                            AdvancedPermissionChecker advancedPermissionChecker,
488                            List<Group> groups, List<Role> roles,
489                            List<UserGroupRole> userGroupRoles,
490                            Map<Long, List<Role>> groupIdsToRoles)
491                    throws Exception {
492    
493                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
494                            searchContext);
495    
496                    if (userId > 0) {
497                            permissionQuery.addTerm(Field.USER_ID, userId);
498                    }
499    
500                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
501                            searchContext);
502                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(
503                            searchContext);
504    
505                    for (Role role : roles) {
506                            String roleName = role.getName();
507    
508                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
509                                    return query;
510                            }
511    
512                            if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
513                                            companyId, className, ResourceConstants.SCOPE_COMPANY,
514                                            String.valueOf(companyId), role.getRoleId(),
515                                            ActionKeys.VIEW)) {
516    
517                                    return query;
518                            }
519    
520                            if ((role.getType() == RoleConstants.TYPE_REGULAR) &&
521                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
522                                            companyId, className,
523                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
524                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
525                                            role.getRoleId(), ActionKeys.VIEW)) {
526    
527                                    return query;
528                            }
529    
530                            for (Group group : groups) {
531                                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
532                                                    companyId, className, ResourceConstants.SCOPE_GROUP,
533                                                    String.valueOf(group.getGroupId()), role.getRoleId(),
534                                                    ActionKeys.VIEW)) {
535    
536                                            groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
537                                    }
538    
539                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
540                                            ResourcePermissionLocalServiceUtil.hasResourcePermission(
541                                                    companyId, className,
542                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE,
543                                                    String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
544                                                    role.getRoleId(), ActionKeys.VIEW)) {
545    
546                                            List<Role> groupRoles = groupIdsToRoles.get(
547                                                    group.getGroupId());
548    
549                                            if (groupRoles.contains(role)) {
550                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
551                                            }
552                                    }
553                            }
554    
555                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
556                    }
557    
558                    for (Group group : groups) {
559                            addRequiredMemberRole(group, rolesQuery);
560                    }
561    
562                    for (UserGroupRole userGroupRole : userGroupRoles) {
563                            rolesQuery.addTerm(
564                                    Field.GROUP_ROLE_ID,
565                                    userGroupRole.getGroupId() + StringPool.DASH +
566                                            userGroupRole.getRoleId());
567                    }
568    
569                    if (!groupsQuery.clauses().isEmpty()) {
570                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
571                    }
572    
573                    if (!rolesQuery.clauses().isEmpty()) {
574                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
575                    }
576    
577                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
578    
579                    fullQuery.add(query, BooleanClauseOccur.MUST);
580                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
581    
582                    return fullQuery;
583            }
584    
585            protected void doUpdatePermissionFields_5(long resourceId)
586                    throws Exception {
587    
588                    Resource resource = ResourceLocalServiceUtil.getResource(resourceId);
589    
590                    Indexer indexer = IndexerRegistryUtil.getIndexer(resource.getName());
591    
592                    if (indexer != null) {
593                            indexer.reindex(
594                                    resource.getName(), GetterUtil.getLong(resource.getPrimKey()));
595                    }
596            }
597    
598            protected void doUpdatePermissionFields_6(
599                            String resourceName, String resourceClassPK)
600                    throws Exception {
601    
602                    Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName);
603    
604                    if (indexer != null) {
605                            indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK));
606                    }
607            }
608    
609            protected PermissionCheckerBag getPermissionCheckerBag(
610                            AdvancedPermissionChecker advancedPermissionChecker, long userId)
611                    throws Exception {
612    
613                    if (!advancedPermissionChecker.isSignedIn()) {
614                            return advancedPermissionChecker.getGuestUserBag();
615                    }
616                    else {
617                            return advancedPermissionChecker.getUserBag(userId, 0);
618                    }
619            }
620    
621            protected boolean hasPermission(long roleId, long resourceId)
622                    throws SystemException {
623    
624                    if (resourceId == 0) {
625                            return false;
626                    }
627    
628                    List<Permission> permissions =
629                            PermissionLocalServiceUtil.getRolePermissions(roleId, resourceId);
630    
631                    List<String> actions = ResourceActionsUtil.getActions(permissions);
632    
633                    if (actions.contains(ActionKeys.VIEW)) {
634                            return true;
635                    }
636                    else {
637                            return false;
638                    }
639            }
640    
641            private static Log _log = LogFactoryUtil.getLog(
642                    SearchPermissionCheckerImpl.class);
643    
644    }