Java tutorial
/** * Copyright 2005-2014 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl2.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.rice.kim.impl.permission; import static org.kuali.rice.core.api.criteria.PredicateFactory.equal; import static org.kuali.rice.core.api.criteria.PredicateFactory.in; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import javax.xml.namespace.QName; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.log4j.Logger; import org.kuali.rice.core.api.cache.CacheKeyUtils; import org.kuali.rice.core.api.criteria.QueryByCriteria; import org.kuali.rice.core.api.criteria.QueryResults; import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; import org.kuali.rice.core.api.exception.RiceIllegalStateException; import org.kuali.rice.core.api.membership.MemberType; import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; import org.kuali.rice.kim.api.KimConstants; import org.kuali.rice.kim.api.common.assignee.Assignee; import org.kuali.rice.kim.api.common.delegate.DelegateType; import org.kuali.rice.kim.api.common.template.Template; import org.kuali.rice.kim.api.common.template.TemplateQueryResults; import org.kuali.rice.kim.api.identity.principal.Principal; import org.kuali.rice.kim.api.permission.Permission; import org.kuali.rice.kim.api.permission.PermissionQueryResults; import org.kuali.rice.kim.api.permission.PermissionService; import org.kuali.rice.kim.api.role.RoleMembership; import org.kuali.rice.kim.api.role.RoleService; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.kim.api.type.KimType; import org.kuali.rice.kim.api.type.KimTypeInfoService; import org.kuali.rice.kim.framework.permission.PermissionTypeService; import org.kuali.rice.kim.impl.common.attribute.AttributeTransform; import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo; import org.kuali.rice.kim.impl.role.RolePermissionBo; import org.kuali.rice.krad.data.DataObjectService; import org.kuali.rice.krad.util.KRADPropertyConstants; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.support.NoOpCacheManager; public class PermissionServiceImpl implements PermissionService { private static final Logger LOG = Logger.getLogger(PermissionServiceImpl.class); protected RoleService roleService; protected PermissionTypeService defaultPermissionTypeService; protected KimTypeInfoService kimTypeInfoService; protected DataObjectService dataObjectService; protected CacheManager cacheManager; private final CopyOnWriteArrayList<Template> allTemplates = new CopyOnWriteArrayList<Template>(); // -------------------- // Authorization Checks // -------------------- public PermissionServiceImpl() { this.cacheManager = new NoOpCacheManager(); } protected PermissionTypeService getPermissionTypeService(Template permissionTemplate) { if (permissionTemplate == null) { throw new IllegalArgumentException("permissionTemplate may not be null"); } KimType kimType = kimTypeInfoService.getKimType(permissionTemplate.getKimTypeId()); String serviceName = kimType.getServiceName(); // if no service specified, return a default implementation if (StringUtils.isBlank(serviceName)) { return defaultPermissionTypeService; } try { Object service = GlobalResourceLoader.getService(QName.valueOf(serviceName)); // if we have a service name, it must exist if (service == null) { throw new RuntimeException( "null returned for permission type service for service name: " + serviceName); } // whatever we retrieved must be of the correct type if (!(service instanceof PermissionTypeService)) { throw new RuntimeException("Service " + serviceName + " was not a PermissionTypeService. Was: " + service.getClass().getName()); } return (PermissionTypeService) service; } catch (Exception ex) { // sometimes service locators throw exceptions rather than returning null, handle that throw new RuntimeException( "Error retrieving service: " + serviceName + " from the KimImplServiceLocator.", ex); } } @Override public boolean hasPermission(String principalId, String namespaceCode, String permissionName) throws RiceIllegalArgumentException { incomingParamCheck(principalId, "principalId"); incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); return isAuthorized(principalId, namespaceCode, permissionName, Collections.<String, String>emptyMap()); } @Override public boolean isAuthorized(String principalId, String namespaceCode, String permissionName, Map<String, String> qualification) throws RiceIllegalArgumentException { incomingParamCheck(principalId, "principalId"); incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); incomingParamCheck(qualification, "qualification"); if (LOG.isDebugEnabled()) { logAuthorizationCheck("Permission", principalId, namespaceCode, permissionName, qualification); } List<String> roleIds = getRoleIdsForPermission(namespaceCode, permissionName); if (roleIds.isEmpty()) { if (LOG.isDebugEnabled()) { LOG.debug("Result: false"); } return false; } boolean isAuthorized = roleService.principalHasRole(principalId, roleIds, qualification); if (LOG.isDebugEnabled()) { LOG.debug("Result: " + isAuthorized); } return isAuthorized; } @Override public boolean hasPermissionByTemplate(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails) throws RiceIllegalArgumentException { incomingParamCheck(principalId, "principalId"); incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); return isAuthorizedByTemplate(principalId, namespaceCode, permissionTemplateName, permissionDetails, Collections.<String, String>emptyMap()); } @Override public boolean isAuthorizedByTemplate(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification) throws RiceIllegalArgumentException { incomingParamCheck(principalId, "principalId"); incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); incomingParamCheck(qualification, "qualification"); if (LOG.isDebugEnabled()) { logAuthorizationCheckByTemplate("Perm Templ", principalId, namespaceCode, permissionTemplateName, permissionDetails, qualification); } List<String> roleIds = getRoleIdsForPermissionTemplate(namespaceCode, permissionTemplateName, permissionDetails); if (roleIds.isEmpty()) { if (LOG.isDebugEnabled()) { LOG.debug("Result: false"); } return false; } boolean isAuthorized = roleService.principalHasRole(principalId, roleIds, qualification); if (LOG.isDebugEnabled()) { LOG.debug("Result: " + isAuthorized); } return isAuthorized; } @Override public List<Permission> getAuthorizedPermissions(String principalId, String namespaceCode, String permissionName, Map<String, String> qualification) throws RiceIllegalArgumentException { incomingParamCheck(principalId, "principalId"); incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); incomingParamCheck(qualification, "qualification"); // get all the permission objects whose name match that requested List<Permission> permissions = getPermissionsByName(namespaceCode, permissionName); // now, filter the full list by the detail passed List<Permission> applicablePermissions = getMatchingPermissions(permissions, null); List<Permission> permissionsForUser = getPermissionsForUser(principalId, applicablePermissions, qualification); return permissionsForUser; } @Override public List<Permission> getAuthorizedPermissionsByTemplate(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification) throws RiceIllegalArgumentException { incomingParamCheck(principalId, "principalId"); incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); incomingParamCheck(qualification, "qualification"); // get all the permission objects whose name match that requested List<Permission> permissions = getPermissionsByTemplateName(namespaceCode, permissionTemplateName); // now, filter the full list by the detail passed List<Permission> applicablePermissions = getMatchingPermissions(permissions, permissionDetails); return getPermissionsForUser(principalId, applicablePermissions, qualification); } /** * Checks the list of permissions against the principal's roles and returns a subset of the list which match. */ protected List<Permission> getPermissionsForUser(String principalId, List<Permission> permissions, Map<String, String> qualification) { List<Permission> results = new ArrayList<Permission>(); for (Permission perm : permissions) { List<String> roleIds = getRoleIdsForPermissions(Collections.singletonList(perm)); if (roleIds != null && !roleIds.isEmpty()) { if (roleService.principalHasRole(principalId, roleIds, qualification)) { results.add(perm); } } } return Collections.unmodifiableList(results); } protected Map<String, PermissionTypeService> getPermissionTypeServicesByTemplateId( Collection<Permission> permissions) { Map<String, PermissionTypeService> permissionTypeServices = new HashMap<String, PermissionTypeService>( permissions.size()); for (Permission perm : permissions) { if (!permissionTypeServices.containsKey(perm.getTemplate().getId())) { permissionTypeServices.put(perm.getTemplate().getId(), getPermissionTypeService(perm.getTemplate())); } } return permissionTypeServices; } protected Map<String, List<Permission>> groupPermissionsByTemplate(Collection<Permission> permissions) { Map<String, List<Permission>> results = new HashMap<String, List<Permission>>(); for (Permission perm : permissions) { List<Permission> perms = results.get(perm.getTemplate().getId()); if (perms == null) { perms = new ArrayList<Permission>(); results.put(perm.getTemplate().getId(), perms); } perms.add(perm); } return results; } /** * Compare each of the passed in permissions with the given permissionDetails. Those that * match are added to the result list. */ protected List<Permission> getMatchingPermissions(List<Permission> permissions, Map<String, String> permissionDetails) { List<String> permissionIds = new ArrayList<String>(permissions.size()); for (Permission permission : permissions) { permissionIds.add(permission.getId()); } String cacheKey = new StringBuilder("{getMatchingPermissions}").append("permissionIds=") .append(CacheKeyUtils.key(permissionIds)).append("|").append("permissionDetails=") .append(CacheKeyUtils.mapKey(permissionDetails)).toString(); Cache.ValueWrapper cachedValue = cacheManager.getCache(Permission.Cache.NAME).get(cacheKey); if (cachedValue != null && cachedValue.get() instanceof List) { return ((List<Permission>) cachedValue.get()); } List<Permission> applicablePermissions = new ArrayList<Permission>(); if (permissionDetails == null || permissionDetails.isEmpty()) { // if no details passed, assume that all match for (Permission perm : permissions) { applicablePermissions.add(perm); } } else { // otherwise, attempt to match the permission details // build a map of the template IDs to the type services Map<String, PermissionTypeService> permissionTypeServices = getPermissionTypeServicesByTemplateId( permissions); // build a map of permissions by template ID Map<String, List<Permission>> permissionMap = groupPermissionsByTemplate(permissions); // loop over the different templates, matching all of the same template against the type // service at once for (Map.Entry<String, List<Permission>> entry : permissionMap.entrySet()) { PermissionTypeService permissionTypeService = permissionTypeServices.get(entry.getKey()); List<Permission> permissionList = entry.getValue(); applicablePermissions .addAll(permissionTypeService.getMatchingPermissions(permissionDetails, permissionList)); } } applicablePermissions = Collections.unmodifiableList(applicablePermissions); cacheManager.getCache(Permission.Cache.NAME).put(cacheKey, applicablePermissions); return applicablePermissions; } @Override public List<Assignee> getPermissionAssignees(String namespaceCode, String permissionName, Map<String, String> qualification) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); incomingParamCheck(qualification, "qualification"); List<String> roleIds = getRoleIdsForPermission(namespaceCode, permissionName); if (roleIds.isEmpty()) { return Collections.emptyList(); } Collection<RoleMembership> roleMembers = roleService.getRoleMembers(roleIds, qualification); List<Assignee> results = new ArrayList<Assignee>(); for (RoleMembership rm : roleMembers) { List<DelegateType.Builder> delegateBuilderList = new ArrayList<DelegateType.Builder>(); if (!rm.getDelegates().isEmpty()) { for (DelegateType delegate : rm.getDelegates()) { delegateBuilderList.add(DelegateType.Builder.create(delegate)); } } if (MemberType.PRINCIPAL.equals(rm.getType())) { results.add(Assignee.Builder.create(rm.getMemberId(), null, delegateBuilderList).build()); } else if (MemberType.GROUP.equals(rm.getType())) { results.add(Assignee.Builder.create(null, rm.getMemberId(), delegateBuilderList).build()); } } return Collections.unmodifiableList(results); } @Override public List<Assignee> getPermissionAssigneesByTemplate(String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); incomingParamCheck(qualification, "qualification"); List<String> roleIds = getRoleIdsForPermissionTemplate(namespaceCode, permissionTemplateName, permissionDetails); if (roleIds.isEmpty()) { return Collections.emptyList(); } Collection<RoleMembership> roleMembers = roleService.getRoleMembers(roleIds, qualification); List<Assignee> results = new ArrayList<Assignee>(); for (RoleMembership rm : roleMembers) { List<DelegateType.Builder> delegateBuilderList = new ArrayList<DelegateType.Builder>(); if (!rm.getDelegates().isEmpty()) { for (DelegateType delegate : rm.getDelegates()) { delegateBuilderList.add(DelegateType.Builder.create(delegate)); } } if (MemberType.PRINCIPAL.equals(rm.getType())) { results.add(Assignee.Builder.create(rm.getMemberId(), null, delegateBuilderList).build()); } else { // a group membership results.add(Assignee.Builder.create(null, rm.getMemberId(), delegateBuilderList).build()); } } return Collections.unmodifiableList(results); } @Override public boolean isPermissionDefined(String namespaceCode, String permissionName) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); // get all the permission objects whose name match that requested List<Permission> permissions = getPermissionsByName(namespaceCode, permissionName); // now, filter the full list by the detail passed return !getMatchingPermissions(permissions, null).isEmpty(); } @Override public boolean isPermissionDefinedByTemplate(String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); // get all the permission objects whose name match that requested List<Permission> permissions = getPermissionsByTemplateName(namespaceCode, permissionTemplateName); // now, filter the full list by the detail passed return !getMatchingPermissions(permissions, permissionDetails).isEmpty(); } @Override public List<String> getRoleIdsForPermission(String namespaceCode, String permissionName) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); // note...this method is cached at the RoleService interface level using an annotation, but it's called quite // a bit internally, so we'll reproduce the caching here using the same key to help optimize String cacheKey = new StringBuilder("{RoleIds}").append("namespaceCode=").append(namespaceCode).append("|") .append("name=").append(permissionName).toString(); Cache.ValueWrapper cachedValue = cacheManager.getCache(Permission.Cache.NAME).get(cacheKey); if (cachedValue != null && cachedValue.get() instanceof List) { return ((List<String>) cachedValue.get()); } // get all the permission objects whose name match that requested List<Permission> permissions = getPermissionsByName(namespaceCode, permissionName); // now, filter the full list by the detail passed List<Permission> applicablePermissions = getMatchingPermissions(permissions, null); List<String> roleIds = getRoleIdsForPermissions(applicablePermissions); cacheManager.getCache(Permission.Cache.NAME).put(cacheKey, roleIds); return roleIds; } protected List<String> getRoleIdsForPermissionTemplate(String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails) { String cacheKey = new StringBuilder("{getRoleIdsForPermissionTemplate}").append("namespaceCode=") .append(namespaceCode).append("|").append("permissionTemplateName=").append(permissionTemplateName) .append("|").append("permissionDetails=").append(CacheKeyUtils.mapKey(permissionDetails)) .toString(); Cache.ValueWrapper cachedValue = cacheManager.getCache(Permission.Cache.NAME).get(cacheKey); if (cachedValue != null && cachedValue.get() instanceof List) { return ((List<String>) cachedValue.get()); } // get all the permission objects whose name match that requested List<Permission> permissions = getPermissionsByTemplateName(namespaceCode, permissionTemplateName); // now, filter the full list by the detail passed List<Permission> applicablePermissions = getMatchingPermissions(permissions, permissionDetails); List<String> roleIds = getRoleIdsForPermissions(applicablePermissions); cacheManager.getCache(Permission.Cache.NAME).put(cacheKey, roleIds); return roleIds; } // -------------------- // Permission Data // -------------------- @Override public Permission getPermission(String permissionId) throws RiceIllegalArgumentException { incomingParamCheck(permissionId, "permissionId"); PermissionBo impl = getPermissionImpl(permissionId); if (impl != null) { return PermissionBo.to(impl); } return null; } @Override public List<Permission> findPermissionsByTemplate(String namespaceCode, String permissionTemplateName) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); List<Permission> perms = getPermissionsByTemplateName(namespaceCode, permissionTemplateName); List<Permission> results = new ArrayList<Permission>(perms.size()); for (Permission perm : perms) { results.add(perm); } return Collections.unmodifiableList(results); } protected PermissionBo getPermissionImpl(String permissionId) throws RiceIllegalArgumentException { incomingParamCheck(permissionId, "permissionId"); return dataObjectService.find(PermissionBo.class, permissionId); } protected List<Permission> getPermissionsByTemplateName(String namespaceCode, String permissionTemplateName) { String cacheKey = new StringBuilder("{getPermissionsByTemplateName}").append("namespaceCode=") .append(namespaceCode).append("|").append("permissionTemplateName=").append(permissionTemplateName) .toString(); Cache.ValueWrapper cachedValue = cacheManager.getCache(Permission.Cache.NAME).get(cacheKey); if (cachedValue != null && cachedValue.get() instanceof List) { return ((List<Permission>) cachedValue.get()); } HashMap<String, Object> criteria = new HashMap<String, Object>(3); criteria.put("template.namespaceCode", namespaceCode); criteria.put("template.name", permissionTemplateName); criteria.put("template.active", Boolean.TRUE); criteria.put(KRADPropertyConstants.ACTIVE, Boolean.TRUE); List<Permission> permissions = toPermissions(dataObjectService .findMatching(PermissionBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()) .getResults()); cacheManager.getCache(Permission.Cache.NAME).put(cacheKey, permissions); return permissions; } protected List<Permission> getPermissionsByName(String namespaceCode, String permissionName) { String cacheKey = new StringBuilder("{getPermissionsByName}").append("namespaceCode=").append(namespaceCode) .append("|").append("permissionName=").append(permissionName).toString(); Cache.ValueWrapper cachedValue = cacheManager.getCache(Permission.Cache.NAME).get(cacheKey); if (cachedValue != null && cachedValue.get() instanceof List) { return ((List<Permission>) cachedValue.get()); } HashMap<String, Object> criteria = new HashMap<String, Object>(3); criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode); criteria.put(KimConstants.UniqueKeyConstants.PERMISSION_NAME, permissionName); criteria.put(KRADPropertyConstants.ACTIVE, Boolean.TRUE); List<Permission> permissions = toPermissions(dataObjectService .findMatching(PermissionBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()) .getResults()); cacheManager.getCache(Permission.Cache.NAME).put(cacheKey, permissions); return permissions; } @Override public Template getPermissionTemplate(String permissionTemplateId) throws RiceIllegalArgumentException { incomingParamCheck(permissionTemplateId, "permissionTemplateId"); PermissionTemplateBo impl = dataObjectService.find(PermissionTemplateBo.class, permissionTemplateId); if (impl != null) { return PermissionTemplateBo.to(impl); } return null; } @Override public Template findPermTemplateByNamespaceCodeAndName(String namespaceCode, String permissionTemplateName) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionTemplateName, "permissionTemplateName"); Map<String, String> criteria = new HashMap<String, String>(2); criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode); criteria.put(KimConstants.UniqueKeyConstants.PERMISSION_TEMPLATE_NAME, permissionTemplateName); QueryResults<PermissionTemplateBo> results = dataObjectService.findMatching(PermissionTemplateBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()); if (results.getResults().isEmpty()) { return null; } return PermissionTemplateBo.to(results.getResults().get(0)); } @Override public List<Template> getAllTemplates() { if (allTemplates.isEmpty()) { Map<String, Object> criteria = new HashMap<String, Object>(1); criteria.put(KRADPropertyConstants.ACTIVE, Boolean.TRUE); QueryResults<PermissionTemplateBo> impls = dataObjectService.findMatching(PermissionTemplateBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()); List<Template> infos = new ArrayList<Template>(impls.getResults().size()); for (PermissionTemplateBo impl : impls.getResults()) { infos.add(PermissionTemplateBo.to(impl)); } Collections.sort(infos, new Comparator<Template>() { @Override public int compare(Template tmpl1, Template tmpl2) { int result = tmpl1.getNamespaceCode().compareTo(tmpl2.getNamespaceCode()); if (result != 0) { return result; } result = tmpl1.getName().compareTo(tmpl2.getName()); return result; } }); allTemplates.addAll(infos); } return Collections.unmodifiableList(allTemplates); } @Override public Permission createPermission(Permission permission) throws RiceIllegalArgumentException, RiceIllegalStateException { incomingParamCheck(permission, "permission"); if (StringUtils.isNotBlank(permission.getId()) && getPermission(permission.getId()) != null) { throw new RiceIllegalStateException("the permission to create already exists: " + permission); } List<PermissionAttributeBo> attrBos = Collections.emptyList(); if (permission.getTemplate() != null) { attrBos = KimAttributeDataBo.createFrom(PermissionAttributeBo.class, permission.getAttributes(), permission.getTemplate().getKimTypeId()); } PermissionBo bo = PermissionBo.from(permission); if (bo.getTemplate() == null && bo.getTemplateId() != null) { bo.setTemplate(PermissionTemplateBo.from(getPermissionTemplate(bo.getTemplateId()))); } bo.setAttributeDetails(attrBos); return PermissionBo.to(dataObjectService.save(bo)); } @Override public Permission updatePermission(Permission permission) throws RiceIllegalArgumentException, RiceIllegalStateException { incomingParamCheck(permission, "permission"); PermissionBo oldPermission = getPermissionImpl(permission.getId()); if (StringUtils.isBlank(permission.getId()) || oldPermission == null) { throw new RiceIllegalStateException("the permission does not exist: " + permission); } //List<PermissionAttributeBo> attrBos = KimAttributeDataBo.createFrom(PermissionAttributeBo.class, permission.getAttributes(), permission.getTemplate().getKimTypeId()); List<PermissionAttributeBo> oldAttrBos = oldPermission.getAttributeDetails(); //put old attributes in map for easier updating Map<String, PermissionAttributeBo> oldAttrMap = new HashMap<String, PermissionAttributeBo>(); for (PermissionAttributeBo oldAttr : oldAttrBos) { oldAttrMap.put(oldAttr.getKimAttribute().getAttributeName(), oldAttr); } List<PermissionAttributeBo> newAttrBos = new ArrayList<PermissionAttributeBo>(); for (String key : permission.getAttributes().keySet()) { if (oldAttrMap.containsKey(key)) { PermissionAttributeBo updatedAttr = oldAttrMap.get(key); updatedAttr.setAttributeValue(permission.getAttributes().get(key)); newAttrBos.add(updatedAttr); } else { //new attribute newAttrBos.addAll(KimAttributeDataBo.createFrom(PermissionAttributeBo.class, Collections.singletonMap(key, permission.getAttributes().get(key)), permission.getTemplate().getKimTypeId())); } } PermissionBo bo = PermissionBo.from(permission); if (CollectionUtils.isNotEmpty(newAttrBos)) { if (null != bo.getAttributeDetails()) { bo.getAttributeDetails().clear(); } bo.setAttributeDetails(newAttrBos); } if (bo.getTemplate() == null && bo.getTemplateId() != null) { bo.setTemplate(PermissionTemplateBo.from(getPermissionTemplate(bo.getTemplateId()))); } return PermissionBo.to(dataObjectService.save(bo)); } @Override public Permission findPermByNamespaceCodeAndName(String namespaceCode, String permissionName) throws RiceIllegalArgumentException { incomingParamCheck(namespaceCode, "namespaceCode"); incomingParamCheck(permissionName, "permissionName"); PermissionBo permissionBo = getPermissionBoByName(namespaceCode, permissionName); if (permissionBo != null) { return PermissionBo.to(permissionBo); } return null; } protected PermissionBo getPermissionBoByName(String namespaceCode, String permissionName) { if (StringUtils.isBlank(namespaceCode) || StringUtils.isBlank(permissionName)) { return null; } Map<String, Object> criteria = new HashMap<String, Object>(3); criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode); criteria.put(KimConstants.UniqueKeyConstants.NAME, permissionName); criteria.put(KRADPropertyConstants.ACTIVE, Boolean.TRUE); // while this is not actually the primary key - there will be at most one row with these criteria QueryResults<PermissionBo> results = dataObjectService.findMatching(PermissionBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()); if (results.getResults().isEmpty()) { return null; } return results.getResults().get(0); } @Override public PermissionQueryResults findPermissions(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException { incomingParamCheck(queryByCriteria, "queryByCriteria"); QueryResults<PermissionBo> results = dataObjectService.findMatching(PermissionBo.class, AttributeTransform.getInstance().apply(queryByCriteria)); PermissionQueryResults.Builder builder = PermissionQueryResults.Builder.create(); builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); builder.setTotalRowCount(results.getTotalRowCount()); final List<Permission.Builder> ims = new ArrayList<Permission.Builder>(); for (PermissionBo bo : results.getResults()) { ims.add(Permission.Builder.create(bo)); } builder.setResults(ims); return builder.build(); } @Override public TemplateQueryResults findPermissionTemplates(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException { incomingParamCheck(queryByCriteria, "queryByCriteria"); QueryResults<PermissionTemplateBo> results = dataObjectService.findMatching(PermissionTemplateBo.class, queryByCriteria); TemplateQueryResults.Builder builder = TemplateQueryResults.Builder.create(); builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); builder.setTotalRowCount(results.getTotalRowCount()); final List<Template.Builder> ims = new ArrayList<Template.Builder>(); for (PermissionTemplateBo bo : results.getResults()) { ims.add(Template.Builder.create(bo)); } builder.setResults(ims); return builder.build(); } private List<String> getRoleIdsForPermissions(Collection<Permission> permissions) { if (CollectionUtils.isEmpty(permissions)) { return Collections.emptyList(); } List<String> ids = new ArrayList<String>(); for (Permission p : permissions) { ids.add(p.getId()); } return getRoleIdsForPermissionIds(ids); } private List<String> getRoleIdsForPermissionIds(Collection<String> permissionIds) { if (CollectionUtils.isEmpty(permissionIds)) { return Collections.emptyList(); } String cacheKey = new StringBuilder("{getRoleIdsForPermissionIds}").append("permissionIds=") .append(CacheKeyUtils.key(permissionIds)).toString(); Cache.ValueWrapper cachedValue = cacheManager.getCache(Permission.Cache.NAME).get(cacheKey); if (cachedValue != null && cachedValue.get() instanceof List) { return ((List<String>) cachedValue.get()); } QueryByCriteria query = QueryByCriteria.Builder.fromPredicates(equal("active", Boolean.TRUE), in("permissionId", permissionIds.toArray(new String[] {}))); QueryResults<RolePermissionBo> results = dataObjectService.findMatching(RolePermissionBo.class, query); List<String> roleIds = new ArrayList<String>(); for (RolePermissionBo bo : results.getResults()) { roleIds.add(bo.getRoleId()); } roleIds = Collections.unmodifiableList(roleIds); cacheManager.getCache(Permission.Cache.NAME).put(cacheKey, roleIds); return roleIds; } /** * Sets the kimTypeInfoService attribute value. * * @param kimTypeInfoService The kimTypeInfoService to set. */ public void setKimTypeInfoService(KimTypeInfoService kimTypeInfoService) { this.kimTypeInfoService = kimTypeInfoService; } /** * Sets the defaultPermissionTypeService attribute value. * * @param defaultPermissionTypeService The defaultPermissionTypeService to set. */ public void setDefaultPermissionTypeService(PermissionTypeService defaultPermissionTypeService) { this.defaultPermissionTypeService = defaultPermissionTypeService; } /** * Sets the roleService attribute value. * * @param roleService The roleService to set. */ public void setRoleService(RoleService roleService) { this.roleService = roleService; } /** * Sets the dataObjectService attribute value. * * @param dataObjectService The dataObjectService to set. */ public void setDataObjectService(final DataObjectService dataObjectService) { this.dataObjectService = dataObjectService; } /** * Sets the cache manager which this service implementation can for internal caching. * Calling this setter is optional, though the value passed to it must not be null. * * @param cacheManager the cache manager to use for internal caching, must not be null * @throws IllegalArgumentException if a null cache manager is passed */ public void setCacheManager(final CacheManager cacheManager) { if (cacheManager == null) { throw new IllegalArgumentException("cacheManager must not be null"); } this.cacheManager = cacheManager; } private List<Permission> toPermissions(Collection<PermissionBo> permissionBos) { if (CollectionUtils.isEmpty(permissionBos)) { return new ArrayList<Permission>(); } List<Permission> permissions = new ArrayList<Permission>(permissionBos.size()); for (PermissionBo permissionBo : permissionBos) { permissions.add(PermissionBo.to(permissionBo)); } return permissions; } protected void logAuthorizationCheck(String checkType, String principalId, String namespaceCode, String permissionName, Map<String, String> qualification) { StringBuilder sb = new StringBuilder(); sb.append('\n'); sb.append("Is AuthZ for ").append(checkType).append(": ").append(namespaceCode).append("/") .append(permissionName).append('\n'); sb.append(" Principal: ").append(principalId); if (principalId != null) { Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(principalId); if (principal != null) { sb.append(" (").append(principal.getPrincipalName()).append(')'); } } sb.append('\n'); sb.append(" Qualifiers:\n"); if (qualification != null && !qualification.isEmpty()) { sb.append(qualification); } else { sb.append(" [null]\n"); } if (LOG.isTraceEnabled()) { LOG.trace(sb.append(ExceptionUtils.getStackTrace(new Throwable()))); } else { LOG.debug(sb.toString()); } } protected void logAuthorizationCheckByTemplate(String checkType, String principalId, String namespaceCode, String permissionName, Map<String, String> permissionDetails, Map<String, String> qualification) { StringBuilder sb = new StringBuilder(); sb.append('\n'); sb.append("Is AuthZ for ").append(checkType).append(": ").append(namespaceCode).append("/") .append(permissionName).append('\n'); sb.append(" Principal: ").append(principalId); if (principalId != null) { Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(principalId); if (principal != null) { sb.append(" (").append(principal.getPrincipalName()).append(')'); } } sb.append('\n'); sb.append(" Details:\n"); if (permissionDetails != null) { sb.append(permissionDetails); } else { sb.append(" [null]\n"); } sb.append(" Qualifiers:\n"); if (qualification != null && !qualification.isEmpty()) { sb.append(qualification); } else { sb.append(" [null]\n"); } if (LOG.isTraceEnabled()) { LOG.trace(sb.append(ExceptionUtils.getStackTrace(new Throwable()))); } else { LOG.debug(sb.toString()); } } private void incomingParamCheck(Object object, String name) { if (object == null) { throw new RiceIllegalArgumentException(name + " was null"); } else if (object instanceof String && StringUtils.isBlank((String) object)) { throw new RiceIllegalArgumentException(name + " was blank"); } } }