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