/** * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.search; import com.liferay.portal.NoSuchResourceException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.search.BooleanClauseOccur; import com.liferay.portal.kernel.search.BooleanQuery; import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil; import com.liferay.portal.kernel.search.Document; import com.liferay.portal.kernel.search.Field; import com.liferay.portal.kernel.search.Indexer; import com.liferay.portal.kernel.search.IndexerRegistryUtil; import com.liferay.portal.kernel.search.Query; import com.liferay.portal.kernel.search.SearchContext; import com.liferay.portal.kernel.search.SearchPermissionChecker; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ListUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.UniqueList; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.model.Group; import com.liferay.portal.model.GroupConstants; import com.liferay.portal.model.ResourceConstants; import com.liferay.portal.model.Role; import com.liferay.portal.model.RoleConstants; import com.liferay.portal.model.UserGroupRole; import com.liferay.portal.security.permission.ActionKeys; import com.liferay.portal.security.permission.AdvancedPermissionChecker; import com.liferay.portal.security.permission.PermissionChecker; import com.liferay.portal.security.permission.PermissionCheckerBag; import com.liferay.portal.security.permission.PermissionThreadLocal; import com.liferay.portal.security.permission.ResourceActionsUtil; import com.liferay.portal.security.permission.ResourceBlockIdsBag; import com.liferay.portal.service.GroupLocalServiceUtil; import com.liferay.portal.service.ResourceBlockLocalServiceUtil; import com.liferay.portal.service.ResourceBlockPermissionLocalServiceUtil; import com.liferay.portal.service.ResourcePermissionLocalServiceUtil; import com.liferay.portal.service.RoleLocalServiceUtil; import com.liferay.portal.service.UserGroupRoleLocalServiceUtil; import com.liferay.portal.util.PortalUtil; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Allen Chiang * @author Bruno Farache * @author Raymond Augé * @author Amos Fong */ public class SearchPermissionCheckerImpl implements SearchPermissionChecker { @Override public void addPermissionFields(long companyId, Document document) { try { long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID)); String className = document.get(Field.ENTRY_CLASS_NAME); boolean relatedEntry = GetterUtil.getBoolean( document.get(Field.RELATED_ENTRY)); if (relatedEntry) { long classNameId = GetterUtil.getLong( document.get(Field.CLASS_NAME_ID)); className = PortalUtil.getClassName(classNameId); } if (Validator.isNull(className)) { return; } String classPK = document.get(Field.ROOT_ENTRY_CLASS_PK); if (Validator.isNull(classPK)) { classPK = document.get(Field.ENTRY_CLASS_PK); } if (relatedEntry) { classPK = document.get(Field.CLASS_PK); } if (Validator.isNull(classPK)) { return; } Indexer indexer = IndexerRegistryUtil.getIndexer(className); if (!indexer.isPermissionAware()) { return; } doAddPermissionFields_6( companyId, groupId, className, classPK, document); } catch (NoSuchResourceException nsre) { } catch (Exception e) { _log.error(e, e); } } @Override public Query getPermissionQuery( long companyId, long[] groupIds, long userId, String className, Query query, SearchContext searchContext) { try { query = doGetPermissionQuery( companyId, groupIds, userId, className, query, searchContext); } catch (Exception e) { _log.error(e, e); } return query; } @Override public void updatePermissionFields( String resourceName, String resourceClassPK) { try { doUpdatePermissionFields(resourceName, resourceClassPK); } catch (Exception e) { _log.error(e, e); } } protected void addRequiredMemberRole( Group group, BooleanQuery permissionQuery) throws Exception { if (group.isOrganization()) { Role organizationUserRole = RoleLocalServiceUtil.getRole( group.getCompanyId(), RoleConstants.ORGANIZATION_USER); permissionQuery.addTerm( Field.GROUP_ROLE_ID, group.getGroupId() + StringPool.DASH + organizationUserRole.getRoleId()); } if (group.isSite()) { Role siteMemberRole = RoleLocalServiceUtil.getRole( group.getCompanyId(), RoleConstants.SITE_MEMBER); permissionQuery.addTerm( Field.GROUP_ROLE_ID, group.getGroupId() + StringPool.DASH + siteMemberRole.getRoleId()); } } protected void doAddPermissionFields_6( long companyId, long groupId, String className, String classPK, Document doc) throws Exception { Group group = null; if (groupId > 0) { group = GroupLocalServiceUtil.getGroup(groupId); } List<Role> roles = ListUtil.copy( ResourceActionsUtil.getRoles(companyId, group, className, null)); if (groupId > 0) { List<Role> teamRoles = RoleLocalServiceUtil.getTeamRoles(groupId); roles.addAll(teamRoles); } long[] roleIdsArray = new long[roles.size()]; for (int i = 0; i < roleIdsArray.length; i++) { Role role = roles.get(i); roleIdsArray[i] = role.getRoleId(); } boolean[] hasResourcePermissions = null; if (ResourceBlockLocalServiceUtil.isSupported(className)) { ResourceBlockIdsBag resourceBlockIdsBag = ResourceBlockLocalServiceUtil.getResourceBlockIdsBag( companyId, groupId, className, roleIdsArray); long actionId = ResourceBlockLocalServiceUtil.getActionId( className, ActionKeys.VIEW); List<Long> resourceBlockIds = resourceBlockIdsBag.getResourceBlockIds(actionId); hasResourcePermissions = new boolean[roleIdsArray.length]; for (long resourceBlockId : resourceBlockIds) { for (int i = 0; i < roleIdsArray.length; i++) { int count = ResourceBlockPermissionLocalServiceUtil. getResourceBlockPermissionsCount( resourceBlockId, roleIdsArray[i]); hasResourcePermissions[i] = (count > 0); } } } else { hasResourcePermissions = ResourcePermissionLocalServiceUtil.hasResourcePermissions( companyId, className, ResourceConstants.SCOPE_INDIVIDUAL, classPK, roleIdsArray, ActionKeys.VIEW); } List<Long> roleIds = new ArrayList<Long>(); List<String> groupRoleIds = new ArrayList<String>(); for (int i = 0; i < hasResourcePermissions.length; i++) { if (!hasResourcePermissions[i]) { continue; } Role role = roles.get(i); if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) || (role.getType() == RoleConstants.TYPE_SITE)) { groupRoleIds.add(groupId + StringPool.DASH + role.getRoleId()); } else { roleIds.add(role.getRoleId()); } } doc.addKeyword( Field.ROLE_ID, roleIds.toArray(new Long[roleIds.size()])); doc.addKeyword( Field.GROUP_ROLE_ID, groupRoleIds.toArray(new String[groupRoleIds.size()])); } protected Query doGetPermissionQuery( long companyId, long[] groupIds, long userId, String className, Query query, SearchContext searchContext) throws Exception { Indexer indexer = IndexerRegistryUtil.getIndexer(className); if (!indexer.isPermissionAware()) { return query; } PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker(); AdvancedPermissionChecker advancedPermissionChecker = null; if ((permissionChecker != null) && (permissionChecker instanceof AdvancedPermissionChecker)) { advancedPermissionChecker = (AdvancedPermissionChecker)permissionChecker; } if (advancedPermissionChecker == null) { return query; } PermissionCheckerBag permissionCheckerBag = getPermissionCheckerBag( advancedPermissionChecker, userId); if (permissionCheckerBag == null) { return query; } List<Group> groups = new UniqueList<Group>(); List<Role> roles = new UniqueList<Role>(); List<UserGroupRole> userGroupRoles = new UniqueList<UserGroupRole>(); Map<Long, List<Role>> groupIdsToRoles = new HashMap<Long, List<Role>>(); roles.addAll(permissionCheckerBag.getRoles()); if (ArrayUtil.isEmpty(groupIds)) { groups.addAll(GroupLocalServiceUtil.getUserGroups(userId, true)); groups.addAll(permissionCheckerBag.getGroups()); userGroupRoles = UserGroupRoleLocalServiceUtil.getUserGroupRoles( userId); } else { groups.addAll(permissionCheckerBag.getGroups()); for (long groupId : groupIds) { if (GroupLocalServiceUtil.hasUserGroup(userId, groupId)) { Group group = GroupLocalServiceUtil.getGroup(groupId); groups.add(group); } userGroupRoles.addAll( UserGroupRoleLocalServiceUtil.getUserGroupRoles( userId, groupId)); userGroupRoles.addAll( UserGroupRoleLocalServiceUtil. getUserGroupRolesByUserUserGroupAndGroup( userId, groupId)); } } if (advancedPermissionChecker.isSignedIn()) { roles.add( RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST)); } for (Group group : groups) { PermissionCheckerBag userBag = advancedPermissionChecker.getUserBag( userId, group.getGroupId()); List<Role> groupRoles = userBag.getRoles(); groupIdsToRoles.put(group.getGroupId(), groupRoles); roles.addAll(groupRoles); } return doGetPermissionQuery_6( companyId, groupIds, userId, className, query, searchContext, advancedPermissionChecker, groups, roles, userGroupRoles, groupIdsToRoles); } protected Query doGetPermissionQuery_6( long companyId, long[] groupIds, long userId, String className, Query query, SearchContext searchContext, AdvancedPermissionChecker advancedPermissionChecker, List<Group> groups, List<Role> roles, List<UserGroupRole> userGroupRoles, Map<Long, List<Role>> groupIdsToRoles) throws Exception { BooleanQuery permissionQuery = BooleanQueryFactoryUtil.create( searchContext); if (userId > 0) { permissionQuery.addTerm(Field.USER_ID, userId); } BooleanQuery groupsQuery = BooleanQueryFactoryUtil.create( searchContext); BooleanQuery rolesQuery = BooleanQueryFactoryUtil.create(searchContext); for (Role role : roles) { String roleName = role.getName(); if (roleName.equals(RoleConstants.ADMINISTRATOR)) { return query; } if (ResourcePermissionLocalServiceUtil.hasResourcePermission( companyId, className, ResourceConstants.SCOPE_COMPANY, String.valueOf(companyId), role.getRoleId(), ActionKeys.VIEW)) { return query; } if ((role.getType() == RoleConstants.TYPE_REGULAR) && ResourcePermissionLocalServiceUtil.hasResourcePermission( companyId, className, ResourceConstants.SCOPE_GROUP_TEMPLATE, String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID), role.getRoleId(), ActionKeys.VIEW)) { return query; } for (Group group : groups) { if (ResourcePermissionLocalServiceUtil.hasResourcePermission( companyId, className, ResourceConstants.SCOPE_GROUP, String.valueOf(group.getGroupId()), role.getRoleId(), ActionKeys.VIEW)) { groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId()); } if ((role.getType() != RoleConstants.TYPE_REGULAR) && ResourcePermissionLocalServiceUtil.hasResourcePermission( companyId, className, ResourceConstants.SCOPE_GROUP_TEMPLATE, String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID), role.getRoleId(), ActionKeys.VIEW)) { List<Role> groupRoles = groupIdsToRoles.get( group.getGroupId()); if (groupRoles.contains(role)) { groupsQuery.addTerm(Field.GROUP_ID, group.getGroupId()); } } if (group.isSite() && !roleName.equals(RoleConstants.SITE_MEMBER) && (role.getType() == RoleConstants.TYPE_SITE)) { rolesQuery.addTerm( Field.GROUP_ROLE_ID, group.getGroupId() + StringPool.DASH + role.getRoleId()); } } rolesQuery.addTerm(Field.ROLE_ID, role.getRoleId()); } for (Group group : groups) { addRequiredMemberRole(group, rolesQuery); } for (UserGroupRole userGroupRole : userGroupRoles) { rolesQuery.addTerm( Field.GROUP_ROLE_ID, userGroupRole.getGroupId() + StringPool.DASH + userGroupRole.getRoleId()); } if (groupsQuery.hasClauses()) { permissionQuery.add(groupsQuery, BooleanClauseOccur.SHOULD); } if (rolesQuery.hasClauses()) { permissionQuery.add(rolesQuery, BooleanClauseOccur.SHOULD); } BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext); fullQuery.add(query, BooleanClauseOccur.MUST); fullQuery.add(permissionQuery, BooleanClauseOccur.MUST); return fullQuery; } protected void doUpdatePermissionFields( String resourceName, String resourceClassPK) throws Exception { Indexer indexer = IndexerRegistryUtil.getIndexer(resourceName); if (indexer != null) { indexer.reindex(resourceName, GetterUtil.getLong(resourceClassPK)); } } protected PermissionCheckerBag getPermissionCheckerBag( AdvancedPermissionChecker advancedPermissionChecker, long userId) throws Exception { if (!advancedPermissionChecker.isSignedIn()) { return advancedPermissionChecker.getGuestUserBag(); } else { return advancedPermissionChecker.getUserBag(userId, 0); } } private static Log _log = LogFactoryUtil.getLog( SearchPermissionCheckerImpl.class); }