X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FNodeUserAdmin.java;h=d0cf93d80c21e117cf36aae65c869c44981e1a31;hb=85688af22a77f82e7762e11e6eb38c6367eddb6c;hp=9dd516137ebe72e268689df709c625132e290e22;hpb=25071ab6bcb2df1fa4057c2c04137f2d606772e7;p=lgpl%2Fargeo-commons.git 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 9dd516137..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 @@ -1,188 +1,127 @@ package org.argeo.cms.internal.kernel; -import java.util.ArrayList; -import java.util.Arrays; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Dictionary; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; +import java.util.Hashtable; import java.util.Map; -import java.util.Set; -import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; -import javax.transaction.Transaction; import javax.transaction.TransactionManager; -import javax.transaction.TransactionSynchronizationRegistry; -import org.argeo.cms.KernelHeader; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.cms.CmsException; +import org.argeo.node.NodeConstants; import org.argeo.osgi.useradmin.AbstractUserDirectory; -import org.argeo.osgi.useradmin.UserAdminAggregator; -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.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.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; import org.osgi.service.useradmin.UserAdmin; - -public class NodeUserAdmin implements UserAdmin, UserAdminAggregator { - final static LdapName ROLES_BASE; - static { - try { - ROLES_BASE = new LdapName(KernelHeader.ROLES_BASEDN); - } catch (InvalidNameException e) { - throw new UserDirectoryException("Cannot initialize " - + NodeUserAdmin.class, e); - } - } - - private UserAdmin nodeRoles = null; - private Map userAdmins = new HashMap(); - - private TransactionSynchronizationRegistry syncRegistry; - private TransactionManager transactionManager; - - @Override - public Role createRole(String name, int type) { - return findUserAdmin(name).createRole(name, type); +import org.osgi.util.tracker.ServiceTracker; + +import bitronix.tm.BitronixTransactionManager; +import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer; + +/** + * Aggregates multiple {@link UserDirectory} and integrates them with system + * roles. + */ +class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactory, KernelConstants { + private final static Log log = LogFactory.getLog(NodeUserAdmin.class); + private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); + + // OSGi + private Map pidToBaseDn = new HashMap<>(); + private Map> pidToServiceRegs = new HashMap<>(); + private ServiceRegistration userAdminReg; + + // JTA + private final ServiceTracker tmTracker; + private final String cacheName = UserDirectory.class.getName(); + + public NodeUserAdmin(String systemRolesBaseDn) { + super(systemRolesBaseDn); + tmTracker = new ServiceTracker<>(bc, TransactionManager.class, null); + tmTracker.open(); } @Override - public boolean removeRole(String name) { - return findUserAdmin(name).removeRole(name); - } - - @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))); + public void updated(String pid, Dictionary properties) throws ConfigurationException { + String uri = (String) properties.get(UserAdminConf.uri.name()); + URI u; + try { + u = new URI(uri); + } catch (URISyntaxException e) { + throw new CmsException("Badly formatted URI " + uri, e); } - 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); + // Create + AbstractUserDirectory userDirectory = u.getScheme().equals("ldap") ? new LdapUserAdmin(properties) + : new LdifUserAdmin(properties); + addUserDirectory(userDirectory); + + // 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); + ServiceRegistration reg = bc.registerService(UserDirectory.class, userDirectory, regProps); + pidToBaseDn.put(pid, baseDn); + pidToServiceRegs.put(pid, reg); + + if (log.isDebugEnabled()) + log.debug("User directory " + userDirectory.getBaseDn() + " [" + u.getScheme() + "] enabled."); + + if (!isSystemRolesBaseDn(baseDn)) { + if (userAdminReg != null) + userAdminReg.unregister(); + // register self as main user admin + Dictionary userAdminregProps = currentState(); + userAdminregProps.put(NodeConstants.CN, NodeConstants.DEFAULT); + userAdminregProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); + userAdminReg = bc.registerService(UserAdmin.class, this, userAdminregProps); } - // 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) { - 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())); - } - return new NodeAuthorization(rawAuthorization.getName(), - rawAuthorization.toString(), systemRoles, - rawAuthorization.getRoles()); + public void deleted(String pid) { + assert pidToServiceRegs.get(pid) != null; + assert pidToBaseDn.get(pid) != null; + pidToServiceRegs.remove(pid).unregister(); + LdapName baseDn = pidToBaseDn.remove(pid); + removeUserDirectory(baseDn); } - // - // USER ADMIN AGGREGATOR - // @Override - public synchronized void addUserAdmin(String baseDn, UserAdmin userAdmin) { - if (userAdmin instanceof AbstractUserDirectory) - ((AbstractUserDirectory) userAdmin).setSyncRegistry(syncRegistry); - - if (baseDn.equals(KernelHeader.ROLES_BASEDN)) { - nodeRoles = userAdmin; - return; - } - - if (userAdmins.containsKey(baseDn)) - throw new UserDirectoryException( - "There is already a user admin for " + baseDn); - try { - userAdmins.put(new LdapName(baseDn), userAdmin); - } catch (InvalidNameException e) { - throw new UserDirectoryException("Badly formatted base DN " - + baseDn, e); - } - } - - @Override - public synchronized void removeUserAdmin(String baseDn) { - 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 UserDirectoryException("Badly formatted base DN " - + baseDn, e); - } - if (!userAdmins.containsKey(base)) - throw new UserDirectoryException("There is no user admin for " - + base); - UserAdmin userAdmin = userAdmins.remove(base); - if (userAdmin instanceof AbstractUserDirectory) - ((AbstractUserDirectory) userAdmin).setSyncRegistry(null); + public String getName() { + return "Node User Admin"; } - 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); + 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 setTransactionManager(TransactionManager transactionManager) { - this.transactionManager = transactionManager; - if (nodeRoles instanceof AbstractUserDirectory) - ((AbstractUserDirectory) nodeRoles) - .setTransactionManager(transactionManager); - for (UserAdmin userAdmin : userAdmins.values()) { - if (userAdmin instanceof AbstractUserDirectory) - ((AbstractUserDirectory) userAdmin) - .setTransactionManager(transactionManager); - } - } - - public void setSyncRegistry(TransactionSynchronizationRegistry syncRegistry) { - this.syncRegistry = syncRegistry; - if (nodeRoles instanceof AbstractUserDirectory) - ((AbstractUserDirectory) nodeRoles).setSyncRegistry(syncRegistry); - for (UserAdmin userAdmin : userAdmins.values()) { - if (userAdmin instanceof AbstractUserDirectory) - ((AbstractUserDirectory) userAdmin) - .setSyncRegistry(syncRegistry); - } + protected void preDestroy(UserDirectory userDirectory) { + if (tmTracker.getService() instanceof BitronixTransactionManager) + EhCacheXAResourceProducer.unregisterXAResource(cacheName, userDirectory.getXaResource()); } }