]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java
Improve LDIF user admin.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / NodeUserAdmin.java
index d8dcf0e361ae842a0e02c95885e36a58b79c276c..31295ae89fac8f58b04fe3ba0ed78247a229c086 100644 (file)
@@ -1,31 +1,46 @@
 package org.argeo.cms.internal.kernel;
 
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
+import javax.transaction.TransactionManager;
 
-import org.argeo.osgi.useradmin.ArgeoUserAdminException;
-import org.argeo.osgi.useradmin.UserAdminAggregator;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.KernelHeader;
+import org.argeo.osgi.useradmin.LdapUserAdmin;
+import org.argeo.osgi.useradmin.LdifUserAdmin;
+import org.argeo.osgi.useradmin.UserAdminConf;
+import org.argeo.osgi.useradmin.UserDirectory;
+import org.argeo.osgi.useradmin.UserDirectoryException;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.useradmin.Authorization;
 import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
-public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
+public class NodeUserAdmin implements UserAdmin {
+       private final static Log log = LogFactory.getLog(NodeUserAdmin.class);
        final static LdapName ROLES_BASE;
        static {
                try {
-                       ROLES_BASE = new LdapName(KernelConstants.ROLES_BASEDN);
+                       ROLES_BASE = new LdapName(KernelHeader.ROLES_BASEDN);
                } catch (InvalidNameException e) {
-                       throw new ArgeoUserAdminException("Cannot initialize "
+                       throw new UserDirectoryException("Cannot initialize "
                                        + NodeUserAdmin.class, e);
                }
        }
@@ -33,6 +48,131 @@ public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
        private UserAdmin nodeRoles = null;
        private Map<LdapName, UserAdmin> userAdmins = new HashMap<LdapName, UserAdmin>();
 
+       public NodeUserAdmin() {
+               File osgiInstanceDir = KernelUtils.getOsgiInstanceDir();
+               File nodeBaseDir = new File(osgiInstanceDir, "node");
+               nodeBaseDir.mkdirs();
+
+               String userAdminUri = KernelUtils
+                               .getFrameworkProp(KernelConstants.USERADMIN_URIS);
+               if (userAdminUri == null) {
+                       String demoBaseDn = "dc=example,dc=com";
+                       File businessRolesFile = new File(nodeBaseDir, demoBaseDn + ".ldif");
+                       if (!businessRolesFile.exists())
+                               try {
+                                       FileUtils.copyInputStreamToFile(getClass()
+                                                       .getResourceAsStream(demoBaseDn + ".ldif"),
+                                                       businessRolesFile);
+                               } catch (IOException e) {
+                                       throw new CmsException("Cannot copy demo resource", e);
+                               }
+                       userAdminUri = businessRolesFile.toURI().toString();
+               }
+
+               String[] uris = userAdminUri.split(" ");
+               for (String uri : uris) {
+                       URI u;
+                       try {
+                               u = new URI(uri);
+                               if (u.getPath() == null)
+                                       throw new CmsException("URI " + uri
+                                                       + " must have a path in order to determine base DN");
+                               if (u.getScheme() == null) {
+                                       if (uri.startsWith("/") || uri.startsWith("./")
+                                                       || uri.startsWith("../"))
+                                               u = new File(uri).getCanonicalFile().toURI();
+                                       else if (!uri.contains("/"))
+                                               u = new File(nodeBaseDir, uri).getCanonicalFile()
+                                                               .toURI();
+                                       else
+                                               throw new CmsException("Cannot interpret " + uri
+                                                               + " as an uri");
+                               } else if (u.getScheme().equals("file")) {
+                                       u = new File(u).getCanonicalFile().toURI();
+                               }
+                       } catch (Exception e) {
+                               throw new CmsException(
+                                               "Cannot interpret " + uri + " as an uri", e);
+                       }
+                       Dictionary<String, ?> properties = UserAdminConf.uriAsProperties(u
+                                       .toString());
+                       UserDirectory businessRoles;
+                       if (u.getScheme().startsWith("ldap")) {
+                               businessRoles = new LdapUserAdmin(properties);
+                       } else {
+                               businessRoles = new LdifUserAdmin(properties);
+                       }
+                       businessRoles.init();
+                       addUserAdmin(businessRoles.getBaseDn(), (UserAdmin) businessRoles);
+                       if (log.isDebugEnabled())
+                               log.debug("User directory " + businessRoles.getBaseDn() + " ["
+                                               + u.getScheme() + "] enabled.");
+               }
+
+               // NOde roles
+               String nodeRolesUri = KernelUtils
+                               .getFrameworkProp(KernelConstants.ROLES_URI);
+               String baseNodeRoleDn = KernelHeader.ROLES_BASEDN;
+               if (nodeRolesUri == null) {
+                       File nodeRolesFile = new File(nodeBaseDir, baseNodeRoleDn + ".ldif");
+                       if (!nodeRolesFile.exists())
+                               try {
+                                       FileUtils.copyInputStreamToFile(getClass()
+                                                       .getResourceAsStream("demo.ldif"), nodeRolesFile);
+                               } catch (IOException e) {
+                                       throw new CmsException("Cannot copy demo resource", e);
+                               }
+                       nodeRolesUri = nodeRolesFile.toURI().toString();
+               }
+
+               Dictionary<String, ?> nodeRolesProperties = UserAdminConf
+                               .uriAsProperties(nodeRolesUri);
+               if (!nodeRolesProperties.get(UserAdminConf.baseDn.property()).equals(
+                               baseNodeRoleDn)) {
+                       throw new CmsException("Invalid base dn for node roles");
+                       // TODO deal with "mounted" roles with a different baseDN
+               }
+               UserDirectory nodeRoles;
+               if (nodeRolesUri.startsWith("ldap")) {
+                       nodeRoles = new LdapUserAdmin(nodeRolesProperties);
+               } else {
+                       nodeRoles = new LdifUserAdmin(nodeRolesProperties);
+               }
+               nodeRoles.setExternalRoles(this);
+               nodeRoles.init();
+               addUserAdmin(baseNodeRoleDn, (UserAdmin) nodeRoles);
+               if (log.isTraceEnabled())
+                       log.trace("Node roles enabled.");
+       }
+
+       Dictionary<String, ?> currentState() {
+               Dictionary<String, Object> res = new Hashtable<String, Object>();
+               for (LdapName name : userAdmins.keySet()) {
+                       StringBuilder buf = new StringBuilder();
+                       if (userAdmins.get(name) instanceof UserDirectory) {
+                               UserDirectory userDirectory = (UserDirectory) userAdmins
+                                               .get(name);
+                               String uri = UserAdminConf.propertiesAsUri(
+                                               userDirectory.getProperties()).toString();
+                               res.put(uri, "");
+                       } else {
+                               buf.append('/').append(name.toString())
+                                               .append("?readOnly=true");
+                       }
+               }
+               return res;
+       }
+
+       public void destroy() {
+               for (LdapName name : userAdmins.keySet()) {
+                       if (userAdmins.get(name) instanceof UserDirectory) {
+                               UserDirectory userDirectory = (UserDirectory) userAdmins
+                                               .get(name);
+                               userDirectory.destroy();
+                       }
+               }
+       }
+
        @Override
        public Role createRole(String name, int type) {
                return findUserAdmin(name).createRole(name, type);
@@ -40,7 +180,9 @@ public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
 
        @Override
        public boolean removeRole(String name) {
-               return findUserAdmin(name).removeRole(name);
+               boolean actuallyDeleted = findUserAdmin(name).removeRole(name);
+               nodeRoles.removeRole(name);
+               return actuallyDeleted;
        }
 
        @Override
@@ -72,52 +214,55 @@ public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
 
        @Override
        public Authorization getAuthorization(User user) {
+               if (user == null) {
+                       return nodeRoles.getAuthorization(null);
+               }
                UserAdmin userAdmin = findUserAdmin(user.getName());
-               // FIXME clarify assumptions
-               return userAdmin.getAuthorization(user);
-               // String[] roles = auth.getRoles();
-               // // Gather system roles
-               // Set<String> systemRoles = new HashSet<String>();
-               // for(String businessRole:roles){
-               //
-               // }
-               // return null;
+               Authorization rawAuthorization = userAdmin.getAuthorization(user);
+               // gather system roles
+               Set<String> systemRoles = new HashSet<String>();
+               for (String role : rawAuthorization.getRoles()) {
+                       Authorization auth = nodeRoles.getAuthorization((User) userAdmin
+                                       .getRole(role));
+                       systemRoles.addAll(Arrays.asList(auth.getRoles()));
+               }
+               return new NodeAuthorization(rawAuthorization.getName(),
+                               rawAuthorization.toString(), systemRoles,
+                               rawAuthorization.getRoles());
        }
 
        //
        // USER ADMIN AGGREGATOR
        //
-       @Override
        public synchronized void addUserAdmin(String baseDn, UserAdmin userAdmin) {
-               if (baseDn.equals(KernelConstants.ROLES_BASEDN)) {
+               if (baseDn.equals(KernelHeader.ROLES_BASEDN)) {
                        nodeRoles = userAdmin;
                        return;
                }
 
                if (userAdmins.containsKey(baseDn))
-                       throw new ArgeoUserAdminException(
+                       throw new UserDirectoryException(
                                        "There is already a user admin for " + baseDn);
                try {
                        userAdmins.put(new LdapName(baseDn), userAdmin);
                } catch (InvalidNameException e) {
-                       throw new ArgeoUserAdminException("Badly formatted base DN "
+                       throw new UserDirectoryException("Badly formatted base DN "
                                        + baseDn, e);
                }
        }
 
-       @Override
        public synchronized void removeUserAdmin(String baseDn) {
-               if (baseDn.equals(KernelConstants.ROLES_BASEDN))
-                       throw new ArgeoUserAdminException("Node roles cannot be removed.");
+               if (baseDn.equals(KernelHeader.ROLES_BASEDN))
+                       throw new UserDirectoryException("Node roles cannot be removed.");
                LdapName base;
                try {
                        base = new LdapName(baseDn);
                } catch (InvalidNameException e) {
-                       throw new ArgeoUserAdminException("Badly formatted base DN "
+                       throw new UserDirectoryException("Badly formatted base DN "
                                        + baseDn, e);
                }
                if (!userAdmins.containsKey(base))
-                       throw new ArgeoUserAdminException("There is no user admin for "
+                       throw new UserDirectoryException("There is no user admin for "
                                        + base);
                userAdmins.remove(base);
        }
@@ -126,7 +271,7 @@ public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
                try {
                        return findUserAdmin(new LdapName(name));
                } catch (InvalidNameException e) {
-                       throw new ArgeoUserAdminException("Badly formatted name " + name, e);
+                       throw new UserDirectoryException("Badly formatted name " + name, e);
                }
        }
 
@@ -139,11 +284,22 @@ public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
                                res.add(userAdmins.get(baseDn));
                }
                if (res.size() == 0)
-                       throw new ArgeoUserAdminException("Cannot find user admin for "
+                       throw new UserDirectoryException("Cannot find user admin for "
                                        + name);
                if (res.size() > 1)
-                       throw new ArgeoUserAdminException("Multiple user admin found for "
+                       throw new UserDirectoryException("Multiple user admin found for "
                                        + name);
                return res.get(0);
        }
+
+       public void setTransactionManager(TransactionManager transactionManager) {
+               if (nodeRoles instanceof UserDirectory)
+                       ((UserDirectory) nodeRoles)
+                                       .setTransactionManager(transactionManager);
+               for (UserAdmin userAdmin : userAdmins.values()) {
+                       if (userAdmin instanceof UserDirectory)
+                               ((UserDirectory) userAdmin)
+                                               .setTransactionManager(transactionManager);
+               }
+       }
 }