001    /**
002     * Copyright (c) 2000-2012 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                    Indexer indexer = IndexerRegistryUtil.getIndexer(className);
285    
286                    if (!indexer.isFilterSearch()) {
287                            return query;
288                    }
289    
290                    PermissionChecker permissionChecker =
291                            PermissionThreadLocal.getPermissionChecker();
292    
293                    AdvancedPermissionChecker advancedPermissionChecker = null;
294    
295                    if ((permissionChecker != null) &&
296                            (permissionChecker instanceof AdvancedPermissionChecker)) {
297    
298                            advancedPermissionChecker =
299                                    (AdvancedPermissionChecker)permissionChecker;
300                    }
301    
302                    if (advancedPermissionChecker == null) {
303                            return query;
304                    }
305    
306                    PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag(
307                            advancedPermissionChecker, userId);
308    
309                    if (permissionCheckerBag == null) {
310                            return query;
311                    }
312    
313                    List<Group> groups = new UniqueList<Group>();
314                    List<Role> roles = new UniqueList<Role>();
315                    List<UserGroupRole> userGroupRoles = new UniqueList<UserGroupRole>();
316                    Map<Long, List<Role>> groupIdsToRoles = new HashMap<Long, List<Role>>();
317    
318                    roles.addAll(permissionCheckerBag.getRoles());
319    
320                    if ((groupIds == null) || (groupIds.length == 0)) {
321                            groups.addAll(GroupLocalServiceUtil.getUserGroups(userId, true));
322                            groups.addAll(permissionCheckerBag.getGroups());
323    
324                            userGroupRoles =
325                                    UserGroupRoleLocalServiceUtil.getUserGroupRoles(userId);
326                    }
327                    else {
328                            groups.addAll(permissionCheckerBag.getGroups());
329    
330                            for (long groupId : groupIds) {
331                                    if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
332                                            Group group = GroupLocalServiceUtil.getGroup(groupId);
333    
334                                            groups.add(group);
335                                    }
336    
337                                    userGroupRoles.addAll(
338                                            UserGroupRoleLocalServiceUtil.getUserGroupRoles(
339                                                    userId, groupId));
340                                    userGroupRoles.addAll(
341                                            UserGroupRoleLocalServiceUtil.
342                                                    getUserGroupRolesByUserUserGroupAndGroup(
343                                                            userId, groupId));
344                            }
345                    }
346    
347                    if (advancedPermissionChecker.isSignedIn()) {
348                            roles.add(
349                                    RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST));
350                    }
351    
352                    for (Group group : groups) {
353                            PermissionCheckerBag userBag = advancedPermissionChecker.getUserBag(
354                                    userId, group.getGroupId());
355    
356                            List<Role> groupRoles = userBag.getRoles();
357    
358                            groupIdsToRoles.put(group.getGroupId(), groupRoles);
359    
360                            roles.addAll(groupRoles);
361                    }
362    
363                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
364                            return doGetPermissionQuery_5(
365                                    companyId, groupIds, userId, className, query, searchContext,
366                                    advancedPermissionChecker, groups, roles, userGroupRoles,
367                                    groupIdsToRoles);
368                    }
369                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
370                            return doGetPermissionQuery_6(
371                                    companyId, groupIds, userId, className, query, searchContext,
372                                    advancedPermissionChecker, groups, roles, userGroupRoles,
373                                    groupIdsToRoles);
374                    }
375    
376                    return query;
377            }
378    
379            protected Query doGetPermissionQuery_5(
380                            long companyId, long[] groupIds, long userId, String className,
381                            Query query, SearchContext searchContext,
382                            AdvancedPermissionChecker advancedPermissionChecker,
383                            List<Group> groups, List<Role> roles,
384                            List<UserGroupRole> userGroupRoles,
385                            Map<Long, List<Role>> groupIdsToRoles)
386                    throws Exception {
387    
388                    long companyResourceId = 0;
389    
390                    try {
391                            Resource companyResource = ResourceLocalServiceUtil.getResource(
392                                    companyId, className, ResourceConstants.SCOPE_COMPANY,
393                                    String.valueOf(companyId));
394    
395                            companyResourceId = companyResource.getResourceId();
396                    }
397                    catch (NoSuchResourceException nsre) {
398                    }
399    
400                    long groupTemplateResourceId = 0;
401    
402                    try {
403                            Resource groupTemplateResource =
404                                    ResourceLocalServiceUtil.getResource(
405                                            companyId, className,
406                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
407                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID));
408    
409                            groupTemplateResourceId = groupTemplateResource.getResourceId();
410                    }
411                    catch (NoSuchResourceException nsre) {
412                    }
413    
414                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
415                            searchContext);
416    
417                    if (userId > 0) {
418                            permissionQuery.addTerm(Field.USER_ID, userId);
419                    }
420    
421                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
422                            searchContext);
423                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
424    
425                    for (Role role : roles) {
426                            String roleName = role.getName();
427    
428                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
429                                    return query;
430                            }
431    
432                            if (hasPermission(role.getRoleId(), companyResourceId)) {
433                                    return query;
434                            }
435    
436                            if (hasPermission(role.getRoleId(), groupTemplateResourceId)) {
437                                    return query;
438                            }
439    
440                            for (Group group : groups) {
441                                    try {
442                                            Resource groupResource =
443                                                    ResourceLocalServiceUtil.getResource(
444                                                            companyId, className, ResourceConstants.SCOPE_GROUP,
445                                                            String.valueOf(group.getGroupId()));
446    
447                                            if (hasPermission(
448                                                            role.getRoleId(), groupResource.getResourceId())) {
449    
450                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
451                                            }
452                                    }
453                                    catch (NoSuchResourceException nsre) {
454                                    }
455    
456                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
457                                            hasPermission(role.getRoleId(), groupTemplateResourceId)) {
458    
459                                            List<Role> groupRoles = groupIdsToRoles.get(
460                                                    group.getGroupId());
461    
462                                            if (groupRoles.contains(role)) {
463                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
464                                            }
465                                    }
466                            }
467    
468                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
469                    }
470    
471                    for (Group group : groups) {
472                            addRequiredMemberRole(group, rolesQuery);
473                    }
474    
475                    for (UserGroupRole userGroupRole : userGroupRoles) {
476                            rolesQuery.addTerm(
477                                    Field.GROUP_ROLE_ID,
478                                    userGroupRole.getGroupId() + StringPool.DASH +
479                                            userGroupRole.getRoleId());
480                    }
481    
482                    if (groupsQuery.hasClauses()) {
483                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
484                    }
485    
486                    if (rolesQuery.hasClauses()) {
487                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
488                    }
489    
490                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
491    
492                    fullQuery.add(query, BooleanClauseOccur.MUST);
493                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
494    
495                    return fullQuery;
496            }
497    
498            protected Query doGetPermissionQuery_6(
499                            long companyId, long[] groupIds, long userId, String className,
500                            Query query, SearchContext searchContext,
501                            AdvancedPermissionChecker advancedPermissionChecker,
502                            List<Group> groups, List<Role> roles,
503                            List<UserGroupRole> userGroupRoles,
504                            Map<Long, List<Role>> groupIdsToRoles)
505                    throws Exception {
506    
507                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
508                            searchContext);
509    
510                    if (userId > 0) {
511                            permissionQuery.addTerm(Field.USER_ID, userId);
512                    }
513    
514                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
515                            searchContext);
516                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
517    
518                    for (Role role : roles) {
519                            String roleName = role.getName();
520    
521                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
522                                    return query;
523                            }
524    
525                            if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
526                                            companyId, className, ResourceConstants.SCOPE_COMPANY,
527                                            String.valueOf(companyId), role.getRoleId(),
528                                            ActionKeys.VIEW)) {
529    
530                                    return query;
531                            }
532    
533                            if ((role.getType() == RoleConstants.TYPE_REGULAR) &&
534                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
535                                            companyId, className,
536                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
537                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
538                                            role.getRoleId(), ActionKeys.VIEW)) {
539    
540                                    return query;
541                            }
542    
543                            for (Group group : groups) {
544                                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
545                                                    companyId, className, ResourceConstants.SCOPE_GROUP,
546                                                    String.valueOf(group.getGroupId()), role.getRoleId(),
547                                                    ActionKeys.VIEW)) {
548    
549                                            groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
550                                    }
551    
552                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
553                                            ResourcePermissionLocalServiceUtil.hasResourcePermission(
554                                                    companyId, className,
555                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE,
556                                                    String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
557                                                    role.getRoleId(), ActionKeys.VIEW)) {
558    
559                                            List<Role> groupRoles = groupIdsToRoles.get(
560                                                    group.getGroupId());
561    
562                                            if (groupRoles.contains(role)) {
563                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
564                                            }
565                                    }
566                            }
567    
568                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
569                    }
570    
571                    for (Group group : groups) {
572                            addRequiredMemberRole(group, rolesQuery);
573                    }
574    
575                    for (UserGroupRole userGroupRole : userGroupRoles) {
576                            rolesQuery.addTerm(
577                                    Field.GROUP_ROLE_ID,
578                                    userGroupRole.getGroupId() + StringPool.DASH +
579                                            userGroupRole.getRoleId());
580                    }
581    
582                    if (groupsQuery.hasClauses()) {
583                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
584                    }
585    
586                    if (rolesQuery.hasClauses()) {
587                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
588                    }
589    
590                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
591    
592                    fullQuery.add(query, BooleanClauseOccur.MUST);
593                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
594    
595                    return fullQuery;
596            }
597    
598            protected void doUpdatePermissionFields_5(long resourceId)
599                    throws Exception {
600    
601                    Resource resource = ResourceLocalServiceUtil.getResource(resourceId);
602    
603                    Indexer indexer = IndexerRegistryUtil.getIndexer(resource.getName());
604    
605                    if (indexer != null) {
606                            indexer.reindex(
607                                    resource.getName(), GetterUtil.getLong(resource.getPrimKey()));
608                    }
609            }
610    
611            protected void doUpdatePermissionFields_6(
612                            String resourceName, String resourceClassPK)
613                    throws Exception {
614    
615                    Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName);
616    
617                    if (indexer != null) {
618                            indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK));
619                    }
620            }
621    
622            protected PermissionCheckerBag getPermissionCheckerBag(
623                            AdvancedPermissionChecker advancedPermissionChecker, long userId)
624                    throws Exception {
625    
626                    if (!advancedPermissionChecker.isSignedIn()) {
627                            return advancedPermissionChecker.getGuestUserBag();
628                    }
629                    else {
630                            return advancedPermissionChecker.getUserBag(userId, 0);
631                    }
632            }
633    
634            protected boolean hasPermission(long roleId, long resourceId)
635                    throws SystemException {
636    
637                    if (resourceId == 0) {
638                            return false;
639                    }
640    
641                    List<Permission> permissions =
642                            PermissionLocalServiceUtil.getRolePermissions(roleId, resourceId);
643    
644                    List<String> actions = ResourceActionsUtil.getActions(permissions);
645    
646                    if (actions.contains(ActionKeys.VIEW)) {
647                            return true;
648                    }
649                    else {
650                            return false;
651                    }
652            }
653    
654            private static Log _log = LogFactoryUtil.getLog(
655                    SearchPermissionCheckerImpl.class);
656    
657    }