package org.argeo.jcr.security; import java.security.Principal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.security.AccessControlList; import javax.jcr.security.AccessControlManager; import javax.jcr.security.AccessControlPolicy; import javax.jcr.security.AccessControlPolicyIterator; import javax.jcr.security.Privilege; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.jcr.JcrUtils; import org.argeo.util.security.SimplePrincipal; /** Apply authorizations to a JCR repository. */ public class JcrAuthorizations implements Runnable { private final static Log log = LogFactory.getLog(JcrAuthorizations.class); private Repository repository; private String workspace = null; /** * key := privilege1,privilege2/path/to/node
* value := group1,group2,user1 */ private Map principalPrivileges = new HashMap(); public void run() { Session session = null; try { session = repository.login(workspace); initAuthorizations(session); } catch (Exception e) { JcrUtils.discardQuietly(session); } finally { JcrUtils.logoutQuietly(session); } } /** @deprecated call {@link #run()} instead. */ @Deprecated public void init() { run(); } protected void initAuthorizations(Session session) throws RepositoryException { AccessControlManager acm = session.getAccessControlManager(); for (String privileges : principalPrivileges.keySet()) { String path = null; int slashIndex = privileges.indexOf('/'); if (slashIndex == 0) { throw new ArgeoException("Privilege " + privileges + " badly formatted it starts with /"); } else if (slashIndex > 0) { path = privileges.substring(slashIndex); privileges = privileges.substring(0, slashIndex); } if (path == null) path = "/"; List privs = new ArrayList(); for (String priv : privileges.split(",")) { privs.add(acm.privilegeFromName(priv)); } String principalNames = principalPrivileges.get(privileges); for (String principalName : principalNames.split(",")) { Principal principal = getOrCreatePrincipal(session, principalName); addPrivileges(session, principal, path, privs); } } session.save(); } /** * Returns a {@link SimplePrincipal}, does not check whether it exists since * such capabilities is not provided by the standard JCR API. Can be * overridden to provide smarter handling */ protected Principal getOrCreatePrincipal(Session session, String principalName) throws RepositoryException { return new SimplePrincipal(principalName); } public static void addPrivileges(Session session, Principal principal, String path, List privs) throws RepositoryException { AccessControlManager acm = session.getAccessControlManager(); // search for an access control list AccessControlList acl = null; AccessControlPolicyIterator policyIterator = acm .getApplicablePolicies(path); if (policyIterator.hasNext()) { while (policyIterator.hasNext()) { AccessControlPolicy acp = policyIterator .nextAccessControlPolicy(); if (acp instanceof AccessControlList) acl = ((AccessControlList) acp); } } else { AccessControlPolicy[] existingPolicies = acm.getPolicies(path); for (AccessControlPolicy acp : existingPolicies) { if (acp instanceof AccessControlList) acl = ((AccessControlList) acp); } } if (acl != null) { acl.addAccessControlEntry(principal, privs.toArray(new Privilege[privs.size()])); acm.setPolicy(path, acl); if (log.isDebugEnabled()) { StringBuffer buf = new StringBuffer(""); for (int i = 0; i < privs.size(); i++) { if (i != 0) buf.append(','); buf.append(privs.get(i).getName()); } log.debug("Added privilege(s) '" + buf + "' to '" + principal.getName() + "' on " + path + " from workspace '" + session.getWorkspace().getName() + "'"); } } else { throw new ArgeoException("Don't know how to apply privileges " + privs + " to " + principal + " on " + path + " from workspace '" + session.getWorkspace().getName() + "'"); } } @Deprecated public void setGroupPrivileges(Map groupPrivileges) { this.principalPrivileges = groupPrivileges; } public void setPrincipalPrivileges(Map principalPrivileges) { this.principalPrivileges = principalPrivileges; } public void setRepository(Repository repository) { this.repository = repository; } public void setWorkspace(String workspace) { this.workspace = workspace; } }