Summary: TBC
The original source: http://wiki.apache.org/jackrabbit/AccessControl
The 'cached' version of source:
Basic privileges:
- jcr:read The privilege to retrieve a node and get its properties and their values.
- jcr:modifyProperties The privilege to create, remove and modify the values of the properties of a node.
- jcr:addChildNodes The privilege to create child nodes of a node.
- jcr:removeNode The privilege to remove a node.
- jcr:removeChildNodes The privilege to remove child nodes of a node.
- jcr:write An aggregate privilege that contains: jcr:read, jcr:modifyProperties, jcr:addChildNodes, jcr:removeNode, jcr:removeChildNodes
- jcr:all An aggregate privilege that contains all available permissions, including jcr:read, jcr:write and the advanced permssions.
Resource-based ACLs
Advantages:
- fully supported by the JCR API / specification
- very widely available ACL model (eg. file systems)
- simple resource inheritance
- default mechanism in Jackrabbit, no configuration needed
Disadvantages:
- cannot assign ACLs to non-existent nodes
- cumbersome when many users need un-groupable ACLs on a few resources (e.g. "subscriptions"), lots of ACL entries per resource
- permissions are stored right inside the content (can be cumbersome for backups, etc.)
Resource-based ACLs are stored per resource/node in a special child node rep:policy. This one will have a list of rep:GrantACE child nodes (usually named allow, allow0,...) for grant access control entries and rep:DenyACE child nodes (usually named deny, deny0,...) for deny access control entries.
Each ACE node has a rep:principalName STRING property pointing to the user or group this ACE belongs to, and a rep:privileges NAME multi-value property, containing all the privileges of this ACE.
Example for your examination (for both cases: Resource-based, and Principal-based)
AccessControlManager aMgr = session.getAccessControlManager();
// create a privilege set with jcr:all
Privilege[] privileges = new Privilege[] { aMgr.privilegeFromName(Privilege.JCR_ALL) };
AccessControlList acl;
try {
// get first applicable policy (for nodes w/o a policy)
acl = aMgr.getApplicablePolicies(path).nextAccessControlPolicy();
} catch (NoSuchElementException e) {
// else node already has a policy, get that one
acl = aMgr.getPolicies(path)[0];
}
// remove all existing entries
for (AccessControlEntry e : acl.getAccessControlEntries()) {
acl.removeAccessControlEntry(e);
}
// add a new one for the special "everyone" principal
acl.addAccessControlEntry(EveryonePrincipal.getInstance(), privileges);
// the policy must be re-set
aMgr.setPolicy(path, acl);
// and the session must be saved for the changes to be applied
session.save();
Principal-based ACLs
Advantages:
- permissions can be assigned to non-existent nodes
- permissions are stored separately from the content (good for content replication, backup etc.)
- good for having many users with un-groupable ACLs (e.g. "subscriptions"); resources don't get filled up with ACL entries
Disadvantages:
- additional Jackrabbit API has to be used for setting ACLs
- modeling resource inheritance requires more ACLs than resource-based
An access control list (rep:ACL) is stored for each user and group (this is transparent, currently it's mirroring the users's home path at /rep:accesscontrol//rep:policy/ ). This consists of entries (rep:ACE), which are either allow (rep:GrantACE) or deny (rep:DenyACE) entries.
The rep:ACE nodetype (used by both resource- and principal-based ACLs) defines the following two properties for principal-based usage. These exact same names need to be used as restrictions when using the Jackrabbit API (JackrabbitAccessControlList.addEntry()):
- rep:nodePath defines the (base) path of a subtree the ACL applies to (mandatory, PATH property)
- rep:glob defines a glob pattern to restrict the subtree, both child nodes & properties (only a path matching is done) (optional, STRING property)
For the glob pattern, see http://jackrabbit.apache.org/api/2.2/org/apache/jackrabbit/core/security/authorization/GlobPattern.html (NodePath is the rep:nodePath and restriction is the rep:glob).
// usual entry point into the Jackrabbit API
JackrabbitSession js = (JackrabbitSession) session;
// get user/principal for whom to read/set ACLs
// Note: the ACL security API works using Java Principals as high-level abstraction and does not
// assume the users are actually stored in the JCR with the Jackrabbit UserManagement; an example
// are external users provided by a custom LoginModule via LDAP
PrincipalManager pMgr = js.getPrincipalManager();
Principal principal = pMgr.getPrincipal(session.getUserID());
// alternatively: get the current user as Authorizable from the user management
// (there is a one-to-one mapping between Authorizables and Principals)
User user = ((User) js.getUserManager().getAuthorizable(session.getUserID()));
Principal principal = user.getPrincipal();
// get the Jackrabbit access control manager
JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) session.getAccessControlManager();
JackrabbitAccessControlPolicy[] ps = acMgr.getPolicies(principal); // or getApplicablePolicies()
JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];
// list entries
JackrabbitAccessControlEntry[] entries = (JackrabbitAccessControlEntry[]) list.getAccessControlEntries();
JackrabbitAccessControlEntry entry = entries[0];
// remove entry
list.removeAccessControlEntry(entry);
// add entry
Privilege[] privileges = new Privileges[] { acMgr.privilegeFromName(Privilege.JCR_READ) };
Map restrictions = new HashMap();
ValueFactory vf = session.getValueFactory();
restrictions.put("rep:nodePath", vf.createValue("/some/path", PropertyType.PATH));
restrictions.put("rep:glob", vf.createValue("*"));
list.addEntry(principal, privileges, true /* allow or deny */, restrictions);
// reorder entries
list.orderBefore(entry, entry2);
// finally set policy again & save
acMgr.setPolicy(list.getPath(), list);
session.save();
