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