From 3439a3b6aba14618b06c72cf59b220e216135c96 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Mon, 24 Aug 2015 19:23:42 +0000 Subject: [PATCH] Add Authorization, with chained groups git-svn-id: https://svn.argeo.org/commons/trunk@8337 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../osgi/useradmin/BasicTestConstants.java | 2 + .../osgi/useradmin/LdifUserAdminTest.java | 23 +++++++- .../test/org/argeo/osgi/useradmin/basic.ldif | 10 +++- .../osgi/useradmin/LdifAuthorization.java | 54 +++++++++++++++++++ .../org/argeo/osgi/useradmin/LdifGroup.java | 49 +++++++++++++++-- .../org/argeo/osgi/useradmin/LdifUser.java | 30 +++++++++-- .../argeo/osgi/useradmin/LdifUserAdmin.java | 23 +++++--- 7 files changed, 173 insertions(+), 18 deletions(-) create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java index f608cce86..56c9b92cd 100644 --- a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java +++ b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/BasicTestConstants.java @@ -2,5 +2,7 @@ package org.argeo.osgi.useradmin; interface BasicTestConstants { final static String ROOT_USER_DN = "uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org"; + final static String DEMO_USER_DN = "uid=demo,ou=People,dc=demo,dc=example,dc=org"; final static String ADMIN_GROUP_DN = "cn=admin,ou=Roles,dc=demo,dc=example,dc=org"; + final static String EDITOR_GROUP_DN = "cn=editor,ou=Roles,dc=demo,dc=example,dc=org"; } diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java index 75a58d0d3..c2d5b31f0 100644 --- a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java +++ b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java @@ -1,7 +1,11 @@ package org.argeo.osgi.useradmin; +import java.util.Arrays; +import java.util.List; + import junit.framework.TestCase; +import org.osgi.service.useradmin.Authorization; import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; @@ -13,10 +17,27 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { .getResourceAsStream("basic.ldif")); User rootUser = (User) userAdmin.getRole(ROOT_USER_DN); assertNotNull(rootUser); + User demoUser = (User) userAdmin.getRole(DEMO_USER_DN); + assertNotNull(demoUser); + Group adminGroup = (Group) userAdmin.getRole(ADMIN_GROUP_DN); assertNotNull(adminGroup); Role[] members = adminGroup.getMembers(); assertEquals(1, members.length); - assertEquals(rootUser.getName(), members[0].getName()); + assertEquals(rootUser, members[0]); + + Group editorGroup = (Group) userAdmin.getRole(EDITOR_GROUP_DN); + assertNotNull(editorGroup); + members = editorGroup.getMembers(); + assertEquals(2, members.length); + assertEquals(adminGroup, members[0]); + assertEquals(demoUser, members[1]); + + Authorization rootAuth = userAdmin.getAuthorization(rootUser); + List rootRoles = Arrays.asList(rootAuth.getRoles()); + assertEquals(3, rootRoles.size()); + assertTrue(rootRoles.contains(ROOT_USER_DN)); + assertTrue(rootRoles.contains(ADMIN_GROUP_DN)); + assertTrue(rootRoles.contains(EDITOR_GROUP_DN)); } } diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif index 380311f4d..56c7499b2 100644 --- a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif +++ b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/basic.ldif @@ -44,4 +44,12 @@ dn: cn=admin,ou=Roles,dc=demo,dc=example,dc=org objectClass: groupOfNames objectClass: top cn: admin -member: uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org \ No newline at end of file +member: uid=root+cn=Super Admin,ou=People,dc=demo,dc=example,dc=org + +dn: cn=editor,ou=Roles,dc=demo,dc=example,dc=org +objectClass: groupOfNames +objectClass: top +cn: admin +member: cn=admin,ou=Roles,dc=demo,dc=example,dc=org +member: uid=demo,ou=People,dc=demo,dc=example,dc=org + diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java new file mode 100644 index 000000000..4ae2434b4 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifAuthorization.java @@ -0,0 +1,54 @@ +package org.argeo.osgi.useradmin; + +import java.util.ArrayList; +import java.util.List; + +import org.osgi.service.useradmin.Authorization; +import org.osgi.service.useradmin.Role; + +public class LdifAuthorization implements Authorization { + private final LdifUser user; + + public LdifAuthorization(LdifUser user) { + this.user = user; + } + + @Override + public String getName() { + return user.getName(); + } + + @Override + public boolean hasRole(String name) { + for (Role role : getAllRoles()) { + if (role.getName().equals(name)) + return true; + } + return false; + } + + @Override + public String[] getRoles() { + List allRoles = getAllRoles(); + String[] res = new String[allRoles.size() + 1]; + res[0] = user.getName(); + for (int i = 0; i < allRoles.size(); i++) + res[i + 1] = allRoles.get(i).getName(); + return res; + } + + List getAllRoles() { + List allRoles = new ArrayList(); + collectRoles(user, allRoles); + return allRoles; + } + + private void collectRoles(LdifUser user, List allRoles) { + for (LdifGroup group : user.directMemberOf) { + // TODO check for loops + allRoles.add(group); + collectRoles(group, allRoles); + } + } + +} diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java index c2c666700..845094820 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java @@ -12,6 +12,8 @@ import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; public class LdifGroup extends LdifUser implements Group { + // optimisation + List directMembers = null; public LdifGroup(LdapName dn, Attributes attributes) { super(dn, attributes); @@ -34,17 +36,55 @@ public class LdifGroup extends LdifUser implements Group { @Override public Role[] getMembers() { + if (directMembers != null) + return directMembers.toArray(new Role[directMembers.size()]); + else + throw new ArgeoUserAdminException("Members have not been loaded."); + + // Attribute memberAttribute = getAttributes().get("member"); + // if (memberAttribute == null) + // return new Role[0]; + // try { + // List roles = new ArrayList(); + // NamingEnumeration values = memberAttribute.getAll(); + // while (values.hasMore()) { + // LdapName dn = new LdapName(values.next().toString()); + // roles.add(new LdifUser(dn, null)); + // } + // return roles.toArray(new Role[roles.size()]); + // } catch (Exception e) { + // throw new ArgeoUserAdminException("Cannot get members", e); + // } + } + + void loadMembers(LdifUserAdmin userAdmin) { + directMembers = new ArrayList(); + for (LdapName ldapName : getMemberNames()) { + LdifUser role; + if (userAdmin.groups.containsKey(ldapName)) + role = userAdmin.groups.get(ldapName); + else if (userAdmin.users.containsKey(ldapName)) + role = userAdmin.users.get(ldapName); + else + throw new ArgeoUserAdminException("No roel found for " + + ldapName); + role.directMemberOf.add(this); + directMembers.add(role); + } + } + + List getMemberNames() { Attribute memberAttribute = getAttributes().get("member"); if (memberAttribute == null) - return new Role[0]; + return new ArrayList(); try { - List roles = new ArrayList(); + List roles = new ArrayList(); NamingEnumeration values = memberAttribute.getAll(); while (values.hasMore()) { LdapName dn = new LdapName(values.next().toString()); - roles.add(new LdifUser(dn, null)); + roles.add(dn); } - return roles.toArray(new Role[roles.size()]); + return roles; } catch (Exception e) { throw new ArgeoUserAdminException("Cannot get members", e); } @@ -59,5 +99,4 @@ public class LdifGroup extends LdifUser implements Group { public int getType() { return GROUP; } - } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java index 1de18c5b4..379ac23ab 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java @@ -1,17 +1,20 @@ package org.argeo.osgi.useradmin; +import java.util.ArrayList; import java.util.Dictionary; -import java.util.Hashtable; +import java.util.List; import javax.naming.directory.Attributes; import javax.naming.ldap.LdapName; import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; class LdifUser implements User { + // optimisation + List directMemberOf = new ArrayList(); + private final LdapName dn; - private final Attributes attributes; + private Attributes attributes; LdifUser(LdapName dn, Attributes attributes) { this.dn = dn; @@ -56,4 +59,25 @@ class LdifUser implements User { return attributes; } + @Override + public int hashCode() { + return dn.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj instanceof LdifUser) { + LdifUser that = (LdifUser) obj; + return this.dn.equals(that.dn); + } + return false; + } + + @Override + public String toString() { + return dn.toString(); + } + } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java index 5796b46c4..440e93d9d 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java @@ -16,7 +16,8 @@ import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; public class LdifUserAdmin implements UserAdmin { - private SortedMap roles = new TreeMap(); + SortedMap users = new TreeMap(); + SortedMap groups = new TreeMap(); public LdifUserAdmin(InputStream in) { try { @@ -29,14 +30,19 @@ public class LdifUserAdmin implements UserAdmin { objectClasses: while (objectClasses.hasMore()) { String objectClass = objectClasses.next().toString(); if (objectClass.equals("inetOrgPerson")) { - roles.put(key, new LdifUser(key, attributes)); + users.put(key, new LdifUser(key, attributes)); break objectClasses; } else if (objectClass.equals("groupOfNames")) { - roles.put(key, new LdifGroup(key, attributes)); + groups.put(key, new LdifGroup(key, attributes)); break objectClasses; } } } + + // optimise + for (LdifGroup group : groups.values()) { + group.loadMembers(this); + } } catch (Exception e) { throw new ArgeoUserAdminException( "Cannot initialise user admin service from LDIF", e); @@ -54,15 +60,16 @@ public class LdifUserAdmin implements UserAdmin { + name, e); } - if (!roles.containsKey(key)) - return null; - return roles.get(key); + if (groups.containsKey(key)) + return groups.get(key); + if (users.containsKey(key)) + return users.get(key); + return null; } @Override public Authorization getAuthorization(User user) { - // TODO Auto-generated method stub - return null; + return new LdifAuthorization((LdifUser) user); } @Override -- 2.30.2