001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.ListUtil;
033    import com.liferay.portal.kernel.util.StringPool;
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.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.util.PortalUtil;
053    
054    import java.util.ArrayList;
055    import java.util.Collections;
056    import java.util.HashMap;
057    import java.util.HashSet;
058    import java.util.Iterator;
059    import java.util.List;
060    import java.util.Map;
061    import java.util.Set;
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                            String viewActionId = document.get(Field.VIEW_ACTION_ID);
113    
114                            if (Validator.isNull(viewActionId)) {
115                                    viewActionId = ActionKeys.VIEW;
116                            }
117    
118                            doAddPermissionFields_6(
119                                    companyId, groupId, className, classPK, viewActionId, document);
120                    }
121                    catch (NoSuchResourceException nsre) {
122                    }
123                    catch (Exception e) {
124                            _log.error(e, e);
125                    }
126            }
127    
128            @Override
129            public Query getPermissionQuery(
130                    long companyId, long[] groupIds, long userId, String className,
131                    Query query, SearchContext searchContext) {
132    
133                    try {
134                            query = doGetPermissionQuery(
135                                    companyId, groupIds, userId, className, query, searchContext);
136                    }
137                    catch (Exception e) {
138                            _log.error(e, e);
139                    }
140    
141                    return query;
142            }
143    
144            @Override
145            public void updatePermissionFields(
146                    String resourceName, String resourceClassPK) {
147    
148                    try {
149                            doUpdatePermissionFields(resourceName, resourceClassPK);
150                    }
151                    catch (Exception e) {
152                            _log.error(e, e);
153                    }
154            }
155    
156            protected void doAddPermissionFields_6(
157                            long companyId, long groupId, String className, String classPK,
158                            String viewActionId, 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 = ListUtil.copy(
168                            ResourceActionsUtil.getRoles(companyId, group, className, null));
169    
170                    if (groupId > 0) {
171                            List<Role> teamRoles = RoleLocalServiceUtil.getTeamRoles(groupId);
172    
173                            roles.addAll(teamRoles);
174                    }
175    
176                    long[] roleIdsArray = new long[roles.size()];
177    
178                    for (int i = 0; i < roleIdsArray.length; i++) {
179                            Role role = roles.get(i);
180    
181                            roleIdsArray[i] = role.getRoleId();
182                    }
183    
184                    boolean[] hasResourcePermissions = null;
185    
186                    if (ResourceBlockLocalServiceUtil.isSupported(className)) {
187                            ResourceBlockIdsBag resourceBlockIdsBag =
188                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
189                                            companyId, groupId, className, roleIdsArray);
190    
191                            long actionId = ResourceBlockLocalServiceUtil.getActionId(
192                                    className, viewActionId);
193    
194                            List<Long> resourceBlockIds =
195                                    resourceBlockIdsBag.getResourceBlockIds(actionId);
196    
197                            hasResourcePermissions = new boolean[roleIdsArray.length];
198    
199                            for (long resourceBlockId : resourceBlockIds) {
200                                    for (int i = 0; i < roleIdsArray.length; i++) {
201                                            int count =
202                                                    ResourceBlockPermissionLocalServiceUtil.
203                                                            getResourceBlockPermissionsCount(
204                                                                    resourceBlockId, roleIdsArray[i]);
205    
206                                            hasResourcePermissions[i] = (count > 0);
207                                    }
208                            }
209                    }
210                    else {
211                            hasResourcePermissions =
212                                    ResourcePermissionLocalServiceUtil.hasResourcePermissions(
213                                            companyId, className, ResourceConstants.SCOPE_INDIVIDUAL,
214                                            classPK, roleIdsArray, viewActionId);
215                    }
216    
217                    List<Long> roleIds = new ArrayList<Long>();
218                    List<String> groupRoleIds = new ArrayList<String>();
219    
220                    for (int i = 0; i < hasResourcePermissions.length; i++) {
221                            if (!hasResourcePermissions[i]) {
222                                    continue;
223                            }
224    
225                            Role role = roles.get(i);
226    
227                            if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
228                                    (role.getType() == RoleConstants.TYPE_SITE)) {
229    
230                                    groupRoleIds.add(groupId + StringPool.DASH + role.getRoleId());
231                            }
232                            else {
233                                    roleIds.add(role.getRoleId());
234                            }
235                    }
236    
237                    doc.addKeyword(
238                            Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()]));
239                    doc.addKeyword(
240                            Field.GROUP_ROLE_ID,
241                            groupRoleIds.toArray(new String[groupRoleIds.size()]));
242            }
243    
244            protected Query doGetPermissionQuery(
245                            long companyId, long[] searchGroupIds, long userId,
246                            String className, Query query, SearchContext searchContext)
247                    throws Exception {
248    
249                    Indexer indexer = IndexerRegistryUtil.getIndexer(className);
250    
251                    if (!indexer.isPermissionAware()) {
252                            return query;
253                    }
254    
255                    PermissionChecker permissionChecker =
256                            PermissionThreadLocal.getPermissionChecker();
257    
258                    AdvancedPermissionChecker advancedPermissionChecker = null;
259    
260                    if ((permissionChecker != null) &&
261                            (permissionChecker instanceof AdvancedPermissionChecker)) {
262    
263                            advancedPermissionChecker =
264                                    (AdvancedPermissionChecker)permissionChecker;
265                    }
266    
267                    if (advancedPermissionChecker == null) {
268                            return query;
269                    }
270    
271                    PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag(
272                            advancedPermissionChecker, userId);
273    
274                    if (permissionCheckerBag == null) {
275                            return query;
276                    }
277    
278                    if (permissionChecker.isCompanyAdmin(companyId)) {
279                            return query;
280                    }
281    
282                    Set<Role> roles = new HashSet<Role>();
283                    Map<Long, List<Role>> usersGroupIdsToRoles =
284                            new HashMap<Long, List<Role>>();
285    
286                    roles.addAll(permissionCheckerBag.getRoles());
287    
288                    if (advancedPermissionChecker.isSignedIn()) {
289                            roles.add(
290                                    RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST));
291                    }
292                    else {
293                            Group guestGroup = GroupLocalServiceUtil.getGroup(
294                                    companyId, GroupConstants.GUEST);
295    
296                            roles.addAll(
297                                    RoleLocalServiceUtil.getUserRelatedRoles(
298                                            userId, Collections.singletonList(guestGroup)));
299                    }
300    
301                    Role organizationUserRole = RoleLocalServiceUtil.getRole(
302                            companyId, RoleConstants.ORGANIZATION_USER);
303                    Role siteMemberRole = RoleLocalServiceUtil.getRole(
304                            companyId, RoleConstants.SITE_MEMBER);
305    
306                    Set<Group> groups = new HashSet<Group>(
307                            permissionCheckerBag.getUserGroups());
308    
309                    groups.addAll(permissionCheckerBag.getUserOrgGroups());
310    
311                    for (Group group : groups) {
312                            long[] roleIds = permissionChecker.getRoleIds(
313                                    userId, group.getGroupId());
314    
315                            List<Role> groupRoles = RoleLocalServiceUtil.getRoles(roleIds);
316    
317                            roles.addAll(groupRoles);
318    
319                            Iterator<Role> iterator = groupRoles.iterator();
320    
321                            while (iterator.hasNext()) {
322                                    Role groupRole = iterator.next();
323    
324                                    if ((groupRole.getType() != RoleConstants.TYPE_ORGANIZATION) &&
325                                            (groupRole.getType() != RoleConstants.TYPE_SITE)) {
326    
327                                            iterator.remove();
328                                    }
329                            }
330    
331                            if (group.isOrganization() &&
332                                    !groupRoles.contains(organizationUserRole)) {
333    
334                                    groupRoles.add(organizationUserRole);
335                            }
336    
337                            if (group.isSite() && !groupRoles.contains(siteMemberRole)) {
338                                    groupRoles.add(siteMemberRole);
339                            }
340    
341                            usersGroupIdsToRoles.put(group.getGroupId(), groupRoles);
342                    }
343    
344                    return doGetPermissionQuery_6(
345                            companyId, searchGroupIds, userId, className, query, searchContext,
346                            advancedPermissionChecker, roles, usersGroupIdsToRoles);
347            }
348    
349            protected Query doGetPermissionQuery_6(
350                            long companyId, long[] searchGroupIds, long userId,
351                            String className, Query query, SearchContext searchContext,
352                            AdvancedPermissionChecker advancedPermissionChecker,
353                            Set<Role> roles, Map<Long, List<Role>> usersGroupIdsToRoles)
354                    throws Exception {
355    
356                    BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create(
357                            searchContext);
358    
359                    if (userId > 0) {
360                            permissionQuery.addTerm(Field.USER_ID, userId);
361                    }
362    
363                    BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create(
364                            searchContext);
365                    BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext);
366    
367                    List<Long> roleIds = new ArrayList<Long>(roles.size());
368                    List<Long> regularRoleIds = new ArrayList<Long>();
369    
370                    for (Role role : roles) {
371                            roleIds.add(role.getRoleId());
372    
373                            if (role.getType() == RoleConstants.TYPE_REGULAR) {
374                                    regularRoleIds.add(role.getRoleId());
375                            }
376    
377                            rolesQuery.addTerm(Field.ROLE_ID, String.valueOf(role.getRoleId()));
378                    }
379    
380                    long[] roleIdsArray = ArrayUtil.toLongArray(roleIds);
381    
382                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
383                                    companyId, className, ResourceConstants.SCOPE_COMPANY,
384                                    String.valueOf(companyId), roleIdsArray, ActionKeys.VIEW)) {
385    
386                            return query;
387                    }
388    
389                    if (ResourcePermissionLocalServiceUtil.hasResourcePermission(
390                                    companyId, className, ResourceConstants.SCOPE_GROUP_TEMPLATE,
391                                    String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
392                                    ArrayUtil.toLongArray(regularRoleIds), ActionKeys.VIEW)) {
393    
394                            return query;
395                    }
396    
397                    for (Map.Entry<Long, List<Role>> entry :
398                                    usersGroupIdsToRoles.entrySet()) {
399    
400                            long groupId = entry.getKey();
401                            List<Role> groupRoles = entry.getValue();
402    
403                            long[] groupRoleIdsArray = new long[groupRoles.size()];
404    
405                            for (int i = 0; i < groupRoleIdsArray.length; i++) {
406                                    Role groupRole = groupRoles.get(i);
407    
408                                    groupRoleIdsArray[i] = groupRole.getRoleId();
409                            }
410    
411                            if (advancedPermissionChecker.isGroupAdmin(groupId) ||
412                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
413                                            companyId, className, ResourceConstants.SCOPE_GROUP,
414                                            String.valueOf(groupId), roleIdsArray, ActionKeys.VIEW) ||
415                                    ResourcePermissionLocalServiceUtil.hasResourcePermission(
416                                            companyId, className,
417                                            ResourceConstants.SCOPE_GROUP_TEMPLATE,
418                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
419                                            groupRoleIdsArray, ActionKeys.VIEW)) {
420    
421                                    groupsQuery.addTerm(Field.GROUP_ID, String.valueOf(groupId));
422                            }
423    
424                            for (Role groupRole : groupRoles) {
425                                    rolesQuery.addTerm(
426                                            Field.GROUP_ROLE_ID,
427                                            groupId + StringPool.DASH + groupRole.getRoleId());
428                            }
429                    }
430    
431                    if (ArrayUtil.isNotEmpty(searchGroupIds)) {
432                            Set<Long> userGroupIds = usersGroupIdsToRoles.keySet();
433    
434                            for (long searchGroupId : searchGroupIds) {
435                                    if (!userGroupIds.contains(searchGroupId) &&
436                                            ResourcePermissionLocalServiceUtil.hasResourcePermission(
437                                                    companyId, className, ResourceConstants.SCOPE_GROUP,
438                                                    String.valueOf(searchGroupId), roleIdsArray,
439                                                    ActionKeys.VIEW)) {
440    
441                                            groupsQuery.addTerm(
442                                                    Field.GROUP_ID, String.valueOf(searchGroupId));
443                                    }
444                            }
445                    }
446    
447                    if (groupsQuery.hasClauses()) {
448                            permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD);
449                    }
450    
451                    if (rolesQuery.hasClauses()) {
452                            permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD);
453                    }
454    
455                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
456    
457                    fullQuery.add(query, BooleanClauseOccur.MUST);
458                    fullQuery.add(permissionQuery, BooleanClauseOccur.MUST);
459    
460                    return fullQuery;
461            }
462    
463            protected void doUpdatePermissionFields(
464                            String resourceName, String resourceClassPK)
465                    throws Exception {
466    
467                    Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName);
468    
469                    if (indexer != null) {
470                            indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK));
471                    }
472            }
473    
474            protected PermissionCheckerBag getPermissionCheckerBag(
475                            AdvancedPermissionChecker advancedPermissionChecker, long userId)
476                    throws Exception {
477    
478                    if (!advancedPermissionChecker.isSignedIn()) {
479                            return advancedPermissionChecker.getGuestUserBag();
480                    }
481                    else {
482                            return advancedPermissionChecker.getUserBag(userId, 0);
483                    }
484            }
485    
486            private static Log _log = LogFactoryUtil.getLog(
487                    SearchPermissionCheckerImpl.class);
488    
489    }