001    /**
002     * Copyright (c) 2000-2013 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.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.search.BooleanClauseOccur;
021    import com.liferay.portal.kernel.search.BooleanQuery;
022    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
023    import com.liferay.portal.kernel.search.Document;
024    import com.liferay.portal.kernel.search.Field;
025    import com.liferay.portal.kernel.search.Indexer;
026    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
027    import com.liferay.portal.kernel.search.Query;
028    import com.liferay.portal.kernel.search.SearchContext;
029    import com.liferay.portal.kernel.search.SearchPermissionChecker;
030    import com.liferay.portal.kernel.util.ArrayUtil;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.ListUtil;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.UniqueList;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.model.Group;
037    import com.liferay.portal.model.GroupConstants;
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.Team;
042    import com.liferay.portal.model.UserGroupRole;
043    import com.liferay.portal.security.permission.ActionKeys;
044    import com.liferay.portal.security.permission.AdvancedPermissionChecker;
045    import com.liferay.portal.security.permission.PermissionChecker;
046    import com.liferay.portal.security.permission.PermissionCheckerBag;
047    import com.liferay.portal.security.permission.PermissionThreadLocal;
048    import com.liferay.portal.security.permission.ResourceActionsUtil;
049    import com.liferay.portal.security.permission.ResourceBlockIdsBag;
050    import com.liferay.portal.service.GroupLocalServiceUtil;
051    import com.liferay.portal.service.ResourceBlockLocalServiceUtil;
052    import com.liferay.portal.service.ResourceBlockPermissionLocalServiceUtil;
053    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
054    import com.liferay.portal.service.RoleLocalServiceUtil;
055    import com.liferay.portal.service.TeamLocalServiceUtil;
056    import com.liferay.portal.service.UserGroupRoleLocalServiceUtil;
057    import com.liferay.portal.util.PortalUtil;
058    
059    import java.util.ArrayList;
060    import java.util.HashMap;
061    import java.util.List;
062    import java.util.Map;
063    
064    /**
065     * @author Allen Chiang
066     * @author Bruno Farache
067     * @author Raymond Aug??
068     * @author Amos Fong
069     */
070    public class SearchPermissionCheckerImpl implements SearchPermissionChecker {
071    
072            @Override
073            public void addPermissionFields(long companyId, Document document) {
074                    try {
075                            long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID));
076    
077                            String className = document.get(Field.ENTRY_CLASS_NAME);
078    
079                            boolean relatedEntry = GetterUtil.getBoolean(
080                                    document.get(Field.RELATED_ENTRY));
081    
082                            if (relatedEntry) {
083                                    long classNameId = GetterUtil.getLong(
084                                            document.get(Field.CLASS_NAME_ID));
085    
086                                    className = PortalUtil.getClassName(classNameId);
087                            }
088    
089                            if (Validator.isNull(className)) {
090                                    return;
091                            }
092    
093                            String classPK = document.get(Field.ROOT_ENTRY_CLASS_PK);
094    
095                            if (Validator.isNull(classPK)) {
096                                    classPK = document.get(Field.ENTRY_CLASS_PK);
097                            }
098    
099                            if (relatedEntry) {
100                                    classPK = document.get(Field.CLASS_PK);
101                            }
102    
103                            if (Validator.isNull(classPK)) {
104                                    return;
105                            }
106    
107                            Indexer indexer = IndexerRegistryUtil.getIndexer(className);
108    
109                            if (!indexer.isPermissionAware()) {
110                                    return;
111                            }
112    
113                            doAddPermissionFields_6(
114                                    companyId, groupId, className, classPK, document);
115                    }
116                    catch (NoSuchResourceException nsre) {
117                    }
118                    catch (Exception e) {
119                            _log.error(e, e);
120                    }
121            }
122    
123            @Override
124            public Query getPermissionQuery(
125                    long companyId, long[] groupIds, long userId, String className,
126                    Query query, SearchContext searchContext) {
127    
128                    try {
129                            query = doGetPermissionQuery(
130                                    companyId, groupIds, userId, className, query, searchContext);
131                    }
132                    catch (Exception e) {
133                            _log.error(e, e);
134                    }
135    
136                    return query;
137            }
138    
139            @Override
140            public void updatePermissionFields(
141                    String resourceName, String resourceClassPK) {
142    
143                    try {
144                            doUpdatePermissionFields(resourceName, resourceClassPK);
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_6(
177                            long companyId, long groupId, String className, String classPK,
178                            Document doc)
179                    throws Exception {
180    
181                    Group group = null;
182    
183                    if (groupId > 0) {
184                            group = GroupLocalServiceUtil.getGroup(groupId);
185                    }
186    
187                    List<Role> roles = ListUtil.copy(
188                            ResourceActionsUtil.getRoles(companyId, group, className, null));
189    
190                    if (groupId > 0) {
191                            List<Team> teams = TeamLocalServiceUtil.getGroupTeams(groupId);
192    
193                            for (Team team : teams) {
194                                    Role role = RoleLocalServiceUtil.getTeamRole(
195                                            team.getCompanyId(), team.getTeamId());
196    
197                                    roles.add(role);
198                            }
199                    }
200    
201                    long[] roleIdsArray = new long[roles.size()];
202    
203                    for (int i = 0; i < roleIdsArray.length; i++) {
204                            Role role = roles.get(i);
205    
206                            roleIdsArray[i] = role.getRoleId();
207                    }
208    
209                    boolean[] hasResourcePermissions = null;
210    
211                    if (ResourceBlockLocalServiceUtil.isSupported(className)) {
212                            ResourceBlockIdsBag resourceBlockIdsBag =
213                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
214                                            companyId, groupId, className, roleIdsArray);
215    
216                            long actionId = ResourceBlockLocalServiceUtil.getActionId(
217                                    className, ActionKeys.VIEW);
218    
219                            List<Long> resourceBlockIds =
220                                    resourceBlockIdsBag.getResourceBlockIds(actionId);
221    
222                            hasResourcePermissions = new boolean[roleIdsArray.length];
223    
224                            for (long resourceBlockId : resourceBlockIds) {
225                                    for (int i = 0; i < roleIdsArray.length; i++) {
226                                            int count =
227                                                    ResourceBlockPermissionLocalServiceUtil.
228                                                            getResourceBlockPermissionsCount(
229                                                                    resourceBlockId, roleIdsArray[i]);
230    
231                                            hasResourcePermissions[i] = (count > 0);
232                                    }
233                            }
234                    }
235                    else {
236                            hasResourcePermissions =
237                                    ResourcePermissionLocalServiceUtil.hasResourcePermissions(
238                                            companyId, className, ResourceConstants.SCOPE_INDIVIDUAL,
239                                            classPK, roleIdsArray, ActionKeys.VIEW);
240                    }
241    
242                    List<Long> roleIds = new ArrayList<Long>();
243                    List<String> groupRoleIds = new ArrayList<String>();
244    
245                    for (int i = 0; i < hasResourcePermissions.length; i++) {
246                            if (!hasResourcePermissions[i]) {
247                                    continue;
248                            }
249    
250                            Role role = roles.get(i);
251    
252                            if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
253                                    (role.getType() == RoleConstants.TYPE_SITE)) {
254    
255                                    groupRoleIds.add(groupId + StringPool.DASH + role.getRoleId());
256                            }
257                            else {
258                                    roleIds.add(role.getRoleId());
259                            }
260                    }
261    
262                    doc.addKeyword(
263                            Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()]));
264                    doc.addKeyword(
265                            Field.GROUP_ROLE_ID,
266                            groupRoleIds.toArray(new String[groupRoleIds.size()]));
267            }
268    
269            protected Query doGetPermissionQuery(
270                            long companyId, long[] groupIds, long userId, String className,
271                            Query query, SearchContext searchContext)
272                    throws Exception {
273    
274                    Indexer indexer = IndexerRegistryUtil.getIndexer(className);
275    
276                    if (!indexer.isPermissionAware()) {
277                            return query;
278                    }
279    
280                    PermissionChecker permissionChecker =
281                            PermissionThreadLocal.getPermissionChecker();
282    
283                    AdvancedPermissionChecker advancedPermissionChecker = null;
284    
285                    if ((permissionChecker != null) &&
286                            (permissionChecker instanceof AdvancedPermissionChecker)) {
287    
288                            advancedPermissionChecker =
289                                    (AdvancedPermissionChecker)permissionChecker;
290                    }
291    
292                    if (advancedPermissionChecker == null) {
293                            return query;
294                    }
295    
296                    PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag(
297                            advancedPermissionChecker, userId);
298    
299                    if (permissionCheckerBag == null) {
300                            return query;
301                    }
302    
303                    List<Group> groups = new UniqueList<Group>();
304                    List<Role> roles = new UniqueList<Role>();
305                    List<UserGroupRole> userGroupRoles = new UniqueList<UserGroupRole>();
306                    Map<Long, List<Role>> groupIdsToRoles = new HashMap<Long, List<Role>>();
307    
308                    roles.addAll(permissionCheckerBag.getRoles());
309    
310                    if (ArrayUtil.isEmpty(groupIds)) {
311                            groups.addAll(GroupLocalServiceUtil.getUserGroups(userId, true));
312                            groups.addAll(permissionCheckerBag.getGroups());
313    
314                            userGroupRoles = UserGroupRoleLocalServiceUtil.getUserGroupRoles(
315                                    userId);
316                    }
317                    else {
318                            groups.addAll(permissionCheckerBag.getGroups());
319    
320                            for (long groupId : groupIds) {
321                                    if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
322                                            Group group = GroupLocalServiceUtil.getGroup(groupId);
323    
324                                            groups.add(group);
325                                    }
326    
327                                    userGroupRoles.addAll(
328                                            UserGroupRoleLocalServiceUtil.getUserGroupRoles(
329                                                    userId, groupId));
330                                    userGroupRoles.addAll(
331                                            UserGroupRoleLocalServiceUtil.
332                                                    getUserGroupRolesByUserUserGroupAndGroup(
333                                                            userId, groupId));
334                            }
335                    }
336    
337                    if (advancedPermissionChecker.isSignedIn()) {
338                            roles.add(
339                                    RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST));
340                    }
341    
342                    for (Group group : groups) {
343                            PermissionCheckerBag userBag = advancedPermissionChecker.getUserBag(
344                                    userId, group.getGroupId());
345    
346                            List<Role> groupRoles = userBag.getRoles();
347    
348                            groupIdsToRoles.put(group.getGroupId(), groupRoles);
349    
350                            roles.addAll(groupRoles);
351                    }
352    
353                    return doGetPermissionQuery_6(
354                            companyId, groupIds, userId, className, query, searchContext,
355                            advancedPermissionChecker, groups, roles, userGroupRoles,
356                            groupIdsToRoles);
357            }
358    
359            protected Query doGetPermissionQuery_6(
360                            long companyId, long[] groupIds, long userId, String className,
361                            Query query, SearchContext searchContext,
362                            AdvancedPermissionChecker advancedPermissionChecker,
363                            List<Group> groups, List<Role> roles,
364                            List<UserGroupRole> userGroupRoles,
365                            Map<Long, List<Role>> groupIdsToRoles)
366                    throws Exception {
367    
368                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
369                            searchContext);
370    
371                    if (userId > 0) {
372                            permissionQuery.addTerm(Field.USER_ID, userId);
373                    }
374    
375                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
376                            searchContext);
377                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
378    
379                    for (Role role : roles) {
380                            String roleName = role.getName();
381    
382                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
383                                    return query;
384                            }
385    
386                            if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
387                                            companyId, className, ResourceConstants.SCOPE_COMPANY,
388                                            String.valueOf(companyId), role.getRoleId(),
389                                            ActionKeys.VIEW)) {
390    
391                                    return query;
392                            }
393    
394                            if ((role.getType() == RoleConstants.TYPE_REGULAR) &&
395                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
396                                            companyId, className,
397                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
398                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
399                                            role.getRoleId(), ActionKeys.VIEW)) {
400    
401                                    return query;
402                            }
403    
404                            for (Group group : groups) {
405                                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
406                                                    companyId, className, ResourceConstants.SCOPE_GROUP,
407                                                    String.valueOf(group.getGroupId()), role.getRoleId(),
408                                                    ActionKeys.VIEW)) {
409    
410                                            groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
411                                    }
412    
413                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
414                                            ResourcePermissionLocalServiceUtil.hasResourcePermission(
415                                                    companyId, className,
416                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE,
417                                                    String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
418                                                    role.getRoleId(), ActionKeys.VIEW)) {
419    
420                                            List<Role> groupRoles = groupIdsToRoles.get(
421                                                    group.getGroupId());
422    
423                                            if (groupRoles.contains(role)) {
424                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
425                                            }
426                                    }
427    
428                                    if (group.isSite() &&
429                                            !role.getName().equals(RoleConstants.SITE_MEMBER) &&
430                                            (role.getType() == RoleConstants.TYPE_SITE)) {
431    
432                                            rolesQuery.addTerm(
433                                                    Field.GROUP_ROLE_ID,
434                                                    group.getGroupId() + StringPool.DASH +
435                                                            role.getRoleId());
436                                    }
437                            }
438    
439                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
440                    }
441    
442                    for (Group group : groups) {
443                            addRequiredMemberRole(group, rolesQuery);
444                    }
445    
446                    for (UserGroupRole userGroupRole : userGroupRoles) {
447                            rolesQuery.addTerm(
448                                    Field.GROUP_ROLE_ID,
449                                    userGroupRole.getGroupId() + StringPool.DASH +
450                                            userGroupRole.getRoleId());
451                    }
452    
453                    if (groupsQuery.hasClauses()) {
454                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
455                    }
456    
457                    if (rolesQuery.hasClauses()) {
458                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
459                    }
460    
461                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
462    
463                    fullQuery.add(query, BooleanClauseOccur.MUST);
464                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
465    
466                    return fullQuery;
467            }
468    
469            protected void doUpdatePermissionFields(
470                            String resourceName, String resourceClassPK)
471                    throws Exception {
472    
473                    Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName);
474    
475                    if (indexer != null) {
476                            indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK));
477                    }
478            }
479    
480            protected PermissionCheckerBag getPermissionCheckerBag(
481                            AdvancedPermissionChecker advancedPermissionChecker, long userId)
482                    throws Exception {
483    
484                    if (!advancedPermissionChecker.isSignedIn()) {
485                            return advancedPermissionChecker.getGuestUserBag();
486                    }
487                    else {
488                            return advancedPermissionChecker.getUserBag(userId, 0);
489                    }
490            }
491    
492            private static Log _log = LogFactoryUtil.getLog(
493                    SearchPermissionCheckerImpl.class);
494    
495    }