Light weight ACLs point checkin.

Inverted structure of authority to capability maps. Faster and simpler.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6769 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2007-09-12 18:07:37 +00:00
parent 2511644075
commit e99a9a0d3d
4 changed files with 271 additions and 338 deletions

View File

@@ -37,154 +37,104 @@ import org.alfresco.service.simple.permission.ACL;
import org.alfresco.service.simple.permission.CapabilityRegistry; import org.alfresco.service.simple.permission.CapabilityRegistry;
/** /**
* Basic implementation of an ACL * Basic implementation of a simple ACL.
* @author britt * @author britt
*/ */
public class ACLImpl implements ACL public class ACLImpl implements ACL
{ {
private static final long serialVersionUID = 5184311729355811095L; private static final long serialVersionUID = -8720314753104805631L;
/**
* Map of capabilities to authorities allowed.
*/
private Map<String, Set<String>> fAllowed;
/**
* Map of capabilities to authorities denied.
*/
private Map<String, Set<String>> fDenied;
/** /**
* The allowed entries for users. * Should this ACL be inherited.
*/
private Map<String, Set<String>> fUserAllows;
/**
* The allowed entries for groups.
*/
private Map<String, Set<String>> fGroupAllows;
/**
* The denied entries for users.
*/
private Map<String, Set<String>> fUserDenies;
/**
* The denied entries for groups.
*/
private Map<String, Set<String>> fGroupDenies;
/**
* Bit indicating whether a child (however that is defined)
* should inherit these permissions.
*/ */
private boolean fInherit; private boolean fInherit;
/**
* String (compact) representation of ACL.
*/
private String fStringRep;
/**
* Reference to the authority service.
*/
private transient AuthorityService fAuthorityService; private transient AuthorityService fAuthorityService;
/**
* Reference to the capability registry.
*/
private transient CapabilityRegistry fCapabilityRegistry; private transient CapabilityRegistry fCapabilityRegistry;
private transient String fStringRep; /**
* Initialize a brand new one.
* @param inherit Should this ACL be inherited.
*/
public ACLImpl(boolean inherit) public ACLImpl(boolean inherit)
{ {
fInherit = inherit;
fAuthorityService = RawServices.Instance().getAuthorityService(); fAuthorityService = RawServices.Instance().getAuthorityService();
fCapabilityRegistry = RawServices.Instance().getCapabilityRegistry(); fCapabilityRegistry = RawServices.Instance().getCapabilityRegistry();
fUserAllows = new HashMap<String, Set<String>>(); fAllowed = new HashMap<String, Set<String>>();
fGroupAllows = new HashMap<String, Set<String>>(); fDenied = new HashMap<String, Set<String>>();
fUserDenies = new HashMap<String, Set<String>>();
fGroupDenies = new HashMap<String, Set<String>>();
fInherit = inherit;
fStringRep = null; fStringRep = null;
} }
public ACLImpl(String stringRep) /**
* Initialize from an external string representation.
* @param rep
*/
public ACLImpl(String rep)
{ {
this(true); this(true);
fStringRep = stringRep; fStringRep = rep;
}
public ACLImpl(ACL other)
{
this(true);
fStringRep = other.getStringRepresentation();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.ACL#allow(java.lang.String, java.lang.String[]) * @see org.alfresco.service.simple.permission.ACL#allow(java.lang.String, java.lang.String[])
*/ */
public void allow(String agent, String... capabilities) public void allow(String capability, String... authorities)
{ {
digest(); digest();
AuthorityType type = AuthorityType.getAuthorityType(agent); // First remove any explicit denies.
if (type == AuthorityType.ADMIN) Set<String> denied = fDenied.get(capability);
if (denied != null)
{ {
return; for (String authority : authorities)
}
Set<String> capDenied = null;
Set<String> capAllowed = null;
switch (type)
{
case EVERYONE :
case GROUP :
{ {
capDenied = fGroupDenies.get(agent); denied.remove(authority);
capAllowed = fGroupAllows.get(agent);
if (capAllowed == null)
{
capAllowed = new HashSet<String>();
fGroupAllows.put(agent, capAllowed);
}
break;
}
case ADMIN :
case USER :
case OWNER :
{
capDenied = fUserDenies.get(agent);
capAllowed = fUserAllows.get(agent);
if (capAllowed == null)
{
capAllowed = new HashSet<String>();
fUserAllows.put(agent, capAllowed);
}
break;
}
default :
{
// ignore.
return;
} }
} }
if (capDenied != null) // Add the authorities to the allowed list.
Set<String> allowed = fAllowed.get(capability);
if (allowed == null)
{ {
for (String cap : capabilities) allowed = new HashSet<String>();
{ fAllowed.put(capability, allowed);
capDenied.remove(cap);
capAllowed.add(cap);
}
} }
else for (String authority : authorities)
{ {
for (String cap : capabilities) allowed.add(authority);
{
capAllowed.add(cap);
}
} }
} }
private void digestMap(String mapRep, Map<String, Set<String>> map) /**
{ * Helper to decode from the string representation.
String[] segments = mapRep.split(":"); */
if (segments.length == 0 || segments[0].equals(""))
{
return;
}
for (String segment : segments)
{
String[] entrySeg = segment.split(";");
if (entrySeg.length == 0 || entrySeg[0].equals(""))
{
continue;
}
Set<String> caps = new HashSet<String>();
map.put(entrySeg[0], caps);
for (int i = 1; i < entrySeg.length; ++i)
{
String cap = fCapabilityRegistry.getCapabilityName(Integer.parseInt(entrySeg[i], 16));
if (cap == null)
{
continue;
}
caps.add(cap);
}
}
}
private void digest() private void digest()
{ {
if (fStringRep == null) if (fStringRep == null)
@@ -192,186 +142,209 @@ public class ACLImpl implements ACL
return; return;
} }
String[] segments = fStringRep.split("\\|"); String[] segments = fStringRep.split("\\|");
fInherit = segments[0].equals("i") ? true : false; fInherit = segments[0].equals("i");
digestMap(segments[1], fUserAllows); digestMap(segments[1], fAllowed);
digestMap(segments[2], fUserDenies); digestMap(segments[2], fDenied);
digestMap(segments[3], fGroupAllows);
digestMap(segments[4], fGroupDenies);
fStringRep = null; fStringRep = null;
} }
/* (non-Javadoc) /**
* @see org.alfresco.service.simple.permission.ACL#can(java.lang.String, java.lang.String) * Sub helper for decoding string representation.
* @param string The partial string representation.
* @param map The map to update.
*/ */
public boolean can(String agent, String capability) private void digestMap(String rep, Map<String, Set<String>> map)
{
String[] segments = rep.split(":");
if (segments.length == 0 || segments[0].equals(""))
{
// This means there are no explicit entries.
return;
}
for (String entryRep : segments)
{
String[] entryRegs = entryRep.split(";");
String capability = fCapabilityRegistry.getCapabilityName(Integer.parseInt(entryRegs[0], 16));
Set<String> authorities = new HashSet<String>();
map.put(capability, authorities);
for (int i = 1; i < entryRegs.length; ++i)
{
authorities.add(entryRegs[i]);
}
}
}
/* (non-Javadoc)
* @see org.alfresco.service.simple.permission.ACL#can(java.lang.String, boolean, java.lang.String)
*/
public boolean can(String authority, boolean isOwner, String capability)
{ {
digest(); digest();
AuthorityType type = AuthorityType.getAuthorityType(agent); AuthorityType type = AuthorityType.getAuthorityType(authority);
// Admin trumps all. // Admin trumps.
if (type == AuthorityType.ADMIN) if (type == AuthorityType.ADMIN)
{ {
return true; return true;
} }
// Next check for denied entries that apply. // Look for denies first.
Set<String> denied = fUserDenies.get(agent); Set<String> denied = fDenied.get(capability);
if (denied == null) if (denied != null)
{ {
denied = new HashSet<String>(); if (denied.contains(authority))
}
Set<String> containing = fAuthorityService.getContainingAuthorities(null, agent, false);
Set<String> found = fGroupDenies.get(agent);
if (found != null)
{
denied.addAll(found);
}
for (String container : containing)
{
found = fGroupDenies.get(container);
if (found != null)
{ {
denied.addAll(found); return false;
}
for (String auth : denied)
{
if (fAuthorityService.getContainedAuthorities(null, auth, false).contains(authority))
{
return false;
}
} }
} }
if (denied.contains(capability)) // Now look for allows.
Set<String> allowed = fAllowed.get(capability);
if (allowed != null)
{ {
return false; if (allowed.contains(authority))
}
// Now go look for the alloweds.
Set<String> allowed = fUserAllows.get(agent);
if (allowed == null)
{
allowed = new HashSet<String>();
}
found = fGroupAllows.get(agent);
if (found != null)
{
allowed.addAll(found);
}
for (String container : containing)
{
found = fGroupAllows.get(container);
if (found != null)
{ {
allowed.addAll(found); return true;
}
for (String auth : allowed)
{
if (fAuthorityService.getContainedAuthorities(null, auth, false).contains(authority))
{
return true;
}
} }
} }
return allowed.contains(capability); return false;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.ACL#deny(java.lang.String, java.lang.String[]) * @see org.alfresco.service.simple.permission.ACL#deny(java.lang.String, java.lang.String[])
*/ */
public void deny(String agent, String ... capabilities) public void deny(String capability, String ... authorities)
{ {
digest(); digest();
AuthorityType type = AuthorityType.getAuthorityType(agent); // Remove corresponding explicit allows.
if (type == AuthorityType.ADMIN) Set<String> allowed = fAllowed.get(capability);
{
return;
}
Set<String> allowed = fUserAllows.get(agent);
if (allowed != null) if (allowed != null)
{ {
for (String cap : capabilities) for (String authority : authorities)
{ {
allowed.remove(cap); allowed.remove(authority);
} }
} }
allowed = fGroupAllows.get(agent); // Now add denies.
if (allowed != null) Set<String> denied = fDenied.get(capability);
if (denied == null)
{ {
for (String cap : capabilities) denied = new HashSet<String>();
{ fDenied.put(capability, denied);
allowed.remove(cap);
}
} }
Set<String> denied = null; for (String authority : authorities)
switch (type)
{ {
case EVERYONE : if (AuthorityType.getAuthorityType(authority) == AuthorityType.ADMIN)
case GROUP :
{ {
denied = fGroupDenies.get(agent); continue;
if (denied == null)
{
denied = new HashSet<String>();
fGroupDenies.put(agent, denied);
}
break;
} }
case OWNER : denied.add(authority);
case USER :
case GUEST :
{
denied = fUserDenies.get(agent);
if (denied == null)
{
denied = new HashSet<String>();
fUserDenies.put(agent, denied);
}
break;
}
default :
{
// Cop Out!
return;
}
}
for (String cap : capabilities)
{
denied.add(cap);
} }
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.ACL#getCapabilities(java.lang.String) * @see org.alfresco.service.simple.permission.ACL#getAllowed(java.lang.String)
*/ */
public Set<String> getCapabilities(String agent) public Set<String> getAllowed(String capability)
{ {
digest(); digest();
AuthorityType type = AuthorityType.getAuthorityType(agent); Set<String> allowed = new HashSet<String>();
allowed.add(AuthorityType.ADMIN.getFixedString());
// Add the explicitly allowed.
Set<String> expAllowed = fAllowed.get(capability);
if (expAllowed == null)
{
return allowed;
}
allowed.addAll(expAllowed);
for (String authority : expAllowed)
{
allowed.addAll(fAuthorityService.getContainedAuthorities(null, authority, false));
}
// Now remove based on denials.
Set<String> denied = fDenied.get(capability);
if (denied == null)
{
return allowed;
}
allowed.removeAll(denied);
// Now those that are indirectly denied.
for (String authority : denied)
{
allowed.removeAll(fAuthorityService.getContainedAuthorities(null, authority, false));
}
return allowed;
}
/* (non-Javadoc)
* @see org.alfresco.service.simple.permission.ACL#getCapabilities(java.lang.String, boolean)
*/
public Set<String> getCapabilities(String authority, boolean isOwner)
{
digest();
AuthorityType type = AuthorityType.getAuthorityType(authority);
if (type == AuthorityType.ADMIN) if (type == AuthorityType.ADMIN)
{ {
return fCapabilityRegistry.getAll(); return fCapabilityRegistry.getAll();
} }
// First add in all the possible capabilities from the allow sets.
Set<String> capabilities = new HashSet<String>(); Set<String> capabilities = new HashSet<String>();
Set<String> found = fUserAllows.get(agent); // First run through the allowed entries.
if (found != null) Set<String> containers = null;
for (Map.Entry<String, Set<String>> entry : fAllowed.entrySet())
{ {
capabilities.addAll(found); if (entry.getValue().contains(authority))
}
found = fGroupAllows.get(agent);
if (found != null)
{
capabilities.addAll(found);
}
Set<String> containers = fAuthorityService.getContainingAuthorities(null, agent, false);
for (String container : containers)
{
found = fGroupAllows.get(container);
if (found != null)
{ {
capabilities.addAll(found); capabilities.add(entry.getKey());
continue;
}
if (containers == null)
{
containers = fAuthorityService.getContainingAuthorities(null, authority, false);
}
for (String auth : containers)
{
if (entry.getValue().contains(auth))
{
capabilities.add(entry.getKey());
break;
}
} }
} }
// Now remove everything that's denied. // Now go through the denials.
found = fUserDenies.get(agent); for (Map.Entry<String, Set<String>> entry : fDenied.entrySet())
if (found != null)
{ {
capabilities.removeAll(found); if (!capabilities.contains(entry.getKey()))
}
found = fGroupDenies.get(agent);
if (found != null)
{
capabilities.removeAll(found);
}
for (String container : containers)
{
found = fGroupDenies.get(container);
if (found != null)
{ {
capabilities.removeAll(found); continue;
}
Set<String> denied = entry.getValue();
if (denied.contains(authority))
{
capabilities.remove(entry.getKey());
continue;
}
if (containers == null)
{
containers = fAuthorityService.getContainingAuthorities(null, authority, false);
}
for (String auth : containers)
{
if (denied.contains(auth))
{
capabilities.remove(entry.getKey());
break;
}
} }
} }
return capabilities; return capabilities;
@@ -390,72 +363,30 @@ public class ACLImpl implements ACL
builder.append(fInherit ? 'i' : 'n'); builder.append(fInherit ? 'i' : 'n');
builder.append('|'); builder.append('|');
int count = 0; int count = 0;
for (Map.Entry<String, Set<String>> entry : fUserAllows.entrySet()) for (Map.Entry<String, Set<String>> entry : fAllowed.entrySet())
{ {
builder.append(entry.getKey()); builder.append(Integer.toString(fCapabilityRegistry.getCapabilityID(entry.getKey()), 16));
if (entry.getValue().size() != 0) for (String authority : entry.getValue())
{ {
for (String cap : entry.getValue()) builder.append(';');
{ builder.append(authority);
builder.append(';');
builder.append(Integer.toString(fCapabilityRegistry.getCapabilityID(cap), 16));
}
} }
if (count++ < fUserAllows.size() - 1) if (count++ < fAllowed.size() - 1)
{ {
builder.append(':'); builder.append(':');
} }
} }
builder.append('|'); builder.append('|');
count = 0; count = 0;
for (Map.Entry<String, Set<String>> entry : fUserDenies.entrySet()) for (Map.Entry<String, Set<String>> entry : fDenied.entrySet())
{ {
builder.append(entry.getKey()); builder.append(Integer.toString(fCapabilityRegistry.getCapabilityID(entry.getKey()), 16));
if (entry.getValue().size() != 0) for (String authority : entry.getValue())
{ {
for (String cap : entry.getValue()) builder.append(';');
{ builder.append(authority);
builder.append(';');
builder.append(Integer.toString(fCapabilityRegistry.getCapabilityID(cap), 16));
}
} }
if (count++ < fUserDenies.size() - 1) if (count++ < fDenied.size() - 1)
{
builder.append(':');
}
}
builder.append('|');
count = 0;
for (Map.Entry<String, Set<String>> entry : fGroupAllows.entrySet())
{
builder.append(entry.getKey());
if (entry.getValue().size() != 0)
{
for (String cap : entry.getValue())
{
builder.append(';');
builder.append(Integer.toString(fCapabilityRegistry.getCapabilityID(cap), 16));
}
}
if (count++ < fGroupAllows.size() - 1)
{
builder.append(':');
}
}
builder.append('|');
count = 0;
for (Map.Entry<String, Set<String>> entry : fGroupDenies.entrySet())
{
builder.append(entry.getKey());
if (entry.getValue().size() != 0)
{
for (String cap : entry.getValue())
{
builder.append(';');
builder.append(Integer.toString(fCapabilityRegistry.getCapabilityID(cap), 16));
}
}
if (count++ < fGroupDenies.size() - 1)
{ {
builder.append(':'); builder.append(':');
} }
@@ -468,15 +399,7 @@ public class ACLImpl implements ACL
*/ */
public boolean inherits() public boolean inherits()
{ {
digest();
return fInherit; return fInherit;
} }
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "[" + getStringRepresentation() + "]";
}
} }

View File

@@ -116,24 +116,25 @@ public class ACLTest extends TestCase
{ {
System.out.println(fCapabilityRegistry.getAll()); System.out.println(fCapabilityRegistry.getAll());
ACL acl = new ACLImpl(true); ACL acl = new ACLImpl(true);
acl.allow("GROUP_Scoobies", "read", "write", "delete", "shimmy"); acl.allow("read", "GROUP_Scoobies", "GROUP_vampires");
acl.deny("Xander", "delete"); acl.allow("write", "GROUP_Scoobies", "GROUP_vampires");
acl.allow("Tara", "shake"); acl.allow("delete", "GROUP_Scoobies", "GROUP_vampires");
acl.allow("GROUP_vampires", "read", "write", "delete", "shimmy", "shake"); acl.allow("shimmy", "GROUP_Scoobies", "GROUP_vampires");
acl.deny("Spike", "shake"); acl.allow("shake", "GROUP_vampires", "Tara");
acl.deny("GROUP_soulless", "delete"); acl.deny("delete", "Xander", "GROUP_soulless");
System.out.println(acl.getCapabilities("Spike")); acl.deny("shake", "Spike");
System.out.println(acl.getCapabilities("Tara")); System.out.println(acl.getCapabilities("Spike", false));
System.out.println(acl.getCapabilities("Xander")); System.out.println(acl.getCapabilities("Tara", false));
System.out.println(acl.getCapabilities("Buffy")); System.out.println(acl.getCapabilities("Xander", false));
System.out.println(acl.getCapabilities("Buffy", false));
String stringRep = acl.getStringRepresentation(); String stringRep = acl.getStringRepresentation();
System.out.println(stringRep); System.out.println(stringRep);
ACL acl2 = new ACLImpl(stringRep); ACL acl2 = new ACLImpl(stringRep);
System.out.println(acl2.getStringRepresentation()); System.out.println(acl2.getStringRepresentation());
System.out.println(acl2.getCapabilities("Spike")); System.out.println(acl2.getCapabilities("Spike", false));
System.out.println(acl2.getCapabilities("Tara")); System.out.println(acl2.getCapabilities("Tara", false));
System.out.println(acl2.getCapabilities("Xander")); System.out.println(acl2.getCapabilities("Xander", false));
System.out.println(acl2.getCapabilities("Buffy")); System.out.println(acl2.getCapabilities("Buffy", false));
System.out.println(acl2.getStringRepresentation()); System.out.println(acl2.getStringRepresentation());
} }
catch (Exception e) catch (Exception e)

View File

@@ -26,6 +26,7 @@
package org.alfresco.repo.simple.permission; package org.alfresco.repo.simple.permission;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -61,7 +62,7 @@ public class CapabilityRegistryImpl implements CapabilityRegistry
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.CapabilityRegistry#addCapability(java.lang.String) * @see org.alfresco.service.simple.permission.CapabilityRegistry#addCapability(java.lang.String)
*/ */
public void addCapability(String capability) public synchronized void addCapability(String capability)
{ {
// TODO Make this do something in the future. // TODO Make this do something in the future.
} }
@@ -69,15 +70,15 @@ public class CapabilityRegistryImpl implements CapabilityRegistry
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.CapabilityRegistry#getAll() * @see org.alfresco.service.simple.permission.CapabilityRegistry#getAll()
*/ */
public Set<String> getAll() public synchronized Set<String> getAll()
{ {
return fCapabilityToID.keySet(); return new HashSet<String>(fCapabilityToID.keySet());
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.CapabilityRegistry#getCapabilityID(java.lang.String) * @see org.alfresco.service.simple.permission.CapabilityRegistry#getCapabilityID(java.lang.String)
*/ */
public int getCapabilityID(String capability) public synchronized int getCapabilityID(String capability)
{ {
Integer id = fCapabilityToID.get(capability); Integer id = fCapabilityToID.get(capability);
if (id == null) if (id == null)
@@ -90,7 +91,7 @@ public class CapabilityRegistryImpl implements CapabilityRegistry
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.CapabilityRegistry#getCapabilityName(int) * @see org.alfresco.service.simple.permission.CapabilityRegistry#getCapabilityName(int)
*/ */
public String getCapabilityName(int id) public synchronized String getCapabilityName(int id)
{ {
return fIDToCapability.get(id); return fIDToCapability.get(id);
} }
@@ -98,7 +99,7 @@ public class CapabilityRegistryImpl implements CapabilityRegistry
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.simple.permission.CapabilityRegistry#removeCapability(java.lang.String) * @see org.alfresco.service.simple.permission.CapabilityRegistry#removeCapability(java.lang.String)
*/ */
public void removeCapability(String capability) public synchronized void removeCapability(String capability)
{ {
// TODO Make this persistent. // TODO Make this persistent.
Integer removed = fCapabilityToID.remove(capability); Integer removed = fCapabilityToID.remove(capability);

View File

@@ -26,12 +26,11 @@
package org.alfresco.service.simple.permission; package org.alfresco.service.simple.permission;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
* Interface for ACLs. ACLs express the capabilities granted to * Interface for ACLs. ACLs express the capabilities granted to
* different agents (users, groups, or roles (one hopes that roles can go away as they are * different authorities (users, groups, or roles (one hopes that roles can go away as they are
* operationally just another name for a group)). ACLs contain explicit entries made of * operationally just another name for a group)). ACLs contain explicit entries made of
* a capability and a list of agents plus an indication of whether the entry denies or allows * a capability and a list of agents plus an indication of whether the entry denies or allows
* the capability. Entries that deny override any entries that allow. * the capability. Entries that deny override any entries that allow.
@@ -40,35 +39,44 @@ import java.util.Set;
public interface ACL extends Serializable public interface ACL extends Serializable
{ {
/** /**
* Insert an allow entry for the agent, capabilities combination. * Insert an allow entry.
* Removes a denials explicitly for the agent and capabilities given. * Removes any denials explicitly for the authorities and capability given.
* @param agent The agent, (user, group, role) * @param capability The capability to grant.
* @param capabilities The capabilities being granted. * @param authorities The authorities granted the capability.
*/ */
public void allow(String agent, String ... capabilities); public void allow(String capability, String ... authorities);
/** /**
* Insert a deny entry for the agent, capabilities combination. * Insert a deny entry.
* Removes an allow explicitly for the agent and capabilities given. * Removes any allows explicitly for the authorities and capability given.
* @param agent The agent, (user, group, role) * @param capability The capability to deny.
* @param capabilities * @param authorities The authorities to deny.
*/ */
public void deny(String agent, String ... capabilities); public void deny(String capability, String ... authorities);
/** /**
* Does the given agent have the given capability * Does the given authority have the given capability
* @param agent The agent (user) * @param authority The authority (user)
* @param isOwner Is the authority the owner of the controlled entity.
* @param capability The capability. * @param capability The capability.
* @return Whether the agent can. * @return Whether the authority can.
*/ */
public boolean can(String agent, String capability); public boolean can(String authority, boolean isOwner, String capability);
/** /**
* Get the capabilities for the given agent. * Get the capabilities for the given authority.
* @param agent The agent. * @param authority The authority.
* @param isOwner is the authority the owner of the controlled entity.
* @return A set of capabilities. * @return A set of capabilities.
*/ */
public Set<String> getCapabilities(String agent); public Set<String> getCapabilities(String authority, boolean isOwner);
/**
* Get the authorities with the given capability.
* @param capability The capability under consideration.
* @return The set of authorities.
*/
public Set<String> getAllowed(String capability);
/** /**
* Get a string representation of this ACL, suitable for persistence. * Get a string representation of this ACL, suitable for persistence.