From 10b1584cd1e3550ecdd1d35dded9c4266d1cb4d8 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 9 Sep 2016 09:15:24 +0000 Subject: [PATCH] Refactor user admin git-svn-id: https://svn.argeo.org/commons/trunk@9106 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../cms/internal/kernel/CmsDeployment.java | 3 + .../argeo/cms/internal/kernel/CmsState.java | 13 +- .../cms/internal/kernel/NodeUserAdmin.java | 552 ++---------------- .../kernel/UserDirectoryServiceFactory.java | 51 -- .../osgi/useradmin/LdifUserAdminTest.java | 41 +- .../osgi/useradmin/AbstractUserDirectory.java | 47 +- .../useradmin/AggregatingAuthorization.java | 73 +++ .../osgi/useradmin/AggregatingUserAdmin.java | 189 ++++++ .../argeo/osgi/useradmin/LdapUserAdmin.java | 6 +- .../argeo/osgi/useradmin/UserDirectory.java | 24 +- 10 files changed, 389 insertions(+), 610 deletions(-) delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/kernel/UserDirectoryServiceFactory.java create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java index a2d072e5b..7a4ca1bf4 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java @@ -28,6 +28,7 @@ import org.argeo.node.NodeDeployment; import org.argeo.node.NodeState; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.framework.wiring.BundleCapability; @@ -178,6 +179,8 @@ public class CmsDeployment implements NodeDeployment { Hashtable properties = new Hashtable<>(); properties.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, name); properties.put(NodeConstants.CN, name); + if (name.equals(ArgeoJcrConstants.ALIAS_NODE)) + properties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); bc.registerService(Repository.class, adminSession.getRepository(), properties); if (log.isDebugEnabled()) log.debug("Published data model " + name); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java index 87fae05cf..63aeeac29 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java @@ -10,6 +10,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Dictionary; +import java.util.Hashtable; import java.util.List; import java.util.Locale; import java.util.UUID; @@ -21,6 +22,7 @@ import javax.transaction.UserTransaction; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.cms.auth.AuthConstants; import org.argeo.cms.maintenance.MaintenanceUi; import org.argeo.node.NodeConstants; import org.argeo.node.NodeState; @@ -32,7 +34,6 @@ import org.osgi.framework.Constants; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ManagedServiceFactory; -import org.osgi.service.useradmin.UserAdmin; import bitronix.tm.BitronixTransactionManager; import bitronix.tm.BitronixTransactionSynchronizationRegistry; @@ -88,6 +89,7 @@ public class CmsState implements NodeState { } private void initServices() { + // JTA initTransactionManager(); // JCR @@ -100,14 +102,9 @@ public class CmsState implements NodeState { bc.registerService(RepositoryFactory.class, repositoryFactory, null); // Security -// UserDirectoryServiceFactory userDirectoryServiceFactory = new UserDirectoryServiceFactory(); -// shutdownHooks.add(() -> userDirectoryServiceFactory.shutdown()); -// bc.registerService(ManagedServiceFactory.class, userDirectoryServiceFactory, -// LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_USER_DIRECTORIES_FACTORY_PID)); - - NodeUserAdmin userAdmin = new NodeUserAdmin(); + NodeUserAdmin userAdmin = new NodeUserAdmin(AuthConstants.ROLES_BASEDN); shutdownHooks.add(() -> userAdmin.destroy()); - Dictionary props = userAdmin.currentState(); + Dictionary props = new Hashtable<>(); props.put(Constants.SERVICE_PID, NodeConstants.NODE_USER_ADMIN_PID); bc.registerService(ManagedServiceFactory.class, userAdmin, props); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java index c04d820da..d0cf93d80 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java @@ -2,92 +2,56 @@ package org.argeo.cms.internal.kernel; import java.net.URI; import java.net.URISyntaxException; -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.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; -import org.argeo.cms.auth.AuthConstants; import org.argeo.node.NodeConstants; +import org.argeo.osgi.useradmin.AbstractUserDirectory; +import org.argeo.osgi.useradmin.AggregatingUserAdmin; 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.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; -import org.osgi.service.useradmin.Authorization; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; import org.osgi.util.tracker.ServiceTracker; +import bitronix.tm.BitronixTransactionManager; import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer; /** - * Aggregates multiple {@link UserDirectory} and integrates them with this node - * system roles. + * Aggregates multiple {@link UserDirectory} and integrates them with system + * roles. */ -class NodeUserAdmin implements UserAdmin, ManagedServiceFactory, KernelConstants { +class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactory, KernelConstants { private final static Log log = LogFactory.getLog(NodeUserAdmin.class); - final static LdapName ROLES_BASE; - static { - try { - ROLES_BASE = new LdapName(AuthConstants.ROLES_BASEDN); - } catch (InvalidNameException e) { - throw new UserDirectoryException("Cannot initialize " + NodeUserAdmin.class, e); - } - } - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - // DAOs - private UserAdmin nodeRoles = null; - private Map userAdmins = new HashMap(); + // OSGi private Map pidToBaseDn = new HashMap<>(); - + private Map> pidToServiceRegs = new HashMap<>(); private ServiceRegistration userAdminReg; + // JTA private final ServiceTracker tmTracker; - - // JCR - // private String homeBasePath = "/home"; - // private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH; - // private Repository repository; - // private Session adminSession; - private final String cacheName = UserDirectory.class.getName(); - public NodeUserAdmin() { - // DAOs - // File nodeBaseDir = new File(getOsgiInstanceDir(), DIR_NODE); - // nodeBaseDir.mkdirs(); - // String userAdminUri = getFrameworkProp(NodeConstants.USERADMIN_URIS); - // initUserAdmins(userAdminUri, nodeBaseDir); - // String nodeRolesUri = getFrameworkProp(NodeConstants.ROLES_URI); - // initNodeRoles(nodeRolesUri, nodeBaseDir); - - // new ServiceTracker<>(bc, TransactionManager.class, new - // TransactionManagerStc()).open(); - tmTracker = new TransactionManagerStc(); + public NodeUserAdmin(String systemRolesBaseDn) { + super(systemRolesBaseDn); + tmTracker = new ServiceTracker<>(bc, TransactionManager.class, null); tmTracker.open(); } @@ -100,492 +64,64 @@ class NodeUserAdmin implements UserAdmin, ManagedServiceFactory, KernelConstants } catch (URISyntaxException e) { throw new CmsException("Badly formatted URI " + uri, e); } - UserDirectory userDirectory = u.getScheme().equals("ldap") ? new LdapUserAdmin(properties) + + // Create + AbstractUserDirectory userDirectory = u.getScheme().equals("ldap") ? new LdapUserAdmin(properties) : new LdifUserAdmin(properties); - LdapName baseDn; - try { - baseDn = new LdapName(userDirectory.getBaseDn()); - } catch (InvalidNameException e) { - throw new CmsException("Badly formatted base DN " + userDirectory.getBaseDn(), e); - } - if (isRolesDnBase(baseDn)) { - nodeRoles = (UserAdmin) userDirectory; - userDirectory.setExternalRoles(this); - } - userDirectory.init(); - addUserAdmin(baseDn.toString(), (UserAdmin) userDirectory); + addUserDirectory(userDirectory); - // publish user directory + // OSGi + LdapName baseDn = userDirectory.getBaseDn(); Dictionary regProps = new Hashtable<>(); regProps.put(Constants.SERVICE_PID, pid); + if(isSystemRolesBaseDn(baseDn)) + regProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); regProps.put(UserAdminConf.baseDn.name(), baseDn); - bc.registerService(UserDirectory.class, userDirectory, regProps); + ServiceRegistration reg = bc.registerService(UserDirectory.class, userDirectory, regProps); pidToBaseDn.put(pid, baseDn); + pidToServiceRegs.put(pid, reg); - if (log.isDebugEnabled()) { + if (log.isDebugEnabled()) log.debug("User directory " + userDirectory.getBaseDn() + " [" + u.getScheme() + "] enabled."); - } - if (!isRolesDnBase(baseDn)) { + if (!isSystemRolesBaseDn(baseDn)) { if (userAdminReg != null) userAdminReg.unregister(); // register self as main user admin - userAdminReg = bc.registerService(UserAdmin.class, this, currentState()); + Dictionary userAdminregProps = currentState(); + userAdminregProps.put(NodeConstants.CN, NodeConstants.DEFAULT); + userAdminregProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); + userAdminReg = bc.registerService(UserAdmin.class, this, userAdminregProps); } } - private boolean isRolesDnBase(LdapName baseDn) { - return baseDn.equals(ROLES_BASE); - } - @Override public void deleted(String pid) { + assert pidToServiceRegs.get(pid) != null; + assert pidToBaseDn.get(pid) != null; + pidToServiceRegs.remove(pid).unregister(); LdapName baseDn = pidToBaseDn.remove(pid); - UserAdmin userAdmin = userAdmins.remove(baseDn); - ((UserDirectory) userAdmin).destroy(); + removeUserDirectory(baseDn); } @Override public String getName() { - return "Node user admin"; - } - - private class TransactionManagerStc extends ServiceTracker { - - public TransactionManagerStc() { - super(bc, TransactionManager.class, null); - } - - @Override - public TransactionManager addingService(ServiceReference reference) { - TransactionManager transactionManager = bc.getService(reference); - if (nodeRoles != null) - ((UserDirectory) nodeRoles).setTransactionManager(transactionManager); - for (UserAdmin userAdmin : userAdmins.values()) { - if (userAdmin instanceof UserDirectory) - ((UserDirectory) userAdmin).setTransactionManager(transactionManager); - } - if (log.isDebugEnabled()) - log.debug("Set transaction manager"); - return transactionManager; - } - - @Override - public void removedService(ServiceReference reference, TransactionManager service) { - ((UserDirectory) nodeRoles).setTransactionManager(null); - for (UserAdmin userAdmin : userAdmins.values()) { - if (userAdmin instanceof UserDirectory) - ((UserDirectory) userAdmin).setTransactionManager(null); - } - } - + return "Node User Admin"; } - // @Deprecated - // public NodeUserAdmin(TransactionManager transactionManager, Repository - // repository) { - // // this.repository = repository; - // // try { - // // this.adminSession = this.repository.login(); - // // } catch (RepositoryException e) { - // // throw new CmsException("Cannot log-in", e); - // // } - // - // // DAOs - // File nodeBaseDir = new File(getOsgiInstanceDir(), DIR_NODE); - // nodeBaseDir.mkdirs(); - // String userAdminUri = getFrameworkProp(NodeConstants.USERADMIN_URIS); - // initUserAdmins(userAdminUri, nodeBaseDir); - // String nodeRolesUri = getFrameworkProp(NodeConstants.ROLES_URI); - // initNodeRoles(nodeRolesUri, nodeBaseDir); - // - // // Transaction manager - // ((UserDirectory) nodeRoles).setTransactionManager(transactionManager); - // for (UserAdmin userAdmin : userAdmins.values()) { - // if (userAdmin instanceof UserDirectory) - // ((UserDirectory) userAdmin).setTransactionManager(transactionManager); - // } - // - // // JCR - // // initJcr(adminSession); - // } - - Dictionary currentState() { - Dictionary res = new Hashtable(); - res.put(NodeConstants.CN, NodeConstants.DEFAULT); - 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; + protected void postAdd(AbstractUserDirectory userDirectory) { + // JTA + TransactionManager tm = tmTracker.getService(); + if (tm == null) + throw new CmsException("A JTA transaction manager must be available."); + userDirectory.setTransactionManager(tm); + if (tmTracker.getService() instanceof BitronixTransactionManager) + EhCacheXAResourceProducer.registerXAResource(cacheName, userDirectory.getXaResource()); } - public void destroy() { - for (LdapName name : userAdmins.keySet()) { - if (userAdmins.get(name) instanceof UserDirectory) { - UserDirectory userDirectory = (UserDirectory) userAdmins.get(name); - try { - // FIXME Make it less bitronix dependant - EhCacheXAResourceProducer.unregisterXAResource(cacheName, userDirectory.getXaResource()); - } catch (Exception e) { - log.error("Cannot unregister resource from Bitronix", e); - } - userDirectory.destroy(); - - } - } - } - - @Override - public Role createRole(String name, int type) { - return findUserAdmin(name).createRole(name, type); - } - - @Override - public boolean removeRole(String name) { - boolean actuallyDeleted = findUserAdmin(name).removeRole(name); - nodeRoles.removeRole(name); - return actuallyDeleted; + protected void preDestroy(UserDirectory userDirectory) { + if (tmTracker.getService() instanceof BitronixTransactionManager) + EhCacheXAResourceProducer.unregisterXAResource(cacheName, userDirectory.getXaResource()); } - @Override - public Role getRole(String name) { - return findUserAdmin(name).getRole(name); - } - - @Override - public Role[] getRoles(String filter) throws InvalidSyntaxException { - List res = new ArrayList(); - for (UserAdmin userAdmin : userAdmins.values()) { - res.addAll(Arrays.asList(userAdmin.getRoles(filter))); - } - res.addAll(Arrays.asList(nodeRoles.getRoles(filter))); - return res.toArray(new Role[res.size()]); - } - - @Override - public User getUser(String key, String value) { - List res = new ArrayList(); - for (UserAdmin userAdmin : userAdmins.values()) { - User u = userAdmin.getUser(key, value); - if (u != null) - res.add(u); - } - // Note: node roles cannot contain users, so it is not searched - return res.size() == 1 ? res.get(0) : null; - } - - @Override - public Authorization getAuthorization(User user) { - if (user == null) {// anonymous - return nodeRoles.getAuthorization(null); - } - UserAdmin userAdmin = findUserAdmin(user.getName()); - Authorization rawAuthorization = userAdmin.getAuthorization(user); - // gather system roles - Set systemRoles = new HashSet(); - for (String role : rawAuthorization.getRoles()) { - Authorization auth = nodeRoles.getAuthorization((User) userAdmin.getRole(role)); - systemRoles.addAll(Arrays.asList(auth.getRoles())); - } - Authorization authorization = new NodeAuthorization(rawAuthorization.getName(), rawAuthorization.toString(), - systemRoles, rawAuthorization.getRoles()); - // syncJcr(adminSession, authorization); - return authorization; - } - - // - // USER ADMIN AGGREGATOR - // - public void addUserAdmin(String baseDn, UserAdmin userAdmin) { - try { - LdapName key = new LdapName(baseDn); - if (userAdmins.containsKey(key)) - throw new UserDirectoryException("There is already a user admin for " + baseDn); - userAdmins.put(key, userAdmin); - } catch (InvalidNameException e) { - throw new UserDirectoryException("Badly formatted base DN " + baseDn, e); - } - if (userAdmin instanceof UserDirectory) { - UserDirectory userDirectory = (UserDirectory) userAdmin; - try { - userDirectory.setTransactionManager(tmTracker.getService()); - // FIXME Make it less bitronix dependant - EhCacheXAResourceProducer.registerXAResource(cacheName, ((UserDirectory) userAdmin).getXaResource()); - } catch (Exception e) { - log.error("Cannot register resource to Bitronix", e); - } - } - } - - private UserAdmin findUserAdmin(String name) { - try { - return findUserAdmin(new LdapName(name)); - } catch (InvalidNameException e) { - throw new UserDirectoryException("Badly formatted name " + name, e); - } - } - - private UserAdmin findUserAdmin(LdapName name) { - if (name.startsWith(ROLES_BASE)) - return nodeRoles; - List res = new ArrayList(1); - for (LdapName baseDn : userAdmins.keySet()) { - if (name.startsWith(baseDn)) - res.add(userAdmins.get(baseDn)); - } - if (res.size() == 0) - throw new UserDirectoryException("Cannot find user admin for " + name); - if (res.size() > 1) - 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); - } - } - - // private void initUserAdmins(String userAdminUri, File nodeBaseDir) { - // // 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 URI(nodeBaseDir.toURI() + uri); - // // 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 properties = - // UserAdminConf.uriAsProperties(u.toString()); - // UserDirectory businessRoles; - // if (u.getScheme().startsWith("ldap")) { - // businessRoles = new LdapUserAdmin(properties); - // } else { - // businessRoles = new LdifUserAdmin(properties); - // } - // businessRoles.init(); - // String baseDn = businessRoles.getBaseDn(); - // if (userAdmins.containsKey(baseDn)) - // throw new UserDirectoryException("There is already a user admin for " + - // baseDn); - // try { - // userAdmins.put(new LdapName(baseDn), (UserAdmin) businessRoles); - // } catch (InvalidNameException e) { - // throw new UserDirectoryException("Badly formatted base DN " + baseDn, e); - // } - // addUserAdmin(businessRoles.getBaseDn(), (UserAdmin) businessRoles); - // if (log.isDebugEnabled()) - // log.debug("User directory " + businessRoles.getBaseDn() + " [" + - // u.getScheme() + "] enabled."); - // } - // - // } - // - // private void initNodeRoles(String nodeRolesUri, File nodeBaseDir) { - // String baseNodeRoleDn = AuthConstants.ROLES_BASEDN; - // if (nodeRolesUri == null) { - // File nodeRolesFile = new File(nodeBaseDir, baseNodeRoleDn + ".ldif"); - // if (!nodeRolesFile.exists()) - // try { - // FileUtils.copyInputStreamToFile(getClass().getResourceAsStream(baseNodeRoleDn - // + ".ldif"), - // nodeRolesFile); - // } catch (IOException e) { - // throw new CmsException("Cannot copy demo resource", e); - // } - // nodeRolesUri = nodeRolesFile.toURI().toString(); - // } - // - // Dictionary nodeRolesProperties = - // UserAdminConf.uriAsProperties(nodeRolesUri); - // if - // (!nodeRolesProperties.get(UserAdminConf.baseDn.name()).equals(baseNodeRoleDn)) - // { - // throw new CmsException("Invalid base dn for node roles"); - // // TODO deal with "mounted" roles with a different baseDN - // } - // if (nodeRolesUri.startsWith("ldap")) { - // nodeRoles = new LdapUserAdmin(nodeRolesProperties); - // } else { - // nodeRoles = new LdifUserAdmin(nodeRolesProperties); - // } - // ((UserDirectory) nodeRoles).setExternalRoles(this); - // ((UserDirectory) nodeRoles).init(); - // addUserAdmin(baseNodeRoleDn, (UserAdmin) nodeRoles); - // if (log.isTraceEnabled()) - // log.trace("Node roles enabled."); - // - // } - - /* - * JCR - */ - // private void initJcr(Session adminSession) { - // try { - // JcrUtils.mkdirs(adminSession, homeBasePath); - // JcrUtils.mkdirs(adminSession, peopleBasePath); - // adminSession.save(); - // - // JcrUtils.addPrivilege(adminSession, homeBasePath, - // AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ); - // JcrUtils.addPrivilege(adminSession, peopleBasePath, - // AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL); - // adminSession.save(); - // } catch (RepositoryException e) { - // throw new CmsException("Cannot initialize node user admin", e); - // } - // } - // - // private Node syncJcr(Session session, Authorization authorization) { - // // TODO check user name validity (e.g. should not start by ROLE_) - // String username = authorization.getName(); - // // String[] roles = authorization.getRoles(); - // try { - // Node userHome = UserJcrUtils.getUserHome(session, username); - // if (userHome == null) { - // String homePath = generateUserPath(homeBasePath, username); - // if (session.itemExists(homePath))// duplicate user id - // userHome = - // session.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath)); - // else - // userHome = JcrUtils.mkdirs(session, homePath); - // // userHome = JcrUtils.mkfolders(session, homePath); - // userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME); - // userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username); - // session.save(); - // - // JcrUtils.clearAccessControList(session, homePath, username); - // JcrUtils.addPrivilege(session, homePath, username, Privilege.JCR_ALL); - // } - // - // Node userProfile = UserJcrUtils.getUserProfile(session, username); - // // new user - // if (userProfile == null) { - // String personPath = generateUserPath(peopleBasePath, username); - // Node personBase; - // if (session.itemExists(personPath))// duplicate user id - // personBase = - // session.getNode(personPath).getParent().addNode(JcrUtils.lastPathElement(personPath)); - // else - // personBase = JcrUtils.mkdirs(session, personPath); - // userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE); - // userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE); - // userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username); - // userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true); - // userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, true); - // userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, true); - // userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true); - // session.save(); - // - // JcrUtils.clearAccessControList(session, userProfile.getPath(), username); - // JcrUtils.addPrivilege(session, userProfile.getPath(), username, - // Privilege.JCR_READ); - // } - // - // // Remote roles - // // if (roles != null) { - // // writeRemoteRoles(userProfile, roles); - // // } - // if (adminSession.hasPendingChanges()) - // adminSession.save(); - // return userProfile; - // } catch (RepositoryException e) { - // JcrUtils.discardQuietly(session); - // throw new ArgeoException("Cannot sync node security model for " + - // username, e); - // } - // } - // - // /** Generate path for a new user home */ - // private String generateUserPath(String base, String username) { - // LdapName dn; - // try { - // dn = new LdapName(username); - // } catch (InvalidNameException e) { - // throw new ArgeoException("Invalid name " + username, e); - // } - // String userId = dn.getRdn(dn.size() - 1).getValue().toString(); - // int atIndex = userId.indexOf('@'); - // if (atIndex > 0) { - // String domain = userId.substring(0, atIndex); - // String name = userId.substring(atIndex + 1); - // return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + domain + - // '/' - // + JcrUtils.firstCharsToPath(name, 2) + '/' + name; - // } else if (atIndex == 0 || atIndex == (userId.length() - 1)) { - // throw new ArgeoException("Unsupported username " + userId); - // } else { - // return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + userId; - // } - // } - - // /** Write remote roles used by remote access in the home directory */ - // private void writeRemoteRoles(Node userHome, String[] roles) - // throws RepositoryException { - // boolean writeRoles = false; - // if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { - // Value[] remoteRoles = userHome.getProperty( - // ArgeoNames.ARGEO_REMOTE_ROLES).getValues(); - // if (remoteRoles.length != roles.length) - // writeRoles = true; - // else - // for (int i = 0; i < remoteRoles.length; i++) - // if (!remoteRoles[i].getString().equals(roles[i])) - // writeRoles = true; - // } else - // writeRoles = true; - // - // if (writeRoles) { - // userHome.getSession().getWorkspace().getVersionManager() - // .checkout(userHome.getPath()); - // userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roles); - // JcrUtils.updateLastModified(userHome); - // userHome.getSession().save(); - // userHome.getSession().getWorkspace().getVersionManager() - // .checkin(userHome.getPath()); - // if (log.isDebugEnabled()) - // log.debug("Wrote remote roles " + roles + " for " - // + userHome.getProperty(ArgeoNames.ARGEO_USER_ID)); - // } - // - // } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/UserDirectoryServiceFactory.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/UserDirectoryServiceFactory.java deleted file mode 100644 index 0726e5029..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/UserDirectoryServiceFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.util.Dictionary; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -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.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.FrameworkUtil; -import org.osgi.service.cm.ConfigurationException; -import org.osgi.service.cm.ManagedServiceFactory; - -class UserDirectoryServiceFactory implements ManagedServiceFactory { - private final BundleContext bc = FrameworkUtil.getBundle(UserDirectoryServiceFactory.class).getBundleContext(); - - private Map userDirectories = new HashMap<>(); - - @Override - public String getName() { - return "User Directories Factory"; - } - - @Override - public void updated(String pid, Dictionary properties) throws ConfigurationException { - String uri = (String) properties.get(UserAdminConf.uri.name()); - UserDirectory userDirectory = uri.startsWith("ldap:") ? new LdapUserAdmin(properties) - : new LdifUserAdmin(properties); - String baseDn = userDirectory.getBaseDn(); - Dictionary regProps = new Hashtable<>(); - regProps.put(Constants.SERVICE_PID, pid); - regProps.put(UserAdminConf.baseDn.name(), baseDn); -// regProps.put(UserAdminConf.uri.name(), uri); - bc.registerService(UserDirectory.class, userDirectory, regProps); - userDirectories.put(pid, userDirectory); - } - - @Override - public void deleted(String pid) { - userDirectories.remove(pid); - } - - void shutdown() { - for (UserDirectory userDirectory : userDirectories.values()) - userDirectory.destroy(); - } -} 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 9714ade9a..e76769d71 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 @@ -13,6 +13,8 @@ import java.util.Hashtable; import java.util.List; import java.util.UUID; +import javax.transaction.TransactionManager; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; @@ -27,8 +29,12 @@ import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer; import junit.framework.TestCase; public class LdifUserAdminTest extends TestCase implements BasicTestConstants { - private AbstractUserDirectory userAdmin; private BitronixTransactionManager tm; + private URI uri; + private AbstractUserDirectory userAdmin; + + public void testConcurrent() throws Exception { + } @SuppressWarnings("unchecked") public void testEdition() throws Exception { @@ -40,11 +46,13 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { demoUser.getProperties().put("cn", newName); assertEquals(newName, demoUser.getProperties().get("cn")); tm.commit(); + persistAndRestart(); assertEquals(newName, demoUser.getProperties().get("cn")); tm.begin(); userAdmin.removeRole(DEMO_USER_DN); tm.commit(); + persistAndRestart(); // check data Role[] search = userAdmin.getRoles("(objectclass=inetOrgPerson)"); @@ -126,8 +134,7 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { @Override protected void setUp() throws Exception { Path tempDir = Files.createTempDirectory(getClass().getName()); - URI uri; - String uriProp = System.getProperty("argeo.useradmin.uri"); + String uriProp = System.getProperty("argeo.userdirectory.uri"); if (uriProp != null) uri = new URI(uriProp); else { @@ -139,25 +146,39 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { uri = ldifPath.toUri(); } + bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration(); + tmConf.setServerId(UUID.randomUUID().toString()); + tmConf.setLogPart1Filename(new File(tempDir.toFile(), "btm1.tlog").getAbsolutePath()); + tmConf.setLogPart2Filename(new File(tempDir.toFile(), "btm2.tlog").getAbsolutePath()); + tm = TransactionManagerServices.getTransactionManager(); + + userAdmin = initUserAdmin(uri, tm); + } + + private AbstractUserDirectory initUserAdmin(URI uri, TransactionManager tm) { Dictionary props = new Hashtable<>(); props.put(UserAdminConf.uri.name(), uri.toString()); props.put(UserAdminConf.baseDn.name(), BASE_DN); props.put(UserAdminConf.userBase.name(), "ou=users"); props.put(UserAdminConf.groupBase.name(), "ou=groups"); + AbstractUserDirectory userAdmin; if (uri.getScheme().startsWith("ldap")) userAdmin = new LdapUserAdmin(props); else userAdmin = new LdifUserAdmin(props); userAdmin.init(); - - bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration(); - tmConf.setServerId(UUID.randomUUID().toString()); - tmConf.setLogPart1Filename(new File(tempDir.toFile(), "btm1.tlog").getAbsolutePath()); - tmConf.setLogPart2Filename(new File(tempDir.toFile(), "btm2.tlog").getAbsolutePath()); - tm = TransactionManagerServices.getTransactionManager(); + // JTA EhCacheXAResourceProducer.registerXAResource(UserDirectory.class.getName(), userAdmin.getXaResource()); - userAdmin.setTransactionManager(tm); + return userAdmin; + } + + private void persistAndRestart() { + EhCacheXAResourceProducer.unregisterXAResource(UserDirectory.class.getName(), userAdmin.getXaResource()); + if (userAdmin instanceof LdifUserAdmin) + ((LdifUserAdmin) userAdmin).save(); + userAdmin.destroy(); + userAdmin = initUserAdmin(uri, tm); } @Override diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index 48d657c2e..3f5bf850d 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -38,13 +38,12 @@ import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; /** Base class for a {@link UserDirectory}. */ -abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { +public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { private final static Log log = LogFactory.getLog(AbstractUserDirectory.class); private final Hashtable properties; - private final String baseDn; - private final String userObjectClass; - private final String groupObjectClass; + private final LdapName baseDn; + private final String userObjectClass, userBase, groupObjectClass, groupBase; private final boolean readOnly; private final URI uri; @@ -56,10 +55,11 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { private String memberAttributeId = "member"; private List credentialAttributeIds = Arrays.asList(new String[] { LdifName.userPassword.name() }); + // JTA private TransactionManager transactionManager; private WcXaResource xaResource = new WcXaResource(this); - AbstractUserDirectory(Dictionary props) { + public AbstractUserDirectory(Dictionary props) { properties = new Hashtable(); for (Enumeration keys = props.keys(); keys.hasMoreElements();) { String key = keys.nextElement(); @@ -76,7 +76,11 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { throw new UserDirectoryException("Badly formatted URI " + uriStr, e); } - baseDn = UserAdminConf.baseDn.getValue(properties).toString(); + try { + baseDn = new LdapName(UserAdminConf.baseDn.getValue(properties)); + } catch (InvalidNameException e) { + throw new UserDirectoryException("Badly formated base DN " + UserAdminConf.baseDn.getValue(properties), e); + } String readOnlyStr = UserAdminConf.readOnly.getValue(properties); if (readOnlyStr == null) { readOnly = readOnlyDefault(uri); @@ -85,7 +89,9 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { readOnly = new Boolean(readOnlyStr); userObjectClass = UserAdminConf.userObjectClass.getValue(properties); + userBase = UserAdminConf.userBase.getValue(properties); groupObjectClass = UserAdminConf.groupObjectClass.getValue(properties); + groupBase = UserAdminConf.groupBase.getValue(properties); } /** Returns the groups this user is a direct member of. */ @@ -105,7 +111,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } - boolean isEditing() { + protected boolean isEditing() { return xaResource.wc() != null; } @@ -116,7 +122,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { return wc; } - void checkEdit() { + protected void checkEdit() { Transaction transaction; try { transaction = transactionManager.getTransaction(); @@ -135,7 +141,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } } - List getAllRoles(DirectoryUser user) { + protected List getAllRoles(DirectoryUser user) { List allRoles = new ArrayList(); if (user != null) { collectRoles(user, allRoles); @@ -334,11 +340,11 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } // GETTERS - String getMemberAttributeId() { + protected String getMemberAttributeId() { return memberAttributeId; } - List getCredentialAttributeIds() { + protected List getCredentialAttributeIds() { return credentialAttributeIds; } @@ -371,27 +377,36 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { return readOnly; } - UserAdmin getExternalRoles() { + protected UserAdmin getExternalRoles() { return externalRoles; } - public String getBaseDn() { - return baseDn; + public LdapName getBaseDn() { + // always clone so that the property is not modified by reference + return (LdapName) baseDn.clone(); } /** dn can be null, in that case a default should be returned. */ - protected String getUserObjectClass() { + public String getUserObjectClass() { return userObjectClass; } + public String getUserBase() { + return userBase; + } + protected String newUserObjectClass(LdapName dn) { return getUserObjectClass(); } - protected String getGroupObjectClass() { + public String getGroupObjectClass() { return groupObjectClass; } + public String getGroupBase() { + return groupBase; + } + public Dictionary getProperties() { return properties; } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java new file mode 100644 index 000000000..f270b8d89 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java @@ -0,0 +1,73 @@ +package org.argeo.osgi.useradmin; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +import org.osgi.service.useradmin.Authorization; + +class AggregatingAuthorization implements Authorization { + private final String name; + private final String displayName; + private final List systemRoles; + private final List roles; + + public AggregatingAuthorization(String name, String displayName, + Collection systemRoles, String[] roles) { + this.name = new X500Principal(name).getName(); + this.displayName = displayName; + this.systemRoles = Collections.unmodifiableList(new ArrayList( + systemRoles)); + this.roles = Collections.unmodifiableList(Arrays.asList(roles)); + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean hasRole(String name) { + if (systemRoles.contains(name)) + return true; + if (roles.contains(name)) + return true; + return false; + } + + @Override + public String[] getRoles() { + int size = systemRoles.size() + roles.size(); + List res = new ArrayList(size); + res.addAll(systemRoles); + res.addAll(roles); + return res.toArray(new String[size]); + } + + @Override + public int hashCode() { + if (name == null) + return super.hashCode(); + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Authorization)) + return false; + Authorization that = (Authorization) obj; + if (name == null) + return that.getName() == null; + return name.equals(that.getName()); + } + + @Override + public String toString() { + return displayName; + } + +} diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java new file mode 100644 index 000000000..860c5efc9 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java @@ -0,0 +1,189 @@ +package org.argeo.osgi.useradmin; + +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 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; + +/** + * Aggregates multiple {@link UserDirectory} and integrates them with system + * roles. + */ +public class AggregatingUserAdmin implements UserAdmin { + private final LdapName systemRolesBaseDn; + + // DAOs + private AbstractUserDirectory systemRoles = null; + private Map businessRoles = new HashMap(); + + public AggregatingUserAdmin(String systemRolesBaseDn) { + try { + this.systemRolesBaseDn = new LdapName(systemRolesBaseDn); + } catch (InvalidNameException e) { + throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin.class, e); + } + } + + @Override + public Role createRole(String name, int type) { + return findUserAdmin(name).createRole(name, type); + } + + @Override + public boolean removeRole(String name) { + boolean actuallyDeleted = findUserAdmin(name).removeRole(name); + systemRoles.removeRole(name); + return actuallyDeleted; + } + + @Override + public Role getRole(String name) { + return findUserAdmin(name).getRole(name); + } + + @Override + public Role[] getRoles(String filter) throws InvalidSyntaxException { + List res = new ArrayList(); + for (UserAdmin userAdmin : businessRoles.values()) { + res.addAll(Arrays.asList(userAdmin.getRoles(filter))); + } + res.addAll(Arrays.asList(systemRoles.getRoles(filter))); + return res.toArray(new Role[res.size()]); + } + + @Override + public User getUser(String key, String value) { + List res = new ArrayList(); + for (UserAdmin userAdmin : businessRoles.values()) { + User u = userAdmin.getUser(key, value); + if (u != null) + res.add(u); + } + // Note: node roles cannot contain users, so it is not searched + return res.size() == 1 ? res.get(0) : null; + } + + @Override + public Authorization getAuthorization(User user) { + if (user == null) {// anonymous + return systemRoles.getAuthorization(null); + } + UserAdmin userAdmin = findUserAdmin(user.getName()); + Authorization rawAuthorization = userAdmin.getAuthorization(user); + // gather system roles + Set sysRoles = new HashSet(); + for (String role : rawAuthorization.getRoles()) { + Authorization auth = systemRoles.getAuthorization((User) userAdmin.getRole(role)); + sysRoles.addAll(Arrays.asList(auth.getRoles())); + } + Authorization authorization = new AggregatingAuthorization(rawAuthorization.getName(), + rawAuthorization.toString(), sysRoles, rawAuthorization.getRoles()); + return authorization; + } + + // + // USER ADMIN AGGREGATOR + // + protected void addUserDirectory(AbstractUserDirectory userDirectory) { + LdapName baseDn = userDirectory.getBaseDn(); + if (isSystemRolesBaseDn(baseDn)) { + this.systemRoles = userDirectory; + systemRoles.setExternalRoles(this); + } else { + if (businessRoles.containsKey(baseDn)) + throw new UserDirectoryException("There is already a user admin for " + baseDn); + businessRoles.put(baseDn, userDirectory); + } + userDirectory.init(); + postAdd(userDirectory); + } + + /** Called after a new user directory has been added */ + protected void postAdd(AbstractUserDirectory userDirectory) { + } + + private UserAdmin findUserAdmin(String name) { + try { + return findUserAdmin(new LdapName(name)); + } catch (InvalidNameException e) { + throw new UserDirectoryException("Badly formatted name " + name, e); + } + } + + private UserAdmin findUserAdmin(LdapName name) { + if (name.startsWith(systemRolesBaseDn)) + return systemRoles; + List res = new ArrayList(1); + for (LdapName baseDn : businessRoles.keySet()) { + if (name.startsWith(baseDn)) + res.add(businessRoles.get(baseDn)); + } + if (res.size() == 0) + throw new UserDirectoryException("Cannot find user admin for " + name); + if (res.size() > 1) + throw new UserDirectoryException("Multiple user admin found for " + name); + return res.get(0); + } + + protected boolean isSystemRolesBaseDn(LdapName baseDn) { + return baseDn.equals(systemRolesBaseDn); + } + + protected Dictionary currentState() { + Dictionary res = new Hashtable(); + // res.put(NodeConstants.CN, NodeConstants.DEFAULT); + for (LdapName name : businessRoles.keySet()) { + AbstractUserDirectory userDirectory = businessRoles.get(name); + String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString(); + res.put(uri, ""); + } + return res; + } + + public void destroy() { + for (LdapName name : businessRoles.keySet()) { + AbstractUserDirectory userDirectory = businessRoles.get(name); + destroy(userDirectory); + } + businessRoles.clear(); + businessRoles = null; + destroy(systemRoles); + systemRoles = null; + } + + private void destroy(AbstractUserDirectory userDirectory) { + preDestroy(userDirectory); + userDirectory.destroy(); + } + + protected void removeUserDirectory(LdapName baseDn) { + if (isSystemRolesBaseDn(baseDn)) + throw new UserDirectoryException("System roles cannot be removed "); + if (!businessRoles.containsKey(baseDn)) + throw new UserDirectoryException("No user directory registered for " + baseDn); + AbstractUserDirectory userDirectory = businessRoles.remove(baseDn); + destroy(userDirectory); + } + + /** + * Called before each user directory is destroyed, so that additional + * actions can be performed. + */ + protected void preDestroy(UserDirectory userDirectory) { + } + +} diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java index c2e26ca4c..b1360c65c 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -113,7 +113,7 @@ public class LdapUserAdmin extends AbstractUserDirectory { SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchBase = getBaseDn(); + LdapName searchBase = getBaseDn(); NamingEnumeration results = getLdapContext().search(searchBase, searchFilter, searchControls); ArrayList res = new ArrayList(); @@ -139,7 +139,7 @@ public class LdapUserAdmin extends AbstractUserDirectory { } } - private LdapName toDn(String baseDn, Binding binding) throws InvalidNameException { + private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException { return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName()); } @@ -153,7 +153,7 @@ public class LdapUserAdmin extends AbstractUserDirectory { SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchBase = getBaseDn(); + LdapName searchBase = getBaseDn(); NamingEnumeration results = getLdapContext().search(searchBase, searchFilter, searchControls); while (results.hasMoreElements()) { diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java index 149172122..e5de73836 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserDirectory.java @@ -1,27 +1,23 @@ package org.argeo.osgi.useradmin; -import java.util.Dictionary; - -import javax.transaction.TransactionManager; +import javax.naming.ldap.LdapName; import javax.transaction.xa.XAResource; -import org.osgi.service.useradmin.UserAdmin; - /** Information about a user directory. */ public interface UserDirectory { - public String getBaseDn(); + /** The base DN of all entries in this user directory */ + public LdapName getBaseDn(); - public void setExternalRoles(UserAdmin externalRoles); + /** The related {@link XAResource} */ + public XAResource getXaResource(); - /** Keys listed and described in {@link UserAdminConf}. */ - public Dictionary getProperties(); + public boolean isReadOnly(); - // Transitional. In the future, more will be managed in OSGi. - public void setTransactionManager(TransactionManager transactionManager); + public String getUserObjectClass(); - public void init(); + public String getUserBase(); - public void destroy(); + public String getGroupObjectClass(); - public XAResource getXaResource(); + public String getGroupBase(); } -- 2.30.2