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.GetterUtil;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.UniqueList;
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.ResourceConstants;
037    import com.liferay.portal.model.Role;
038    import com.liferay.portal.model.RoleConstants;
039    import com.liferay.portal.model.Team;
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.TeamLocalServiceUtil;
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 = ResourceActionsUtil.getRoles(
186                            companyId, group, className, null);
187    
188                    if (groupId > 0) {
189                            List<Team> teams = TeamLocalServiceUtil.getGroupTeams(groupId);
190    
191                            for (Team team : teams) {
192                                    Role role = RoleLocalServiceUtil.getTeamRole(
193                                            team.getCompanyId(), team.getTeamId());
194    
195                                    roles.add(role);
196                            }
197                    }
198    
199                    long[] roleIdsArray = new long[roles.size()];
200    
201                    for (int i = 0; i < roleIdsArray.length; i++) {
202                            Role role = roles.get(i);
203    
204                            roleIdsArray[i] = role.getRoleId();
205                    }
206    
207                    boolean[] hasResourcePermissions = null;
208    
209                    if (ResourceBlockLocalServiceUtil.isSupported(className)) {
210                            ResourceBlockIdsBag resourceBlockIdsBag =
211                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
212                                            companyId, groupId, className, roleIdsArray);
213    
214                            long actionId = ResourceBlockLocalServiceUtil.getActionId(
215                                    className, ActionKeys.VIEW);
216    
217                            List<Long> resourceBlockIds =
218                                    resourceBlockIdsBag.getResourceBlockIds(actionId);
219    
220                            hasResourcePermissions = new boolean[roleIdsArray.length];
221    
222                            for (long resourceBlockId : resourceBlockIds) {
223                                    for (int i = 0; i < roleIdsArray.length; i++) {
224                                            int count =
225                                                    ResourceBlockPermissionLocalServiceUtil.
226                                                            getResourceBlockPermissionsCount(
227                                                                    resourceBlockId, roleIdsArray[i]);
228    
229                                            hasResourcePermissions[i] = (count > 0);
230                                    }
231                            }
232                    }
233                    else {
234                            hasResourcePermissions =
235                                    ResourcePermissionLocalServiceUtil.hasResourcePermissions(
236                                            companyId, className, ResourceConstants.SCOPE_INDIVIDUAL,
237                                            classPK, roleIdsArray, ActionKeys.VIEW);
238                    }
239    
240                    List<Long> roleIds = new ArrayList<Long>();
241                    List<String> groupRoleIds = new ArrayList<String>();
242    
243                    for (int i = 0; i < hasResourcePermissions.length; i++) {
244                            if (!hasResourcePermissions[i]) {
245                                    continue;
246                            }
247    
248                            Role role = roles.get(i);
249    
250                            if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
251                                    (role.getType() == RoleConstants.TYPE_SITE)) {
252    
253                                    groupRoleIds.add(groupId + StringPool.DASH + role.getRoleId());
254                            }
255                            else {
256                                    roleIds.add(role.getRoleId());
257                            }
258                    }
259    
260                    doc.addKeyword(
261                            Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()]));
262                    doc.addKeyword(
263                            Field.GROUP_ROLE_ID,
264                            groupRoleIds.toArray(new String[groupRoleIds.size()]));
265            }
266    
267            protected Query doGetPermissionQuery(
268                            long companyId, long[] groupIds, long userId, String className,
269                            Query query, SearchContext searchContext)
270                    throws Exception {
271    
272                    Indexer indexer = IndexerRegistryUtil.getIndexer(className);
273    
274                    if (!indexer.isPermissionAware()) {
275                            return query;
276                    }
277    
278                    PermissionChecker permissionChecker =
279                            PermissionThreadLocal.getPermissionChecker();
280    
281                    AdvancedPermissionChecker advancedPermissionChecker = null;
282    
283                    if ((permissionChecker != null) &&
284                            (permissionChecker instanceof AdvancedPermissionChecker)) {
285    
286                            advancedPermissionChecker =
287                                    (AdvancedPermissionChecker)permissionChecker;
288                    }
289    
290                    if (advancedPermissionChecker == null) {
291                            return query;
292                    }
293    
294                    PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag(
295                            advancedPermissionChecker, userId);
296    
297                    if (permissionCheckerBag == null) {
298                            return query;
299                    }
300    
301                    List<Group> groups = new UniqueList<Group>();
302                    List<Role> roles = new UniqueList<Role>();
303                    List<UserGroupRole> userGroupRoles = new UniqueList<UserGroupRole>();
304                    Map<Long, List<Role>> groupIdsToRoles = new HashMap<Long, List<Role>>();
305    
306                    roles.addAll(permissionCheckerBag.getRoles());
307    
308                    if ((groupIds == null) || (groupIds.length == 0)) {
309                            groups.addAll(GroupLocalServiceUtil.getUserGroups(userId, true));
310                            groups.addAll(permissionCheckerBag.getGroups());
311    
312                            userGroupRoles = UserGroupRoleLocalServiceUtil.getUserGroupRoles(
313                                    userId);
314                    }
315                    else {
316                            groups.addAll(permissionCheckerBag.getGroups());
317    
318                            for (long groupId : groupIds) {
319                                    if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
320                                            Group group = GroupLocalServiceUtil.getGroup(groupId);
321    
322                                            groups.add(group);
323                                    }
324    
325                                    userGroupRoles.addAll(
326                                            UserGroupRoleLocalServiceUtil.getUserGroupRoles(
327                                                    userId, groupId));
328                                    userGroupRoles.addAll(
329                                            UserGroupRoleLocalServiceUtil.
330                                                    getUserGroupRolesByUserUserGroupAndGroup(
331                                                            userId, groupId));
332                            }
333                    }
334    
335                    if (advancedPermissionChecker.isSignedIn()) {
336                            roles.add(
337                                    RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST));
338                    }
339    
340                    for (Group group : groups) {
341                            PermissionCheckerBag userBag = advancedPermissionChecker.getUserBag(
342                                    userId, group.getGroupId());
343    
344                            List<Role> groupRoles = userBag.getRoles();
345    
346                            groupIdsToRoles.put(group.getGroupId(), groupRoles);
347    
348                            roles.addAll(groupRoles);
349                    }
350    
351                    return doGetPermissionQuery_6(
352                            companyId, groupIds, userId, className, query, searchContext,
353                            advancedPermissionChecker, groups, roles, userGroupRoles,
354                            groupIdsToRoles);
355            }
356    
357            protected Query doGetPermissionQuery_6(
358                            long companyId, long[] groupIds, long userId, String className,
359                            Query query, SearchContext searchContext,
360                            AdvancedPermissionChecker advancedPermissionChecker,
361                            List<Group> groups, List<Role> roles,
362                            List<UserGroupRole> userGroupRoles,
363                            Map<Long, List<Role>> groupIdsToRoles)
364                    throws Exception {
365    
366                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
367                            searchContext);
368    
369                    if (userId > 0) {
370                            permissionQuery.addTerm(Field.USER_ID, userId);
371                    }
372    
373                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
374                            searchContext);
375                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
376    
377                    for (Role role : roles) {
378                            String roleName = role.getName();
379    
380                            if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
381                                    return query;
382                            }
383    
384                            if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
385                                            companyId, className, ResourceConstants.SCOPE_COMPANY,
386                                            String.valueOf(companyId), role.getRoleId(),
387                                            ActionKeys.VIEW)) {
388    
389                                    return query;
390                            }
391    
392                            if ((role.getType() == RoleConstants.TYPE_REGULAR) &&
393                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
394                                            companyId, className,
395                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
396                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
397                                            role.getRoleId(), ActionKeys.VIEW)) {
398    
399                                    return query;
400                            }
401    
402                            for (Group group : groups) {
403                                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
404                                                    companyId, className, ResourceConstants.SCOPE_GROUP,
405                                                    String.valueOf(group.getGroupId()), role.getRoleId(),
406                                                    ActionKeys.VIEW)) {
407    
408                                            groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
409                                    }
410    
411                                    if ((role.getType() != RoleConstants.TYPE_REGULAR) &&
412                                            ResourcePermissionLocalServiceUtil.hasResourcePermission(
413                                                    companyId, className,
414                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE,
415                                                    String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
416                                                    role.getRoleId(), ActionKeys.VIEW)) {
417    
418                                            List<Role> groupRoles = groupIdsToRoles.get(
419                                                    group.getGroupId());
420    
421                                            if (groupRoles.contains(role)) {
422                                                    groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId());
423                                            }
424                                    }
425    
426                                    if (group.isSite() &&
427                                            !role.getName().equals(RoleConstants.SITE_MEMBER) &&
428                                            (role.getType() == RoleConstants.TYPE_SITE)) {
429    
430                                            rolesQuery.addTerm(
431                                                    Field.GROUP_ROLE_ID,
432                                                    group.getGroupId() + StringPool.DASH +
433                                                            role.getRoleId());
434                                    }
435                            }
436    
437                            rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId());
438                    }
439    
440                    for (Group group : groups) {
441                            addRequiredMemberRole(group, rolesQuery);
442                    }
443    
444                    for (UserGroupRole userGroupRole : userGroupRoles) {
445                            rolesQuery.addTerm(
446                                    Field.GROUP_ROLE_ID,
447                                    userGroupRole.getGroupId() + StringPool.DASH +
448                                            userGroupRole.getRoleId());
449                    }
450    
451                    if (groupsQuery.hasClauses()) {
452                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
453                    }
454    
455                    if (rolesQuery.hasClauses()) {
456                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
457                    }
458    
459                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
460    
461                    fullQuery.add(query, BooleanClauseOccur.MUST);
462                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
463    
464                    return fullQuery;
465            }
466    
467            protected void doUpdatePermissionFields(
468                            String resourceName, String resourceClassPK)
469                    throws Exception {
470    
471                    Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName);
472    
473                    if (indexer != null) {
474                            indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK));
475                    }
476            }
477    
478            protected PermissionCheckerBag getPermissionCheckerBag(
479                            AdvancedPermissionChecker advancedPermissionChecker, long userId)
480                    throws Exception {
481    
482                    if (!advancedPermissionChecker.isSignedIn()) {
483                            return advancedPermissionChecker.getGuestUserBag();
484                    }
485                    else {
486                            return advancedPermissionChecker.getUserBag(userId, 0);
487                    }
488            }
489    
490            private static Log _log = LogFactoryUtil.getLog(
491                    SearchPermissionCheckerImpl.class);
492    
493    }