As we transition to the new Hyland Community, some post links may be temporarily disrupted as we finalize redirects. We apologize for the inconvenience and are working to resolve this as quickly as possible. Details.
public class CompositeVoter implements AccessDecisionVoter, InitializingBean { List<AccessDecisionVoter> containedVoters; private int combine(int currentResult, int newResult) { // Deny always wins if (currentResult == ACCESS_DENIED || newResult == ACCESS_DENIED) { return ACCESS_DENIED; } // Allow precedes abstain if (currentResult == ACCESS_GRANTED || newResult == ACCESS_GRANTED) { return ACCESS_GRANTED; } return ACCESS_ABSTAIN; } @Override public boolean supports(ConfigAttribute arg0) { boolean result = false; for (AccessDecisionVoter voter : containedVoters) { result |= voter.supports(arg0); } return result; } @Override public boolean supports(Class arg0) { boolean result = false; for (AccessDecisionVoter voter : containedVoters) { result |= voter.supports(arg0); } return result; } @Override public int vote(Authentication arg0, Object arg1, ConfigAttributeDefinition arg2) { int result = ACCESS_ABSTAIN; for (AccessDecisionVoter voter : containedVoters) { // Could be optimized: on a deny, you can give up immediately result = combine(result, voter.vote(arg0, arg1, arg2)); } return result; } @Override public void afterPropertiesSet() throws Exception { assert containedVoters != null; } public void setContainedVoters(List<AccessDecisionVoter> containedVoters) { this.containedVoters = containedVoters; } }
public class ConfidentialityVoter implements InitializingBean, AccessDecisionVoter { private Logger logger = Logger.getLogger(ConfidentialityVoter.class); private static final String ACL_NODE = "ACL_NODE"; private static final String ACL_PARENT = "ACL_PARENT"; private static final String ACL_ALLOW = "ACL_ALLOW"; private static final String ACL_METHOD = "ACL_METHOD"; private static final String TOP_SECRET = "AllowStrengVertraulich"; private static final String RESTRICTED = "AllowVertraulich"; private static final String INTERNAL = "AllowIntern"; private static final QName nameProp = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "name"); private AuthenticationService authenticationService; private NodeService nodeService; private NamespacePrefixResolver nspr; private AuthorityService authorityService; private PermissionServiceSPI permissionService; private PermissionReference allowTopSecret = SimplePermissionReference.getPermissionReference(MyModel.QNAME_PROP_INFORMATIONSSCHUTZ, TOP_SECRET); private PermissionReference allowRestricted = SimplePermissionReference.getPermissionReference(MyModel.QNAME_PROP_INFORMATIONSSCHUTZ, RESTRICTED); private PermissionReference allowInternal = SimplePermissionReference.getPermissionReference(MyModel.QNAME_PROP_INFORMATIONSSCHUTZ, INTERNAL); @Override public void afterPropertiesSet() throws Exception { logger.debug("Entered afterPropertiesSet"); assert authenticationService != null; assert nodeService != null; assert nspr != null; } @Override public boolean supports(ConfigAttribute arg0) { logger.debug("Entered supports (configAttribute : " + arg0.getAttribute() + ")"); if ((arg0.getAttribute() != null) && (arg0.getAttribute().startsWith(ACL_NODE))) { return true; } else { return false; } } @Override public boolean supports(Class arg0) { logger.debug("Entered supports (class)"); return MethodInvocation.class.isAssignableFrom(arg0); } @Override public int vote(Authentication authentication, Object obj, ConfigAttributeDefinition attributes) { logger.debug("Entered vote: obj = " + obj.toString() + ", config = " + attributes.toString()); // The system user can do everything if (authenticationService.isCurrentUserTheSystemUser()) { logger.debug("system user -> allow"); return ACCESS_GRANTED; } // Find the called method and the applicable config attributes List<ConfigAttributeHelper> supportedDefinitions = this.extractSupportedDefinitions(attributes); MethodInvocation invocation = (MethodInvocation) obj; Method method = invocation.getMethod(); Class[] params = method.getParameterTypes(); // Check for the permissions for (ConfigAttributeHelper attribute : supportedDefinitions) { logger.debug("Processing attribute " + attribute.toString()); // The parameter needs to be interpreted as a node ref if (NodeRef.class.isAssignableFrom(params[attribute.parameter])) { NodeRef node = (NodeRef) invocation.getArguments()[attribute.parameter]; logger.debug("Authorities: " + authorityService.getAuthorities().toString()); // The aspect must be present on the node //if (nodeService.hasAspect(node, MyModel.QNAME_ASPECT_CONFIDENTIALITY)) { if (this.hasConfidentialityAspect(node) == Boolean.TRUE) { String confidentiality = (String) nodeService.getProperty(node, MyModel.QNAME_PROP_INFORMATIONSSCHUTZ); logger.debug("Found node with confidentiality '" + confidentiality+ "'"); // For unrestricted nodes, access is granted no matter what if ("unrestricted".contentEquals(confidentiality)) { return ACCESS_GRANTED; } if (INTERNAL.contentEquals(confidentiality)) { if (permissionService.hasPermission(node, this.allowInternal) != AccessStatus.ALLOWED) { logger.debug("ACCESS DENIED on node: " + nodeService.getProperty(node, nameProp)); } return (permissionService.hasPermission(node, this.allowInternal) == AccessStatus.ALLOWED ? ACCESS_GRANTED : ACCESS_DENIED); } // For restricted nodes, the principal must have the restricted allowed permission if (RESTRICTED.contentEquals(confidentiality)) { if (permissionService.hasPermission(node, this.allowRestricted) != AccessStatus.ALLOWED) { logger.debug("ACCESS DENIED on node: " + nodeService.getProperty(node, nameProp)); } return (permissionService.hasPermission(node, this.allowRestricted) == AccessStatus.ALLOWED ? ACCESS_GRANTED : ACCESS_DENIED); } // For top secret nodes, the principal must have the top secret permission if (TOP_SECRET.contentEquals(confidentiality)) { if (permissionService.hasPermission(node, this.allowTopSecret) != AccessStatus.ALLOWED) { logger.debug("ACCESS DENIED on node: " + nodeService.getProperty(node, nameProp)); } return (permissionService.hasPermission(node, this.allowTopSecret) == AccessStatus.ALLOWED ? ACCESS_GRANTED : ACCESS_DENIED); } } } } // if no match, then abstain logger.debug("No match -> abstain"); return ACCESS_ABSTAIN; } public void setAuthenticationService(AuthenticationService authenticationService) { this.authenticationService = authenticationService; } public AuthenticationService getAuthenticationService() { return authenticationService; } public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public NodeService getNodeService() { return nodeService; } public NamespacePrefixResolver getNamespacePrefixResolver() { return nspr; } public void setNamespacePrefixResolver(NamespacePrefixResolver nspr) { this.nspr = nspr; } public void setAuthorityService(AuthorityService authorityService) { this.authorityService = authorityService; } public AuthorityService getAuthorityService() { return authorityService; } public void setPermissionService(PermissionServiceSPI permissionService) { this.permissionService = permissionService; } public PermissionServiceSPI getPermissionService() { return permissionService; } // Private methods private List<ConfigAttributeHelper> extractSupportedDefinitions(ConfigAttributeDefinition config) { List<ConfigAttributeHelper> definitions = new ArrayList<ConfigAttributeHelper>(2); Iterator iter = config.getConfigAttributes(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); logger.debug("Config attribute: " + attr.getAttribute()); if (this.supports(attr)) { logger.debug("Matched"); definitions.add(new ConfigAttributeHelper(attr)); } } return definitions; } private Boolean hasConfidentialityAspect(final NodeRef node) { //if (nodeService.hasAspect(node, MyModel.QNAME_ASPECT_CONFIDENTIALITY)) return AuthenticationUtil.runAs( new AuthenticationUtil.RunAsWork<Boolean>() { @Override public Boolean doWork() throws Exception { return nodeService.hasAspect(node, MyModel.QNAME_ASPECT_NEEDED); } }, AuthenticationUtil.getSystemUserName()); } private class ConfigAttributeHelper { String attr; String typeString; SimplePermissionReference required; int parameter; String authority; public String toString() { return attr; } ConfigAttributeHelper(ConfigAttribute attr) { logger.debug("Create ConfigAttributeHelper with attr = " + attr.getAttribute()); this.attr = attr.getAttribute(); StringTokenizer st = new StringTokenizer(attr.getAttribute(), ".", false); if (st.countTokens() < 1) { throw new ACLEntryVoterException("There must be at least one token in a config attribute"); } typeString = st.nextToken(); if (!(typeString.equals(ACL_NODE) || typeString.equals(ACL_PARENT) || typeString.equals(ACL_ALLOW) || typeString .equals(ACL_METHOD))) { throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW"); } if (typeString.equals(ACL_NODE) || typeString.equals(ACL_PARENT)) { if (st.countTokens() != 3) { throw new ACLEntryVoterException("There must be four . separated tokens in each config attribute"); } String numberString = st.nextToken(); String qNameString = st.nextToken(); String permissionString = st.nextToken(); parameter = Integer.parseInt(numberString); QName qName = QName.createQName(qNameString, nspr); required = SimplePermissionReference.getPermissionReference(qName, permissionString); } else if (typeString.equals(ACL_METHOD)) { if (st.countTokens() != 1) { throw new ACLEntryVoterException( "There must be two . separated tokens in each group or role config attribute"); } authority = st.nextToken(); } } } }