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