diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml
index 47fd76a876..82632ceeef 100644
--- a/config/alfresco/application-context.xml
+++ b/config/alfresco/application-context.xml
@@ -40,7 +40,8 @@
-
+
+
diff --git a/config/alfresco/simple-permissions-context.xml b/config/alfresco/simple-permissions-context.xml
new file mode 100644
index 0000000000..7b24feb515
--- /dev/null
+++ b/config/alfresco/simple-permissions-context.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ read
+ write
+ delete
+ shimmy
+ shake
+
+
+
+
diff --git a/source/java/org/alfresco/repo/avm/util/RawServices.java b/source/java/org/alfresco/repo/avm/util/RawServices.java
index 04214acd9e..1f3f1c1629 100644
--- a/source/java/org/alfresco/repo/avm/util/RawServices.java
+++ b/source/java/org/alfresco/repo/avm/util/RawServices.java
@@ -9,6 +9,8 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.MimetypeService;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.simple.permission.CapabilityRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -58,6 +60,16 @@ public class RawServices implements ApplicationContextAware
*/
private LookupCache fLookupCache;
+ /**
+ * The Authority Service.
+ */
+ private AuthorityService fAuthorityService;
+
+ /**
+ * The CapabilityRegistry.
+ */
+ private CapabilityRegistry fCapabilityRegistry;
+
/**
* Default constructor.
*/
@@ -135,6 +147,25 @@ public class RawServices implements ApplicationContextAware
return fLookupCache;
}
+ public AuthorityService getAuthorityService()
+ {
+ if (fAuthorityService == null)
+ {
+ // TODO change this back to the unwrapped bean before production.
+ fAuthorityService = (AuthorityService)fContext.getBean("AuthorityService");
+ }
+ return fAuthorityService;
+ }
+
+ public CapabilityRegistry getCapabilityRegistry()
+ {
+ if (fCapabilityRegistry == null)
+ {
+ fCapabilityRegistry = (CapabilityRegistry)fContext.getBean("capabilityRegistry");
+ }
+ return fCapabilityRegistry;
+ }
+
public ApplicationContext getContext()
{
return fContext;
diff --git a/source/java/org/alfresco/repo/simple/permission/ACLImpl.java b/source/java/org/alfresco/repo/simple/permission/ACLImpl.java
new file mode 100644
index 0000000000..5cab211fc4
--- /dev/null
+++ b/source/java/org/alfresco/repo/simple/permission/ACLImpl.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing
+ */
+
+package org.alfresco.repo.simple.permission;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.repo.avm.util.RawServices;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.AuthorityType;
+import org.alfresco.service.simple.permission.ACL;
+import org.alfresco.service.simple.permission.CapabilityRegistry;
+
+/**
+ * Basic implementation of an ACL
+ * @author britt
+ */
+public class ACLImpl implements ACL
+{
+ private static final long serialVersionUID = 5184311729355811095L;
+
+ /**
+ * The allowed entries for users.
+ */
+ private Map> fUserAllows;
+
+ /**
+ * The allowed entries for groups.
+ */
+ private Map> fGroupAllows;
+
+ /**
+ * The denied entries for users.
+ */
+ private Map> fUserDenies;
+
+ /**
+ * The denied entries for groups.
+ */
+ private Map> fGroupDenies;
+
+ /**
+ * Bit indicating whether a child (however that is defined)
+ * should inherit these permissions.
+ */
+ private boolean fInherit;
+
+ private transient AuthorityService fAuthorityService;
+
+ private transient CapabilityRegistry fCapabilityRegistry;
+
+ private transient String fStringRep;
+
+ public ACLImpl(boolean inherit)
+ {
+ fAuthorityService = RawServices.Instance().getAuthorityService();
+ fCapabilityRegistry = RawServices.Instance().getCapabilityRegistry();
+ fUserAllows = new HashMap>();
+ fGroupAllows = new HashMap>();
+ fUserDenies = new HashMap>();
+ fGroupDenies = new HashMap>();
+ fInherit = inherit;
+ fStringRep = null;
+ }
+
+ public ACLImpl(String stringRep)
+ {
+ this(true);
+ fStringRep = stringRep;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.ACL#allow(java.lang.String, java.lang.String[])
+ */
+ public void allow(String agent, String... capabilities)
+ {
+ digest();
+ AuthorityType type = AuthorityType.getAuthorityType(agent);
+ if (type == AuthorityType.ADMIN)
+ {
+ return;
+ }
+ Set capDenied = null;
+ Set capAllowed = null;
+ switch (type)
+ {
+ case EVERYONE :
+ case GROUP :
+ {
+ capDenied = fGroupDenies.get(agent);
+ capAllowed = fGroupAllows.get(agent);
+ if (capAllowed == null)
+ {
+ capAllowed = new HashSet();
+ 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();
+ fUserAllows.put(agent, capAllowed);
+ }
+ break;
+ }
+ default :
+ {
+ // ignore.
+ return;
+ }
+ }
+ if (capDenied != null)
+ {
+ for (String cap : capabilities)
+ {
+ capDenied.remove(cap);
+ capAllowed.add(cap);
+ }
+ }
+ else
+ {
+ for (String cap : capabilities)
+ {
+ capAllowed.add(cap);
+ }
+ }
+ }
+
+ private void digestMap(String mapRep, Map> map)
+ {
+ 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 caps = new HashSet();
+ 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()
+ {
+ if (fStringRep == null)
+ {
+ return;
+ }
+ String[] segments = fStringRep.split("\\|");
+ fInherit = segments[0].equals("i") ? true : false;
+ digestMap(segments[1], fUserAllows);
+ digestMap(segments[2], fUserDenies);
+ digestMap(segments[3], fGroupAllows);
+ digestMap(segments[4], fGroupDenies);
+ fStringRep = null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.ACL#can(java.lang.String, java.lang.String)
+ */
+ public boolean can(String agent, String capability)
+ {
+ digest();
+ AuthorityType type = AuthorityType.getAuthorityType(agent);
+ // Admin trumps all.
+ if (type == AuthorityType.ADMIN)
+ {
+ return true;
+ }
+ // Next check for denied entries that apply.
+ Set denied = fUserDenies.get(agent);
+ if (denied == null)
+ {
+ denied = new HashSet();
+ }
+ Set containing = fAuthorityService.getContainingAuthorities(null, agent, false);
+ Set found = fGroupDenies.get(agent);
+ if (found != null)
+ {
+ denied.addAll(found);
+ }
+ for (String container : containing)
+ {
+ found = fGroupDenies.get(container);
+ if (found != null)
+ {
+ denied.addAll(found);
+ }
+ }
+ if (denied.contains(capability))
+ {
+ return false;
+ }
+ // Now go look for the alloweds.
+ Set allowed = fUserAllows.get(agent);
+ if (allowed == null)
+ {
+ allowed = new HashSet();
+ }
+ 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 allowed.contains(capability);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.ACL#deny(java.lang.String, java.lang.String[])
+ */
+ public void deny(String agent, String ... capabilities)
+ {
+ digest();
+ AuthorityType type = AuthorityType.getAuthorityType(agent);
+ if (type == AuthorityType.ADMIN)
+ {
+ return;
+ }
+ Set allowed = fUserAllows.get(agent);
+ if (allowed != null)
+ {
+ for (String cap : capabilities)
+ {
+ allowed.remove(cap);
+ }
+ }
+ allowed = fGroupAllows.get(agent);
+ if (allowed != null)
+ {
+ for (String cap : capabilities)
+ {
+ allowed.remove(cap);
+ }
+ }
+ Set denied = null;
+ switch (type)
+ {
+ case EVERYONE :
+ case GROUP :
+ {
+ denied = fGroupDenies.get(agent);
+ if (denied == null)
+ {
+ denied = new HashSet();
+ fGroupDenies.put(agent, denied);
+ }
+ break;
+ }
+ case OWNER :
+ case USER :
+ case GUEST :
+ {
+ denied = fUserDenies.get(agent);
+ if (denied == null)
+ {
+ denied = new HashSet();
+ fUserDenies.put(agent, denied);
+ }
+ break;
+ }
+ default :
+ {
+ // Cop Out!
+ return;
+ }
+ }
+ for (String cap : capabilities)
+ {
+ denied.add(cap);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.ACL#getCapabilities(java.lang.String)
+ */
+ public Set getCapabilities(String agent)
+ {
+ digest();
+ AuthorityType type = AuthorityType.getAuthorityType(agent);
+ if (type == AuthorityType.ADMIN)
+ {
+ return fCapabilityRegistry.getAll();
+ }
+ // First add in all the possible capabilities from the allow sets.
+ Set capabilities = new HashSet();
+ Set found = fUserAllows.get(agent);
+ if (found != null)
+ {
+ capabilities.addAll(found);
+ }
+ found = fGroupAllows.get(agent);
+ if (found != null)
+ {
+ capabilities.addAll(found);
+ }
+ Set containers = fAuthorityService.getContainingAuthorities(null, agent, false);
+ for (String container : containers)
+ {
+ found = fGroupAllows.get(container);
+ if (found != null)
+ {
+ capabilities.addAll(found);
+ }
+ }
+ // Now remove everything that's denied.
+ found = fUserDenies.get(agent);
+ if (found != null)
+ {
+ capabilities.removeAll(found);
+ }
+ found = fGroupDenies.get(agent);
+ if (found != null)
+ {
+ capabilities.removeAll(found);
+ }
+ for (String container : containers)
+ {
+ found = fGroupDenies.get(container);
+ if (found != null)
+ {
+ capabilities.removeAll(found);
+ }
+ }
+ return capabilities;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.ACL#getStringRepresentation()
+ */
+ public String getStringRepresentation()
+ {
+ if (fStringRep != null)
+ {
+ return fStringRep;
+ }
+ StringBuilder builder = new StringBuilder();
+ builder.append(fInherit ? 'i' : 'n');
+ builder.append('|');
+ int count = 0;
+ for (Map.Entry> entry : fUserAllows.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++ < fUserAllows.size() - 1)
+ {
+ builder.append(':');
+ }
+ }
+ builder.append('|');
+ count = 0;
+ for (Map.Entry> entry : fUserDenies.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++ < fUserDenies.size() - 1)
+ {
+ builder.append(':');
+ }
+ }
+ builder.append('|');
+ count = 0;
+ for (Map.Entry> 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> 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(':');
+ }
+ }
+ return builder.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.ACL#inherits()
+ */
+ public boolean inherits()
+ {
+ return fInherit;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString()
+ {
+ return "[" + getStringRepresentation() + "]";
+ }
+}
diff --git a/source/java/org/alfresco/repo/simple/permission/ACLTest.java b/source/java/org/alfresco/repo/simple/permission/ACLTest.java
new file mode 100644
index 0000000000..14b62aae28
--- /dev/null
+++ b/source/java/org/alfresco/repo/simple/permission/ACLTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing
+ */
+
+package org.alfresco.repo.simple.permission;
+
+import org.alfresco.repo.security.authentication.AuthenticationComponent;
+import org.alfresco.service.cmr.security.AuthenticationService;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.AuthorityType;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.simple.permission.ACL;
+import org.alfresco.service.simple.permission.CapabilityRegistry;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+import junit.framework.TestCase;
+
+/**
+ * Rudimentary test of ACLs.
+ * @author britt
+ */
+public class ACLTest extends TestCase
+{
+ private static FileSystemXmlApplicationContext fContext = null;
+
+ private static PersonService fPersonService;
+
+ private static AuthorityService fAuthorityService;
+
+ private static AuthenticationService fAuthenticationService;
+
+ private static AuthenticationComponent fAuthenticationComponent;
+
+ private static CapabilityRegistry fCapabilityRegistry;
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+ protected void setUp() throws Exception
+ {
+ if (fContext == null)
+ {
+ fContext = new FileSystemXmlApplicationContext("config/alfresco/application-context.xml");
+ fPersonService = (PersonService)fContext.getBean("PersonService");
+ fAuthorityService = (AuthorityService)fContext.getBean("AuthorityService");
+ fAuthenticationService = (AuthenticationService)fContext.getBean("AuthenticationService");
+ fAuthenticationComponent = (AuthenticationComponent)fContext.getBean("AuthenticationComponent");
+ fAuthenticationComponent.setSystemUserAsCurrentUser();
+ fCapabilityRegistry = (CapabilityRegistry)fContext.getBean("capabilityRegistry");
+ }
+ // Set up sample users groups and roles.
+ fAuthenticationService.createAuthentication("Buffy", "Buffy".toCharArray());
+ fPersonService.getPerson("Buffy");
+ fAuthorityService.createAuthority(AuthorityType.GROUP, null, "Scoobies");
+ fAuthorityService.addAuthority("GROUP_Scoobies", "Buffy");
+ fAuthenticationService.createAuthentication("Willow", "Willow".toCharArray());
+ fPersonService.getPerson("Willow");
+ fAuthorityService.addAuthority("GROUP_Scoobies", "Willow");
+ fAuthenticationService.createAuthentication("Xander", "Xander".toCharArray());
+ fPersonService.getPerson("Xander");
+ fAuthorityService.addAuthority("GROUP_Scoobies", "Xander");
+ fAuthenticationService.createAuthentication("Tara", "Tara".toCharArray());
+ fPersonService.getPerson("Tara");
+ fAuthenticationService.createAuthentication("Spike", "Spike".toCharArray());
+ fPersonService.getPerson("Spike");
+ fAuthorityService.createAuthority(AuthorityType.GROUP, null, "vampires");
+ fAuthorityService.addAuthority("GROUP_vampires", "Spike");
+ fAuthorityService.createAuthority(AuthorityType.GROUP, null, "soulless");
+ fAuthorityService.addAuthority("GROUP_soulless", "Spike");
+ }
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception
+ {
+ fAuthenticationService.deleteAuthentication("Buffy");
+ fAuthenticationService.deleteAuthentication("Willow");
+ fAuthenticationService.deleteAuthentication("Xander");
+ fAuthenticationService.deleteAuthentication("Tara");
+ fAuthenticationService.deleteAuthentication("Spike");
+ fPersonService.deletePerson("Buffy");
+ fPersonService.deletePerson("Willow");
+ fPersonService.deletePerson("Tara");
+ fPersonService.deletePerson("Xander");
+ fPersonService.deletePerson("Spike");
+ fAuthorityService.deleteAuthority("GROUP_Scoobies");
+ fAuthorityService.deleteAuthority("GROUP_vampires");
+ fAuthorityService.deleteAuthority("GROUP_soulless");
+ }
+
+ public void testBasic()
+ {
+ try
+ {
+ System.out.println(fCapabilityRegistry.getAll());
+ ACL acl = new ACLImpl(true);
+ acl.allow("GROUP_Scoobies", "read", "write", "delete", "shimmy");
+ acl.deny("Xander", "delete");
+ acl.allow("Tara", "shake");
+ acl.allow("GROUP_vampires", "read", "write", "delete", "shimmy", "shake");
+ acl.deny("Spike", "shake");
+ acl.deny("GROUP_soulless", "delete");
+ System.out.println(acl.getCapabilities("Spike"));
+ System.out.println(acl.getCapabilities("Tara"));
+ System.out.println(acl.getCapabilities("Xander"));
+ System.out.println(acl.getCapabilities("Buffy"));
+ String stringRep = acl.getStringRepresentation();
+ System.out.println(stringRep);
+ ACL acl2 = new ACLImpl(stringRep);
+ System.out.println(acl2.getStringRepresentation());
+ System.out.println(acl2.getCapabilities("Spike"));
+ System.out.println(acl2.getCapabilities("Tara"));
+ System.out.println(acl2.getCapabilities("Xander"));
+ System.out.println(acl2.getCapabilities("Buffy"));
+ System.out.println(acl2.getStringRepresentation());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail();
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/simple/permission/CapabilityRegistryImpl.java b/source/java/org/alfresco/repo/simple/permission/CapabilityRegistryImpl.java
new file mode 100644
index 0000000000..60e56cb057
--- /dev/null
+++ b/source/java/org/alfresco/repo/simple/permission/CapabilityRegistryImpl.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing
+ */
+
+package org.alfresco.repo.simple.permission;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.service.simple.permission.CapabilityRegistry;
+
+/**
+ * Basic implementation of a capability registry.
+ * @author britt
+ */
+public class CapabilityRegistryImpl implements CapabilityRegistry
+{
+ private Map fIDToCapability;
+
+ private Map fCapabilityToID;
+
+ public CapabilityRegistryImpl()
+ {
+ fIDToCapability = new HashMap();
+ fCapabilityToID = new HashMap();
+ }
+
+ public void setCapabilities(Set capabilities)
+ {
+ int count = 0;
+ for (String cap : capabilities)
+ {
+ Integer id = count++;
+ fIDToCapability.put(id, cap);
+ fCapabilityToID.put(cap, id);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.CapabilityRegistry#addCapability(java.lang.String)
+ */
+ public void addCapability(String capability)
+ {
+ // TODO Make this do something in the future.
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.CapabilityRegistry#getAll()
+ */
+ public Set getAll()
+ {
+ return fCapabilityToID.keySet();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.CapabilityRegistry#getCapabilityID(java.lang.String)
+ */
+ public int getCapabilityID(String capability)
+ {
+ Integer id = fCapabilityToID.get(capability);
+ if (id == null)
+ {
+ return -1;
+ }
+ return id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.CapabilityRegistry#getCapabilityName(int)
+ */
+ public String getCapabilityName(int id)
+ {
+ return fIDToCapability.get(id);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.simple.permission.CapabilityRegistry#removeCapability(java.lang.String)
+ */
+ public void removeCapability(String capability)
+ {
+ // TODO Make this persistent.
+ Integer removed = fCapabilityToID.remove(capability);
+ fIDToCapability.remove(removed);
+ }
+}
diff --git a/source/java/org/alfresco/service/simple/permission/ACL.java b/source/java/org/alfresco/service/simple/permission/ACL.java
new file mode 100644
index 0000000000..bfe6f2c2e7
--- /dev/null
+++ b/source/java/org/alfresco/service/simple/permission/ACL.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing
+ */
+
+package org.alfresco.service.simple.permission;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 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
+ * 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
+ * the capability. Entries that deny override any entries that allow.
+ * @author britt
+ */
+public interface ACL extends Serializable
+{
+ /**
+ * Insert an allow entry for the agent, capabilities combination.
+ * Removes a denials explicitly for the agent and capabilities given.
+ * @param agent The agent, (user, group, role)
+ * @param capabilities The capabilities being granted.
+ */
+ public void allow(String agent, String ... capabilities);
+
+ /**
+ * Insert a deny entry for the agent, capabilities combination.
+ * Removes an allow explicitly for the agent and capabilities given.
+ * @param agent The agent, (user, group, role)
+ * @param capabilities
+ */
+ public void deny(String agent, String ... capabilities);
+
+ /**
+ * Does the given agent have the given capability
+ * @param agent The agent (user)
+ * @param capability The capability.
+ * @return Whether the agent can.
+ */
+ public boolean can(String agent, String capability);
+
+ /**
+ * Get the capabilities for the given agent.
+ * @param agent The agent.
+ * @return A set of capabilities.
+ */
+ public Set getCapabilities(String agent);
+
+ /**
+ * Get a string representation of this ACL, suitable for persistence.
+ * @return The string representation.
+ */
+ public String getStringRepresentation();
+
+ /**
+ * Should this ACL be inherited.
+ * @return Whether it should.
+ */
+ public boolean inherits();
+}
diff --git a/source/java/org/alfresco/service/simple/permission/CapabilityRegistry.java b/source/java/org/alfresco/service/simple/permission/CapabilityRegistry.java
new file mode 100644
index 0000000000..fa4994f028
--- /dev/null
+++ b/source/java/org/alfresco/service/simple/permission/CapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing
+ */
+
+package org.alfresco.service.simple.permission;
+
+import java.util.Set;
+
+/**
+ * Interface for a registry of capabilities.
+ * @author britt
+ */
+public interface CapabilityRegistry
+{
+ /**
+ * Get all known capabilities.
+ * @return A list of all the capabilities.
+ */
+ public Set getAll();
+
+ /**
+ * Get the integer id corresponding to the given capability.
+ * @return The id.
+ */
+ public int getCapabilityID(String capability);
+
+ /**
+ * Get the name of a capability from it's unique id.
+ * @param id
+ * @return The capability name or null if the id is invalid.
+ */
+ public String getCapabilityName(int id);
+
+ /**
+ * Add a capability.
+ * @param capability
+ */
+ public void addCapability(String capability);
+
+ /**
+ * Remove a capability from the system.
+ * @param capability
+ */
+ public void removeCapability(String capability);
+}
diff --git a/source/java/org/alfresco/service/simple/permission/SimplePermissionService.java b/source/java/org/alfresco/service/simple/permission/SimplePermissionService.java
new file mode 100644
index 0000000000..d15d72a68b
--- /dev/null
+++ b/source/java/org/alfresco/service/simple/permission/SimplePermissionService.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing
+ */
+
+package org.alfresco.service.simple.permission;
+
+import java.util.List;
+
+/**
+ * Interface for a simple permission mechanism.
+ * Nothing but String valued capabilities, and ACLs.
+ * @author britt
+ */
+public interface SimplePermissionService
+{
+ /**
+ * Can the current user perform the action indicated by the capability.
+ * @param capability The capability: marker for an ability to perform an action
+ * governed by an ACL.
+ * @param acl The ACL. If this is null then the permission is granted.
+ * @param owner The owner. The owner can always has the "changepermission" capability.
+ * @return Whether permission is granted.
+ */
+ boolean can(String capability, ACL acl, String owner);
+
+ /**
+ * Can the user (agent) specified perform the action indicated by the capability.
+ * @param agent The agent (user) to check.
+ * @param capability The capability to check.
+ * @param acl The ACL. If this is null then the permission is granted.
+ * @param owner The owner.
+ * @return Whether permission is granted.
+ */
+ boolean can(String agent, String capability, ACL acl, String owner);
+
+ /**
+ * Get the capabilities that this acl grants the current user.
+ * @param acl The ACL.
+ * @param owner The owner of the controlled entity.
+ * @return A list of capabilities.
+ */
+ List getCapabilities(ACL acl, String owner);
+
+ /**
+ * Get the capabilities that this agent grants the specifiec agent.
+ * @param agent The agent (user).
+ * @param acl The ACL.
+ * @param owner The owner of the controlled entity.
+ * @return A list of capabilities.
+ */
+ List getCapabilities(String agent, ACL acl, String owner);
+}