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