Start generalizing LDIF/LDAP user admin
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 4 Sep 2015 10:01:12 +0000 (10:01 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 4 Sep 2015 10:01:12 +0000 (10:01 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8363 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractLdapUserAdmin.java
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifGroup.java
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminAggregator.java [new file with mode: 0644]
org.argeo.security.core/src/org/argeo/osgi/useradmin/cm/LdapUserAdminFactory.java [new file with mode: 0644]

index df2ad4e8ad86d4402341d99051780dc590b06aeb..254e5423c272e2972ceb98eeb9961cf81eb747e7 100644 (file)
@@ -10,6 +10,8 @@ public abstract class AbstractLdapUserAdmin implements UserAdmin {
        private boolean isReadOnly;
        private URI uri;
 
+       private UserAdmin externalRoles;
+
        public AbstractLdapUserAdmin() {
        }
 
@@ -45,8 +47,20 @@ public abstract class AbstractLdapUserAdmin implements UserAdmin {
                return isReadOnly;
        }
 
+       public void init() {
+
+       }
+
        public void destroy() {
 
        }
 
+       UserAdmin getExternalRoles() {
+               return externalRoles;
+       }
+
+       public void setExternalRoles(UserAdmin externalRoles) {
+               this.externalRoles = externalRoles;
+       }
+
 }
index 4154d55a74ffec26983324055449d80ff55eebae..fbc678c52c7589e9484967d3352d48f76a7368b7 100644 (file)
@@ -15,13 +15,24 @@ public class LdifGroup extends LdifUser implements Group {
        // optimisation
        List<Role> directMembers = null;
 
+       private String memberAttrName = "member";
+
        public LdifGroup(LdapName dn, Attributes attributes) {
                super(dn, attributes);
        }
 
        @Override
        public boolean addMember(Role role) {
-               throw new UnsupportedOperationException();
+               Attribute member = getAttributes().get(memberAttrName);
+               if (member != null) {
+                       if (member.contains(role.getName()))
+                               return false;
+               } else
+                       getAttributes().put(memberAttrName, role.getName());
+               directMembers.add(role);
+               if (role instanceof LdifUser)
+                       ((LdifUser) role).directMemberOf.add(this);
+               return true;
        }
 
        @Override
@@ -31,7 +42,17 @@ public class LdifGroup extends LdifUser implements Group {
 
        @Override
        public boolean removeMember(Role role) {
-               throw new UnsupportedOperationException();
+               Attribute member = getAttributes().get(memberAttrName);
+               if (member != null) {
+                       if (!member.contains(role.getName()))
+                               return false;
+                       member.remove(role.getName());
+                       directMembers.remove(role);
+                       if (role instanceof LdifUser)
+                               ((LdifUser) role).directMemberOf.remove(this);
+                       return true;
+               } else
+                       return false;
        }
 
        @Override
@@ -41,7 +62,7 @@ public class LdifGroup extends LdifUser implements Group {
                else
                        throw new ArgeoUserAdminException("Members have not been loaded.");
 
-               // Attribute memberAttribute = getAttributes().get("member");
+               // Attribute memberAttribute = getAttributes().get(memberAttrName);
                // if (memberAttribute == null)
                // return new Role[0];
                // try {
@@ -57,24 +78,24 @@ public class LdifGroup extends LdifUser implements Group {
                // }
        }
 
-       void loadMembers(LdifUserAdmin userAdmin) {
-               directMembers = new ArrayList<Role>();
-               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);
-               }
-       }
+//     void loadMembers(LdifUserAdmin userAdmin) {
+//             directMembers = new ArrayList<Role>();
+//             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 role found for "
+//                                             + ldapName);
+//                     role.directMemberOf.add(this);
+//                     directMembers.add(role);
+//             }
+//     }
 
        List<LdapName> getMemberNames() {
-               Attribute memberAttribute = getAttributes().get("member");
+               Attribute memberAttribute = getAttributes().get(memberAttrName);
                if (memberAttribute == null)
                        return new ArrayList<LdapName>();
                try {
@@ -99,4 +120,10 @@ public class LdifGroup extends LdifUser implements Group {
        public int getType() {
                return GROUP;
        }
+
+       public String getMemberAttrName() {
+               return memberAttrName;
+       }
+       
+       
 }
index b1e9ceb49808a26f88ede1b0c56c004575fb731b..dacae7964f1ee74a24415529655fbd7940133a44 100644 (file)
@@ -14,7 +14,9 @@ import java.util.TreeMap;
 import javax.naming.InvalidNameException;
 import javax.naming.NamingEnumeration;
 import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
 import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
 
 import org.osgi.framework.Filter;
 import org.osgi.framework.FrameworkUtil;
@@ -46,11 +48,6 @@ public class LdifUserAdmin extends AbstractLdapUserAdmin {
                        throw new UnsupportedOperationException(getUri().getScheme()
                                        + "not supported read-write.");
 
-               try {
-                       load(getUri().toURL().openStream());
-               } catch (Exception e) {
-                       throw new ArgeoUserAdminException("Cannot open URL " + getUri(), e);
-               }
        }
 
        public LdifUserAdmin(InputStream in) {
@@ -59,6 +56,14 @@ public class LdifUserAdmin extends AbstractLdapUserAdmin {
                setUri(null);
        }
 
+       public void init() {
+               try {
+                       load(getUri().toURL().openStream());
+               } catch (Exception e) {
+                       throw new ArgeoUserAdminException("Cannot open URL " + getUri(), e);
+               }
+       }
+
        protected void load(InputStream in) {
                try {
                        LdifParser ldifParser = new LdifParser();
@@ -81,7 +86,7 @@ public class LdifUserAdmin extends AbstractLdapUserAdmin {
 
                        // optimise
                        for (LdifGroup group : groups.values())
-                               group.loadMembers(this);
+                               loadMembers(group);
 
                        // indexes
                        for (String attr : getIndexedUserProperties())
@@ -140,12 +145,60 @@ public class LdifUserAdmin extends AbstractLdapUserAdmin {
 
        @Override
        public Role createRole(String name, int type) {
-               throw new UnsupportedOperationException();
+               try {
+                       LdapName dn = new LdapName(name);
+                       if (users.containsKey(dn) || groups.containsKey(dn))
+                               throw new ArgeoUserAdminException("Already a role " + name);
+
+                       BasicAttributes attrs = new BasicAttributes();
+                       attrs.put("dn", dn.toString());
+                       Rdn nameRdn = dn.getRdn(dn.size() - 1);
+                       // TODO deal with multiple attr RDN
+                       attrs.put(nameRdn.getType(), nameRdn.getValue());
+                       LdifUser newRole;
+                       if (type == Role.USER) {
+                               newRole = new LdifUser(dn, attrs);
+                               users.put(dn, newRole);
+                       } else if (type == Role.GROUP) {
+                               newRole = new LdifGroup(dn, attrs);
+                               groups.put(dn, (LdifGroup) newRole);
+                       } else
+                               throw new ArgeoUserAdminException("Unsupported type " + type);
+                       return newRole;
+               } catch (InvalidNameException e) {
+                       throw new ArgeoUserAdminException("Cannot create role " + name, e);
+               }
        }
 
        @Override
        public boolean removeRole(String name) {
-               throw new UnsupportedOperationException();
+               try {
+                       LdapName dn = new LdapName(name);
+                       LdifUser role = null;
+                       if (users.containsKey(dn))
+                               role = users.remove(dn);
+                       else if (groups.containsKey(dn))
+                               role = groups.remove(dn);
+                       else
+                               throw new ArgeoUserAdminException("There is no role " + name);
+                       if (role == null)
+                               return false;
+                       for (LdifGroup group : role.directMemberOf) {
+                               group.directMembers.remove(role);
+                               group.getAttributes().get(group.getMemberAttrName())
+                                               .remove(dn.toString());
+                       }
+                       if (role instanceof LdifGroup) {
+                               LdifGroup group = (LdifGroup) role;
+                               for (Role user : group.directMembers) {
+                                       if (user instanceof LdifUser)
+                                               ((LdifUser) user).directMemberOf.remove(group);
+                               }
+                       }
+                       return true;
+               } catch (InvalidNameException e) {
+                       throw new ArgeoUserAdminException("Cannot create role " + name, e);
+               }
        }
 
        @Override
@@ -199,4 +252,25 @@ public class LdifUserAdmin extends AbstractLdapUserAdmin {
                // throw new UnsupportedOperationException();
        }
 
+       protected void loadMembers(LdifGroup group) {
+               group.directMembers = new ArrayList<Role>();
+               for (LdapName ldapName : group.getMemberNames()) {
+                       LdifUser role = null;
+                       if (groups.containsKey(ldapName))
+                               role = groups.get(ldapName);
+                       else if (users.containsKey(ldapName))
+                               role = users.get(ldapName);
+                       else {
+                               if (getExternalRoles() != null)
+                                       role = (LdifUser) getExternalRoles().getRole(
+                                                       ldapName.toString());
+                               if (role == null)
+                                       throw new ArgeoUserAdminException("No role found for "
+                                                       + ldapName);
+                       }
+                       role.directMemberOf.add(group);
+                       group.directMembers.add(role);
+               }
+       }
+
 }
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminAggregator.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminAggregator.java
new file mode 100644 (file)
index 0000000..9113117
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.osgi.useradmin;
+
+import org.osgi.service.useradmin.UserAdmin;
+
+public interface UserAdminAggregator {
+       public void addUserAdmin(String baseDn, UserAdmin userAdmin);
+
+       public void removeUserAdmin(String baseDn);
+}
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/cm/LdapUserAdminFactory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/cm/LdapUserAdminFactory.java
new file mode 100644 (file)
index 0000000..64fdea0
--- /dev/null
@@ -0,0 +1,53 @@
+package org.argeo.osgi.useradmin.cm;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.argeo.osgi.useradmin.AbstractLdapUserAdmin;
+import org.argeo.osgi.useradmin.ArgeoUserAdminException;
+import org.argeo.osgi.useradmin.LdapUserAdmin;
+import org.argeo.osgi.useradmin.LdifUserAdmin;
+import org.argeo.osgi.useradmin.UserAdminAggregator;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+public class LdapUserAdminFactory implements ManagedServiceFactory {
+       private final UserAdminAggregator userAdminAggregator;
+
+       private Map<String, String> index = new HashMap<String, String>();
+
+       public LdapUserAdminFactory(UserAdminAggregator userAdminAggregator) {
+               this.userAdminAggregator = userAdminAggregator;
+       }
+
+       @Override
+       public String getName() {
+               return "LDAP/LDIF User Source";
+       }
+
+       @Override
+       public synchronized void updated(String pid,
+                       Dictionary<String, ?> properties) throws ConfigurationException {
+               String baseDn = properties.get("baseDn").toString();
+               String userAdminUri = properties.get("uri").toString();
+               AbstractLdapUserAdmin userAdmin;
+               if (userAdminUri.startsWith("ldap"))
+                       userAdmin = new LdapUserAdmin(userAdminUri);
+               else
+                       userAdmin = new LdifUserAdmin(userAdminUri);
+               userAdminAggregator.addUserAdmin(baseDn, userAdmin);
+               index.put(pid, baseDn);
+       }
+
+       @Override
+       public synchronized void deleted(String pid) {
+               if (index.containsKey(pid))
+                       userAdminAggregator.removeUserAdmin(index.get(pid));
+               else
+                       throw new ArgeoUserAdminException("No user admin registered for "
+                                       + pid);
+               index.remove(pid);
+       }
+
+}