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