001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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.isPermissionAware()) {
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                    long[] roleIdsArray = new long[roles.size()];
234    
235                    for (int i = 0; i < roleIdsArray.length; i++) {
236                            Role role = roles.get(i);
237    
238                            roleIdsArray[i] = role.getRoleId();
239                    }
240    
241                    boolean[] hasResourcePermissions =
242                            ResourcePermissionLocalServiceUtil.hasResourcePermissions(
243                                    companyId, className, ResourceConstants.SCOPE_INDIVIDUAL,
244                                    classPK, roleIdsArray, ActionKeys.VIEW);
245    
246                    List<Long> roleIds = new ArrayList<Long>();
247                    List<String> groupRoleIds = new ArrayList<String>();
248    
249                    for (int i = 0; i < hasResourcePermissions.length; i++) {
250                            if (!hasResourcePermissions[i]) {
251                                    continue;
252                            }
253    
254                            Role role = roles.get(i);
255    
256                            if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
257                                    (role.getType() == RoleConstants.TYPE_SITE)) {
258    
259                                    groupRoleIds.add(groupId + StringPool.DASH + role.getRoleId());
260                            }
261                            else {
262                                    roleIds.add(role.getRoleId());
263                            }
264                    }
265    
266                    doc.addKeyword(
267                            Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()]));
268                    doc.addKeyword(
269                            Field.GROUP_ROLE_ID,
270                            groupRoleIds.toArray(new String[groupRoleIds.size()]));
271            }
272    
273            protected Query doGetPermissionQuery(
274                            long companyId, long[] groupIds, long userId, String className,
275                            Query query, SearchContext searchContext)
276                    throws Exception {
277    
278                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 5) &&
279                            (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6)) {
280    
281                            return query;
282                    }
283    
284                    PermissionChecker permissionChecker =
285                            PermissionThreadLocal.getPermissionChecker();
286    
287                    AdvancedPermissionChecker advancedPermissionChecker = null;
288    
289                    if ((permissionChecker != null) &&
290                            (permissionChecker instanceof AdvancedPermissionChecker)) {
291    
292                            advancedPermissionChecker =
293                                    (AdvancedPermissionChecker)permissionChecker;
294                    }
295    
296                    if (advancedPermissionChecker == null) {
297                            return query;
298                    }
299    
300                    PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag(
301                            advancedPermissionChecker, userId);
302    
303                    if (permissionCheckerBag == null) {
304                            return query;
305                    }
306    
307                    List<Group> groups = new UniqueList<Group>();
308                    List<Role> roles = new UniqueList<Role>();
309                    List<UserGroupRole> userGroupRoles = new UniqueList<UserGroupRole>();
310                    Map<Long, List<Role>> groupIdsToRoles = new HashMap<Long, List<Role>>();
311    
312                    roles.addAll(permissionCheckerBag.getRoles());
313    
314                    if ((groupIds == null) || (groupIds.length == 0)) {
315                            groups.addAll(GroupLocalServiceUtil.getUserGroups(userId, true));
316                            groups.addAll(permissionCheckerBag.getGroups());
317    
318                            userGroupRoles =
319                                    UserGroupRoleLocalServiceUtil.getUserGroupRoles(userId);
320                    }
321                    else {
322                            groups.addAll(permissionCheckerBag.getGroups());
323    
324                            for (long groupId : groupIds) {
325                                    if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
326                                            Group group = GroupLocalServiceUtil.getGroup(groupId);
327    
328                                            groups.add(group);
329                                    }
330    
331                                    userGroupRoles.addAll(
332                                            UserGroupRoleLocalServiceUtil.getUserGroupRoles(
333                                                    userId, groupId));
334                                    userGroupRoles.addAll(
335                                            UserGroupRoleLocalServiceUtil.
336                                                    getUserGroupRolesByUserUserGroupAndGroup(
337                                                            userId, groupId));
338                            }
339                    }
340    
341                    if (advancedPermissionChecker.isSignedIn()) {
342                            roles.add(
343                                    RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST));
344                    }
345    
346                    for (Group group : groups) {
347                            PermissionCheckerBag userBag = advancedPermissionChecker.getUserBag(
348                                    userId, group.getGroupId());
349    
350                            List<Role> groupRoles = userBag.getRoles();
351    
352                            groupIdsToRoles.put(group.getGroupId(), groupRoles);
353    
354                            roles.addAll(groupRoles);
355                    }
356    
357                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
358                            return doGetPermissionQuery_5(
359                                    companyId, groupIds, userId, className, query, searchContext,
360                                    advancedPermissionChecker, groups, roles, userGroupRoles,
361                                    groupIdsToRoles);
362                    }
363                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
364                            return doGetPermissionQuery_6(
365                                    companyId, groupIds, userId, className, query, searchContext,
366                                    advancedPermissionChecker, groups, roles, userGroupRoles,
367                                    groupIdsToRoles);
368                    }
369    
370                    return query;
371            }
372    
373            protected Query doGetPermissionQuery_5(
374                            long companyId, long[] groupIds, long userId, String className,
375                            Query query, SearchContext searchContext,
376                            AdvancedPermissionChecker advancedPermissionChecker,
377                            List<Group> groups, List<Role> roles,
378                            List<UserGroupRole> userGroupRoles,
379                            Map<Long, List<Role>> groupIdsToRoles)
380                    throws Exception {
381    
382                    long companyResourceId = 0;
383    
384                    try {
385                            Resource companyResource = ResourceLocalServiceUtil.getResource(
386                                    companyId, className, ResourceConstants.SCOPE_COMPANY,
387                                    String.valueOf(companyId));
388    
389                            companyResourceId = companyResource.getResourceId();
390                    }
391                    catch (NoSuchResourceException nsre) {
392                    }
393    
394                    long groupTemplateResourceId = 0;
395    
396                    try {
397                            Resource groupTemplateResource =
398                                    ResourceLocalServiceUtil.getResource(
399                                            companyId, className,
400                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
401                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID));
402    
403                            groupTemplateResourceId = groupTemplateResource.getResourceId();
404                    }
405                    catch (NoSuchResourceException nsre) {
406                    }
407    
408                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
409                            searchContext);
410    
411                    if (userId > 0) {
412                            permissionQuery.addTerm(Field.USER_ID, userId);
413                    }
414    
415                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
416                            searchContext);
417                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
418    
419                    for (Role role : roles) {
420                            String roleName = role.getName();
421    
422                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
423                                    return query;
424                            }
425    
426                            if (hasPermission(role.getRoleId(), companyResourceId)) {
427                                    return query;
428                            }
429    
430                            if (hasPermission(role.getRoleId(), groupTemplateResourceId)) {
431                                    return query;
432                            }
433    
434                            for (Group group : groups) {
435                                    try {
436                                            Resource groupResource =
437                                                    ResourceLocalServiceUtil.getResource(
438                                                            companyId, className, ResourceConstants.SCOPE_GROUP,
439                                                            String.valueOf(group.getGroupId()));
440    
441                                            if (hasPermission(
442                                                            role.getRoleId(), groupResource.getResourceId())) {
443    
444                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
445                                            }
446                                    }
447                                    catch (NoSuchResourceException nsre) {
448                                    }
449    
450                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
451                                            hasPermission(role.getRoleId(), groupTemplateResourceId)) {
452    
453                                            List<Role> groupRoles = groupIdsToRoles.get(
454                                                    group.getGroupId());
455    
456                                            if (groupRoles.contains(role)) {
457                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
458                                            }
459                                    }
460                            }
461    
462                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
463                    }
464    
465                    for (Group group : groups) {
466                            addRequiredMemberRole(group, rolesQuery);
467                    }
468    
469                    for (UserGroupRole userGroupRole : userGroupRoles) {
470                            rolesQuery.addTerm(
471                                    Field.GROUP_ROLE_ID,
472                                    userGroupRole.getGroupId() + StringPool.DASH +
473                                            userGroupRole.getRoleId());
474                    }
475    
476                    if (groupsQuery.hasClauses()) {
477                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
478                    }
479    
480                    if (rolesQuery.hasClauses()) {
481                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
482                    }
483    
484                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
485    
486                    fullQuery.add(query, BooleanClauseOccur.MUST);
487                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
488    
489                    return fullQuery;
490            }
491    
492            protected Query doGetPermissionQuery_6(
493                            long companyId, long[] groupIds, long userId, String className,
494                            Query query, SearchContext searchContext,
495                            AdvancedPermissionChecker advancedPermissionChecker,
496                            List<Group> groups, List<Role> roles,
497                            List<UserGroupRole> userGroupRoles,
498                            Map<Long, List<Role>> groupIdsToRoles)
499                    throws Exception {
500    
501                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
502                            searchContext);
503    
504                    if (userId > 0) {
505                            permissionQuery.addTerm(Field.USER_ID, userId);
506                    }
507    
508                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
509                            searchContext);
510                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
511    
512                    for (Role role : roles) {
513                            String roleName = role.getName();
514    
515                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
516                                    return query;
517                            }
518    
519                            if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
520                                            companyId, className, ResourceConstants.SCOPE_COMPANY,
521                                            String.valueOf(companyId), role.getRoleId(),
522                                            ActionKeys.VIEW)) {
523    
524                                    return query;
525                            }
526    
527                            if ((role.getType() == RoleConstants.TYPE_REGULAR) &&
528                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
529                                            companyId, className,
530                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
531                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
532                                            role.getRoleId(), ActionKeys.VIEW)) {
533    
534                                    return query;
535                            }
536    
537                            for (Group group : groups) {
538                                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
539                                                    companyId, className, ResourceConstants.SCOPE_GROUP,
540                                                    String.valueOf(group.getGroupId()), role.getRoleId(),
541                                                    ActionKeys.VIEW)) {
542    
543                                            groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
544                                    }
545    
546                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
547                                            ResourcePermissionLocalServiceUtil.hasResourcePermission(
548                                                    companyId, className,
549                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE,
550                                                    String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
551                                                    role.getRoleId(), ActionKeys.VIEW)) {
552    
553                                            List<Role> groupRoles = groupIdsToRoles.get(
554                                                    group.getGroupId());
555    
556                                            if (groupRoles.contains(role)) {
557                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
558                                            }
559                                    }
560                            }
561    
562                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
563                    }
564    
565                    for (Group group : groups) {
566                            addRequiredMemberRole(group, rolesQuery);
567                    }
568    
569                    for (UserGroupRole userGroupRole : userGroupRoles) {
570                            rolesQuery.addTerm(
571                                    Field.GROUP_ROLE_ID,
572                                    userGroupRole.getGroupId() + StringPool.DASH +
573                                            userGroupRole.getRoleId());
574                    }
575    
576                    if (groupsQuery.hasClauses()) {
577                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
578                    }
579    
580                    if (rolesQuery.hasClauses()) {
581                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
582                    }
583    
584                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
585    
586                    fullQuery.add(query, BooleanClauseOccur.MUST);
587                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
588    
589                    return fullQuery;
590            }
591    
592            protected void doUpdatePermissionFields_5(long resourceId)
593                    throws Exception {
594    
595                    Resource resource = ResourceLocalServiceUtil.getResource(resourceId);
596    
597                    Indexer indexer = IndexerRegistryUtil.getIndexer(resource.getName());
598    
599                    if (indexer != null) {
600                            indexer.reindex(
601                                    resource.getName(), GetterUtil.getLong(resource.getPrimKey()));
602                    }
603            }
604    
605            protected void doUpdatePermissionFields_6(
606                            String resourceName, String resourceClassPK)
607                    throws Exception {
608    
609                    Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName);
610    
611                    if (indexer != null) {
612                            indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK));
613                    }
614            }
615    
616            protected PermissionCheckerBag getPermissionCheckerBag(
617                            AdvancedPermissionChecker advancedPermissionChecker, long userId)
618                    throws Exception {
619    
620                    if (!advancedPermissionChecker.isSignedIn()) {
621                            return advancedPermissionChecker.getGuestUserBag();
622                    }
623                    else {
624                            return advancedPermissionChecker.getUserBag(userId, 0);
625                    }
626            }
627    
628            protected boolean hasPermission(long roleId, long resourceId)
629                    throws SystemException {
630    
631                    if (resourceId == 0) {
632                            return false;
633                    }
634    
635                    List<Permission> permissions =
636                            PermissionLocalServiceUtil.getRolePermissions(roleId, resourceId);
637    
638                    List<String> actions = ResourceActionsUtil.getActions(permissions);
639    
640                    if (actions.contains(ActionKeys.VIEW)) {
641                            return true;
642                    }
643                    else {
644                            return false;
645                    }
646            }
647    
648            private static Log _log = LogFactoryUtil.getLog(
649                    SearchPermissionCheckerImpl.class);
650    
651    }