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