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