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