From 3400a80f88b418c598bf30f27b13ce1360902376 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 10 Aug 2016 17:41:06 +0000 Subject: [PATCH] Continue framework clean up. git-svn-id: https://svn.argeo.org/commons/trunk@9082 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../cms/internal/kernel/KernelUtils.java | 35 +-- .../cms/internal/kernel/NodeDeployConfig.java | 100 ++++++++ .../cms/internal/kernel/NodeUserAdmin.java | 2 +- .../transaction/SimpleTransaction.java | 164 ------------ .../transaction/SimpleTransactionManager.java | 185 ------------- .../cms/internal/transaction/UuidXid.java | 132 ---------- .../osgi/useradmin/AbstractUserDirectory.java | 88 +------ .../argeo/osgi/useradmin/LdifUserAdmin.java | 4 +- .../argeo/osgi/useradmin/UserAdminConf.java | 79 +++--- .../internal/UserDirectoryFactory.java | 45 ++++ .../internal/AbstractUserAdminWrapper.java | 105 ++++++++ .../ui/admin/internal/UserAdminUtils.java | 242 ++++++++++++++++++ .../ui/admin/internal/UserAdminWrapper.java | 2 +- .../admin/internal/commands/DeleteGroups.java | 2 +- .../admin/internal/commands/DeleteUsers.java | 2 +- .../ui/admin/internal/commands/NewUser.java | 2 +- .../admin/internal/parts/GroupMainPage.java | 2 +- .../ui/admin/internal/parts/GroupsView.java | 2 +- .../internal/parts/UserBatchUpdateWizard.java | 2 +- .../ui/admin/internal/parts/UserEditor.java | 2 +- .../ui/admin/internal/parts/UserMainPage.java | 2 +- .../ui/admin/internal/parts/UsersView.java | 2 +- .../internal/providers/CommonNameLP.java | 2 +- .../internal/providers/DomainNameLP.java | 2 +- .../ui/admin/internal/providers/MailLP.java | 2 +- .../providers/UserAdminAbstractLP.java | 2 +- .../admin/internal/providers/UserFilter.java | 2 +- 27 files changed, 564 insertions(+), 647 deletions(-) create mode 100644 org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeDeployConfig.java delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransaction.java delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/transaction/UuidXid.java create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/internal/UserDirectoryFactory.java create mode 100644 org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/AbstractUserAdminWrapper.java create mode 100644 org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminUtils.java diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java index 49f8c20a5..cb22e2790 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java @@ -30,8 +30,8 @@ import org.osgi.framework.FrameworkUtil; /** Package utilities */ class KernelUtils implements KernelConstants { - private final static String OSGI_INSTANCE_AREA = "osgi.instance.area"; - private final static String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; + final static String OSGI_INSTANCE_AREA = "osgi.instance.area"; + final static String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; static Dictionary asDictionary(Properties props) { Hashtable hashtable = new Hashtable(); @@ -73,19 +73,20 @@ class KernelUtils implements KernelConstants { static URI getOsgiInstanceUri(String relativePath) { String osgiInstanceBaseUri = getFrameworkProp(OSGI_INSTANCE_AREA); - return safeUri(osgiInstanceBaseUri + (relativePath != null ? relativePath : "")); + return safeUri(osgiInstanceBaseUri + (relativePath != null ? relativePath : "")); } -// static String getOsgiInstancePath(String relativePath) { -// try { -// if (relativePath == null) -// return getOsgiInstanceDir().getCanonicalPath(); -// else -// return new File(getOsgiInstanceDir(), relativePath).getCanonicalPath(); -// } catch (IOException e) { -// throw new CmsException("Cannot get instance path for " + relativePath, e); -// } -// } + // static String getOsgiInstancePath(String relativePath) { + // try { + // if (relativePath == null) + // return getOsgiInstanceDir().getCanonicalPath(); + // else + // return new File(getOsgiInstanceDir(), relativePath).getCanonicalPath(); + // } catch (IOException e) { + // throw new CmsException("Cannot get instance path for " + relativePath, + // e); + // } + // } static File getOsgiConfigurationFile(String relativePath) { try { @@ -195,14 +196,14 @@ class KernelUtils implements KernelConstants { private static BundleContext getBundleContext() { return getBundleContext(KernelUtils.class); } - - private static URI safeUri(String uri){ - if(uri==null) + + private static URI safeUri(String uri) { + if (uri == null) throw new CmsException("URI cannot be null"); try { return new URI(uri); } catch (URISyntaxException e) { - throw new CmsException("Dadly formatted URI "+uri, e); + throw new CmsException("Dadly formatted URI " + uri, e); } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeDeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeDeployConfig.java new file mode 100644 index 000000000..85906b092 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeDeployConfig.java @@ -0,0 +1,100 @@ +package org.argeo.cms.internal.kernel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.SortedMap; +import java.util.function.Function; + +import javax.naming.InvalidNameException; +import javax.naming.directory.Attributes; +import javax.naming.ldap.LdapName; + +import org.argeo.cms.CmsException; +import org.argeo.node.NodeConstants; +import org.argeo.node.RepoConf; +import org.argeo.util.naming.AttributesDictionary; +import org.argeo.util.naming.LdifParser; +import org.argeo.util.naming.LdifWriter; + +class NodeDeployConfig { + private final String BASE = "ou=deploy,ou=node"; + private final Path path; + private final Function getter; + + private final SortedMap configurations; + + public NodeDeployConfig(Function getter) { + String osgiConfigurationArea = getter.apply(KernelUtils.OSGI_CONFIGURATION_AREA); + try { + this.path = Paths.get(new URI(osgiConfigurationArea)); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Cannot parse " + getter.apply(KernelUtils.OSGI_CONFIGURATION_AREA), e); + } + this.getter = getter; + + if (!Files.exists(path)) + try (Writer writer = Files.newBufferedWriter(path)) { + Files.createFile(path); + LdifWriter ldifWriter = new LdifWriter(writer); + } catch (IOException e) { + throw new CmsException("Cannot create " + path, e); + } + + try (InputStream in = Files.newInputStream(path)) { + configurations = new LdifParser().read(in); + } catch (IOException e) { + throw new CmsException("Cannot read " + path, e); + } + } + + public Dictionary getConfiguration(String servicePid) { + LdapName dn; + try { + dn = new LdapName("ou=" + servicePid + "," + BASE); + } catch (InvalidNameException e) { + throw new IllegalArgumentException("Cannot parse DN", e); + } + if (configurations.containsKey(dn)) + return new AttributesDictionary(configurations.get(dn)); + else + return null; + } + + static Dictionary getStatePropertiesFromEnvironment(Function getter) { + Hashtable props = new Hashtable<>(); + // i18n + copyFrameworkProp(getter, NodeConstants.I18N_DEFAULT_LOCALE, props); + copyFrameworkProp(getter, NodeConstants.I18N_LOCALES, props); + // user admin + copyFrameworkProp(getter, NodeConstants.ROLES_URI, props); + copyFrameworkProp(getter, NodeConstants.USERADMIN_URIS, props); + // data + for (RepoConf repoConf : RepoConf.values()) + copyFrameworkProp(getter, NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name(), props); + // TODO add other environment sources + return props; + } + + static Dictionary getUserAdminPropertiesFromEnvironment(Function getter) { + Hashtable props = new Hashtable<>(); + copyFrameworkProp(getter, NodeConstants.ROLES_URI, props); + copyFrameworkProp(getter, NodeConstants.USERADMIN_URIS, props); + return props; + } + + private static void copyFrameworkProp(Function getter, String key, + Dictionary props) { + String value = getter.apply(key); + if (value != null) + props.put(key, value); + } + +} 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 8f1c36860..fd9ba31df 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 @@ -365,7 +365,7 @@ class NodeUserAdmin implements UserAdmin, ManagedService, KernelConstants { } Dictionary nodeRolesProperties = UserAdminConf.uriAsProperties(nodeRolesUri); - if (!nodeRolesProperties.get(UserAdminConf.baseDn.property()).equals(baseNodeRoleDn)) { + 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 } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransaction.java b/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransaction.java deleted file mode 100644 index f3a27fe53..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransaction.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.argeo.cms.internal.transaction; - -import java.util.ArrayList; -import java.util.List; - -import javax.transaction.HeuristicMixedException; -import javax.transaction.HeuristicRollbackException; -import javax.transaction.RollbackException; -import javax.transaction.Status; -import javax.transaction.Synchronization; -import javax.transaction.SystemException; -import javax.transaction.Transaction; -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; -import javax.transaction.xa.Xid; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -class SimpleTransaction implements Transaction, Status { - private final static Log log = LogFactory.getLog(SimpleTransaction.class); - - private final Xid xid; - private int status = Status.STATUS_ACTIVE; - private final List xaResources = new ArrayList(); - - private final SimpleTransactionManager transactionManager; - - public SimpleTransaction(SimpleTransactionManager transactionManager) { - this.xid = new UuidXid(); - this.transactionManager = transactionManager; - } - - @Override - public synchronized void commit() throws RollbackException, - HeuristicMixedException, HeuristicRollbackException, - SecurityException, IllegalStateException, SystemException { - status = STATUS_PREPARING; - for (XAResource xaRes : xaResources) { - if (status == STATUS_MARKED_ROLLBACK) - break; - try { - xaRes.prepare(xid); - } catch (XAException e) { - status = STATUS_MARKED_ROLLBACK; - log.error("Cannot prepare " + xaRes + " for " + xid, e); - } - } - if (status == STATUS_MARKED_ROLLBACK) { - rollback(); - throw new RollbackException(); - } - status = STATUS_PREPARED; - - status = STATUS_COMMITTING; - for (XAResource xaRes : xaResources) { - if (status == STATUS_MARKED_ROLLBACK) - break; - try { - xaRes.commit(xid, false); - } catch (XAException e) { - status = STATUS_MARKED_ROLLBACK; - log.error("Cannot prepare " + xaRes + " for " + xid, e); - } - } - if (status == STATUS_MARKED_ROLLBACK) { - rollback(); - throw new RollbackException(); - } - - // complete - status = STATUS_COMMITTED; - if (log.isDebugEnabled()) - log.debug("COMMITTED " + xid); - clearResources(XAResource.TMSUCCESS); - transactionManager.unregister(xid); - } - - @Override - public synchronized void rollback() throws IllegalStateException, - SystemException { - status = STATUS_ROLLING_BACK; - for (XAResource xaRes : xaResources) { - try { - xaRes.rollback(xid); - } catch (XAException e) { - log.error("Cannot rollback " + xaRes + " for " + xid, e); - } - } - - // complete - status = STATUS_ROLLEDBACK; - if (log.isDebugEnabled()) - log.debug("ROLLEDBACK " + xid); - clearResources(XAResource.TMFAIL); - transactionManager.unregister(xid); - } - - @Override - public synchronized boolean enlistResource(XAResource xaRes) - throws RollbackException, IllegalStateException, SystemException { - if (xaResources.add(xaRes)) { - try { - xaRes.start(getXid(), XAResource.TMNOFLAGS); - return true; - } catch (XAException e) { - log.error("Cannot enlist " + xaRes, e); - return false; - } - } else - return false; - } - - @Override - public synchronized boolean delistResource(XAResource xaRes, int flag) - throws IllegalStateException, SystemException { - if (xaResources.remove(xaRes)) { - try { - xaRes.end(getXid(), flag); - } catch (XAException e) { - log.error("Cannot delist " + xaRes, e); - return false; - } - return true; - } else - return false; - } - - protected void clearResources(int flag) { - for (XAResource xaRes : xaResources) - try { - xaRes.end(getXid(), flag); - } catch (XAException e) { - log.error("Cannot end " + xaRes, e); - } - xaResources.clear(); - } - - @Override - public synchronized int getStatus() throws SystemException { - return status; - } - - @Override - public void registerSynchronization(Synchronization sync) - throws RollbackException, IllegalStateException, SystemException { - throw new UnsupportedOperationException(); - } - - @Override - public void setRollbackOnly() throws IllegalStateException, SystemException { - status = STATUS_MARKED_ROLLBACK; - } - - @Override - public int hashCode() { - return xid.hashCode(); - } - - Xid getXid() { - return xid; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java b/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java deleted file mode 100644 index 30d9b7291..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java +++ /dev/null @@ -1,185 +0,0 @@ -package org.argeo.cms.internal.transaction; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.transaction.HeuristicMixedException; -import javax.transaction.HeuristicRollbackException; -import javax.transaction.InvalidTransactionException; -import javax.transaction.NotSupportedException; -import javax.transaction.RollbackException; -import javax.transaction.Status; -import javax.transaction.Synchronization; -import javax.transaction.SystemException; -import javax.transaction.Transaction; -import javax.transaction.TransactionManager; -import javax.transaction.TransactionSynchronizationRegistry; -import javax.transaction.UserTransaction; -import javax.transaction.xa.Xid; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.CmsException; - -public class SimpleTransactionManager implements TransactionManager, - UserTransaction { - private final static Log log = LogFactory - .getLog(SimpleTransactionManager.class); - - private ThreadLocal current = new ThreadLocal(); - - private Map knownTransactions = Collections - .synchronizedMap(new HashMap()); - private SyncRegistry syncRegistry = new SyncRegistry(); - - @Override - public void begin() throws NotSupportedException, SystemException { - if (getCurrent() != null) - throw new NotSupportedException( - "Nested transactions are not supported"); - SimpleTransaction transaction = new SimpleTransaction(this); - knownTransactions.put(transaction.getXid(), transaction); - current.set(transaction); - if (log.isDebugEnabled()) - log.debug("STARTED " + transaction.getXid()); - } - - @Override - public void commit() throws RollbackException, HeuristicMixedException, - HeuristicRollbackException, SecurityException, - IllegalStateException, SystemException { - if (getCurrent() == null) - throw new IllegalStateException( - "No transaction registered with the current thread."); - getCurrent().commit(); - } - - @Override - public int getStatus() throws SystemException { - if (getCurrent() == null) - return Status.STATUS_NO_TRANSACTION; - return getTransaction().getStatus(); - } - - @Override - public Transaction getTransaction() throws SystemException { - return getCurrent(); - } - - protected SimpleTransaction getCurrent() throws SystemException { - SimpleTransaction transaction = current.get(); - if (transaction == null) - return null; - int status = transaction.getStatus(); - if (Status.STATUS_COMMITTED == status - || Status.STATUS_ROLLEDBACK == status) { - current.remove(); - return null; - } - return transaction; - } - - void unregister(Xid xid){ - knownTransactions.remove(xid); - } - - @Override - public void resume(Transaction tobj) throws InvalidTransactionException, - IllegalStateException, SystemException { - if (getCurrent() != null) - throw new IllegalStateException("Transaction " + current.get() - + " already registered"); - current.set((SimpleTransaction) tobj); - } - - @Override - public void rollback() throws IllegalStateException, SecurityException, - SystemException { - if (getCurrent() == null) - throw new IllegalStateException( - "No transaction registered with the current thread."); - getCurrent().rollback(); - } - - @Override - public void setRollbackOnly() throws IllegalStateException, SystemException { - if (getCurrent() == null) - throw new IllegalStateException( - "No transaction registered with the current thread."); - getCurrent().setRollbackOnly(); - } - - @Override - public void setTransactionTimeout(int seconds) throws SystemException { - throw new UnsupportedOperationException(); - } - - @Override - public Transaction suspend() throws SystemException { - Transaction transaction = getCurrent(); - current.remove(); - return transaction; - } - - public TransactionSynchronizationRegistry getTsr() { - return syncRegistry; - } - - private class SyncRegistry implements TransactionSynchronizationRegistry { - @Override - public Object getTransactionKey() { - try { - SimpleTransaction transaction = getCurrent(); - if (transaction == null) - return null; - return getCurrent().getXid(); - } catch (SystemException e) { - throw new CmsException("Cannot get transaction key", e); - } - } - - @Override - public void putResource(Object key, Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public Object getResource(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerInterposedSynchronization(Synchronization sync) { - throw new UnsupportedOperationException(); - } - - @Override - public int getTransactionStatus() { - try { - return getStatus(); - } catch (SystemException e) { - throw new CmsException("Cannot get status", e); - } - } - - @Override - public boolean getRollbackOnly() { - try { - return getStatus() == Status.STATUS_MARKED_ROLLBACK; - } catch (SystemException e) { - throw new CmsException("Cannot get status", e); - } - } - - @Override - public void setRollbackOnly() { - try { - getCurrent().setRollbackOnly(); - } catch (Exception e) { - throw new CmsException("Cannot set rollback only", e); - } - } - - } -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/transaction/UuidXid.java b/org.argeo.cms/src/org/argeo/cms/internal/transaction/UuidXid.java deleted file mode 100644 index 18975ead8..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/transaction/UuidXid.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.argeo.cms.internal.transaction; - -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.UUID; - -import javax.transaction.xa.Xid; - -/** - * Implementation of {@link Xid} based on {@link UUID}, using max significant - * bits as global transaction id, and least significant bits as branch - * qualifier. - */ -public class UuidXid implements Xid, Serializable { - private static final long serialVersionUID = -5380531989917886819L; - public final static int FORMAT = (int) serialVersionUID; - - private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE; - - private final int format; - private final byte[] globalTransactionId; - private final byte[] branchQualifier; - private final String uuid; - private final int hashCode; - - public UuidXid() { - this(UUID.randomUUID()); - } - - public UuidXid(UUID uuid) { - this.format = FORMAT; - this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits()); - this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits()); - this.uuid = uuid.toString(); - this.hashCode = uuid.hashCode(); - } - - public UuidXid(Xid xid) { - this(xid.getFormatId(), xid.getGlobalTransactionId(), xid - .getBranchQualifier()); - } - - private UuidXid(int format, byte[] globalTransactionId, - byte[] branchQualifier) { - this.format = format; - this.globalTransactionId = globalTransactionId; - this.branchQualifier = branchQualifier; - this.uuid = bytesToUUID(globalTransactionId, branchQualifier) - .toString(); - this.hashCode = uuid.hashCode(); - } - - @Override - public int getFormatId() { - return format; - } - - @Override - public byte[] getGlobalTransactionId() { - return Arrays.copyOf(globalTransactionId, globalTransactionId.length); - } - - @Override - public byte[] getBranchQualifier() { - return Arrays.copyOf(branchQualifier, branchQualifier.length); - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj instanceof UuidXid) { - UuidXid that = (UuidXid) obj; - return Arrays.equals(globalTransactionId, that.globalTransactionId) - && Arrays.equals(branchQualifier, that.branchQualifier); - } - if (obj instanceof Xid) { - Xid that = (Xid) obj; - return Arrays.equals(globalTransactionId, - that.getGlobalTransactionId()) - && Arrays - .equals(branchQualifier, that.getBranchQualifier()); - } - return uuid.equals(obj.toString()); - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return new UuidXid(format, globalTransactionId, branchQualifier); - } - - @Override - public String toString() { - return uuid; - } - - public UUID asUuid() { - return bytesToUUID(globalTransactionId, branchQualifier); - } - - public static byte[] uuidToBytes(long bits) { - ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG); - buffer.putLong(0, bits); - return buffer.array(); - } - - public static UUID bytesToUUID(byte[] most, byte[] least) { - if (most.length < BYTES_PER_LONG) - most = Arrays.copyOf(most, BYTES_PER_LONG); - if (least.length < BYTES_PER_LONG) - least = Arrays.copyOf(least, BYTES_PER_LONG); - ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG); - buffer.put(most, 0, BYTES_PER_LONG); - buffer.put(least, 0, BYTES_PER_LONG); - buffer.flip(); - return new UUID(buffer.getLong(), buffer.getLong()); - } - - // public static void main(String[] args) { - // UUID uuid = UUID.randomUUID(); - // System.out.println(uuid); - // uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()), - // uuidToBytes(uuid.getLeastSignificantBits())); - // System.out.println(uuid); - // } -} 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 768610b8e..121fb3500 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 @@ -57,13 +57,8 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { private List credentialAttributeIds = Arrays.asList(new String[] { LdifName.userPassword.name() }); private TransactionManager transactionManager; - // private TransactionSynchronizationRegistry transactionRegistry; - // private Xid editingTransactionXid = null; private WcXaResource xaResource = new WcXaResource(this); - // POSIX - private String homeDirectoryBase = "/home"; - AbstractUserDirectory(Dictionary props) { properties = new Hashtable(); for (Enumeration keys = props.keys(); keys.hasMoreElements();) { @@ -85,7 +80,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { String readOnlyStr = UserAdminConf.readOnly.getValue(properties); if (readOnlyStr == null) { readOnly = readOnlyDefault(uri); - properties.put(UserAdminConf.readOnly.property(), Boolean.toString(readOnly)); + properties.put(UserAdminConf.readOnly.name(), Boolean.toString(readOnly)); } else readOnly = new Boolean(readOnlyStr); @@ -111,21 +106,13 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } boolean isEditing() { - // if (editingTransactionXid == null) - // return false; - // return workingCopy.get() != null; return xaResource.wc() != null; } protected UserDirectoryWorkingCopy getWorkingCopy() { - // UserDirectoryWorkingCopy wc = workingCopy.get(); UserDirectoryWorkingCopy wc = xaResource.wc(); if (wc == null) return null; - // if (wc.getXid() == null) { - // workingCopy.set(null); - // return null; - // } return wc; } @@ -139,24 +126,12 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { if (transaction == null) throw new UserDirectoryException("A transaction needs to be active in order to edit"); if (xaResource.wc() == null) { - // UserDirectoryWorkingCopy wc = new UserDirectoryWorkingCopy(this); try { transaction.enlistResource(xaResource); - // editingTransactionXid = wc.getXid(); - // workingCopy.set(wc); } catch (Exception e) { throw new UserDirectoryException("Cannot enlist " + xaResource, e); } } else { - // UserDirectoryWorkingCopy wc = xaResource.wc(); - // if (wc == null) - // throw new UserDirectoryException("Transaction " - // + editingTransactionXid + " already editing"); - // else if - // (!editingTransactionXid.equals(workingCopy.get().getXid())) - // throw new UserDirectoryException("Working copy Xid " - // + workingCopy.get().getXid() + " inconsistent with" - // + editingTransactionXid); } } @@ -336,62 +311,6 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { return actuallyDeleted; } - // // POSIX - // /** Generate path for a new user home */ - // protected String generateHomeDirectory(String username) { - // String base = homeDirectoryBase; - // int atIndex = username.indexOf('@'); - // if (atIndex > 0) { - // String domain = username.substring(0, atIndex); - // String name = username.substring(atIndex + 1); - // return base + '/' + firstCharsToPath(domain, 2) + '/' + domain + '/' + - // firstCharsToPath(name, 2) + '/' - // + name; - // } else if (atIndex == 0 || atIndex == (username.length() - 1)) { - // throw new ArgeoException("Unsupported username " + username); - // } else { - // return base + '/' + firstCharsToPath(username, 2) + '/' + username; - // } - // } - // - // protected long max(String attr) { - // long max; - // try { - // List users = doGetRoles(FrameworkUtil.createFilter("(" + - // attr + "=*)")); - // max = 1000; - // for (DirectoryUser user : users) { - // long uid = - // Long.parseLong(user.getAttributes().get(attr).get().toString()); - // if (uid > max) - // max = uid; - // } - // } catch (Exception e) { - // throw new UserDirectoryException("Cannot get max of " + attr, e); - // } - // return max; - // } - - // /** - // * Creates depth from a string (typically a username) by adding levels - // based - // * on its first characters: "aBcD",2 => a/aB - // */ - // public static String firstCharsToPath(String str, Integer nbrOfChars) { - // if (str.length() < nbrOfChars) - // throw new ArgeoException("String " + str + " length must be greater or - // equal than " + nbrOfChars); - // StringBuffer path = new StringBuffer(""); - // StringBuffer curr = new StringBuffer(""); - // for (int i = 0; i < nbrOfChars; i++) { - // curr.append(str.charAt(i)); - // path.append(curr); - // if (i < nbrOfChars - 1) - // path.append('/'); - // } - // return path.toString(); - // } - // TRANSACTION protected void prepare(UserDirectoryWorkingCopy wc) { @@ -405,10 +324,6 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } - // void clearEditingTransactionXid() { - // editingTransactionXid = null; - // } - // UTILITIES protected LdapName toDn(String name) { try { @@ -419,7 +334,6 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } // GETTERS - String getMemberAttributeId() { return memberAttributeId; } 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 fbedeb79c..366c32fa0 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 @@ -51,8 +51,8 @@ public class LdifUserAdmin extends AbstractUserDirectory { private static Dictionary fromUri(String uri, String baseDn) { Hashtable res = new Hashtable(); - res.put(UserAdminConf.uri.property(), uri); - res.put(UserAdminConf.baseDn.property(), baseDn); + res.put(UserAdminConf.uri.name(), uri); + res.put(UserAdminConf.baseDn.name(), baseDn); return res; } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminConf.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminConf.java index baf487bb0..5a9cd8c41 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminConf.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/UserAdminConf.java @@ -37,7 +37,7 @@ public enum UserAdminConf { /** Read-only source */ readOnly(null); - public final static String PREFIX = "argeo.useradmin"; + public final static String FACTORY_PID = "org.argeo.osgi.useradmin.config"; /** The default value. */ private Object def; @@ -50,13 +50,14 @@ public enum UserAdminConf { return def; } - /** For use as Java property. */ + /** + * For use as Java property. + * + * @deprecated use {@link #name()} instead + */ + @Deprecated public String property() { - return getPrefix() + '.' + name(); - } - - public String getPrefix() { - return PREFIX; + return name(); } public String getValue(Dictionary properties) { @@ -68,14 +69,16 @@ public enum UserAdminConf { @SuppressWarnings("unchecked") public T getRawValue(Dictionary properties) { - Object res = properties.get(property()); + Object res = properties.get(name()); if (res == null) res = getDefault(); return (T) res; } + /** @deprecated use {@link #valueOf(String)} instead */ + @Deprecated public static UserAdminConf local(String property) { - return UserAdminConf.valueOf(property.substring(PREFIX.length() + 1)); + return UserAdminConf.valueOf(property); } /** Hides host and credentials. */ @@ -83,27 +86,24 @@ public enum UserAdminConf { StringBuilder query = new StringBuilder(); boolean first = true; - for (Enumeration keys = properties.keys(); keys - .hasMoreElements();) { + for (Enumeration keys = properties.keys(); keys.hasMoreElements();) { String key = keys.nextElement(); - if (key.startsWith(PREFIX) && !key.equals(baseDn.property()) - && !key.equals(uri.property())) { + if (!key.startsWith("java") && !key.equals(baseDn.name()) && !key.equals(uri.name())) { if (first) first = false; else query.append('&'); - query.append(local(key).name()); + query.append(valueOf(key).name()); query.append('=').append(properties.get(key).toString()); } } - String bDn = (String) properties.get(baseDn.property()); + String bDn = (String) properties.get(baseDn.name()); try { - return new URI(null, null, bDn != null ? '/' + bDn : null, - query.length() != 0 ? query.toString() : null, null); + return new URI(null, null, bDn != null ? '/' + bDn : null, query.length() != 0 ? query.toString() : null, + null); } catch (URISyntaxException e) { - throw new UserDirectoryException( - "Cannot create URI from properties", e); + throw new UserDirectoryException("Cannot create URI from properties", e); } } @@ -113,8 +113,7 @@ public enum UserAdminConf { URI u = new URI(uriStr); String scheme = u.getScheme(); String path = u.getPath(); - String bDn = path.substring(path.lastIndexOf('/') + 1, - path.length()); + String bDn = path.substring(path.lastIndexOf('/') + 1, path.length()); if (bDn.endsWith(".ldif")) bDn = bDn.substring(0, bDn.length() - ".ldif".length()); @@ -128,20 +127,18 @@ public enum UserAdminConf { credentials = userInfo.length > 1 ? userInfo[1] : null; } else if (scheme.equals("file")) { } else - throw new UserDirectoryException("Unsupported scheme " - + scheme); + throw new UserDirectoryException("Unsupported scheme " + scheme); Map> query = splitQuery(u.getQuery()); for (String key : query.keySet()) { UserAdminConf ldapProp = UserAdminConf.valueOf(key); List values = query.get(key); if (values.size() == 1) { - res.put(ldapProp.property(), values.get(0)); + res.put(ldapProp.name(), values.get(0)); } else { - throw new UserDirectoryException( - "Only single values are supported"); + throw new UserDirectoryException("Only single values are supported"); } } - res.put(baseDn.property(), bDn); + res.put(baseDn.name(), bDn); if (principal != null) res.put(Context.SECURITY_PRINCIPAL, principal); if (credentials != null) @@ -149,48 +146,42 @@ public enum UserAdminConf { if (scheme != null) { URI bareUri = new URI(scheme, null, u.getHost(), u.getPort(), scheme.equals("file") ? u.getPath() : null, null, null); - res.put(uri.property(), bareUri.toString()); + res.put(uri.name(), bareUri.toString()); } return res; } catch (Exception e) { - throw new UserDirectoryException("Cannot convert " + uri - + " to properties", e); + throw new UserDirectoryException("Cannot convert " + uri + " to properties", e); } } - private static Map> splitQuery(String query) - throws UnsupportedEncodingException { + private static Map> splitQuery(String query) throws UnsupportedEncodingException { final Map> query_pairs = new LinkedHashMap>(); if (query == null) return query_pairs; final String[] pairs = query.split("&"); for (String pair : pairs) { final int idx = pair.indexOf("="); - final String key = idx > 0 ? URLDecoder.decode( - pair.substring(0, idx), "UTF-8") : pair; + final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair; if (!query_pairs.containsKey(key)) { query_pairs.put(key, new LinkedList()); } - final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder - .decode(pair.substring(idx + 1), "UTF-8") : null; + final String value = idx > 0 && pair.length() > idx + 1 + ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null; query_pairs.get(key).add(value); } return query_pairs; } public static void main(String[] args) { - Dictionary props = uriAsProperties("ldap://" - + "uid=admin,ou=system:secret@localhost:10389" - + "/dc=example,dc=com" - + "?readOnly=false&userObjectClass=person"); + Dictionary props = uriAsProperties("ldap://" + "uid=admin,ou=system:secret@localhost:10389" + + "/dc=example,dc=com" + "?readOnly=false&userObjectClass=person"); System.out.println(props); System.out.println(propertiesAsUri(props)); - System.out - .println(uriAsProperties("file://some/dir/dc=example,dc=com.ldif")); + System.out.println(uriAsProperties("file://some/dir/dc=example,dc=com.ldif")); - props = uriAsProperties("/dc=example,dc=com.ldif?readOnly=true" - + "&userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles"); + props = uriAsProperties( + "/dc=example,dc=com.ldif?readOnly=true" + "&userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles"); System.out.println(props); System.out.println(propertiesAsUri(props)); } diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/internal/UserDirectoryFactory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/internal/UserDirectoryFactory.java new file mode 100644 index 000000000..2182028d9 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/internal/UserDirectoryFactory.java @@ -0,0 +1,45 @@ +package org.argeo.osgi.useradmin.internal; + +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; + +public class UserDirectoryFactory implements ManagedServiceFactory { + private final BundleContext bc = FrameworkUtil.getBundle(UserDirectoryFactory.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); + Dictionary regProps = new Hashtable<>(); + regProps.put(Constants.SERVICE_PID, pid); + 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); + } + +} diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/AbstractUserAdminWrapper.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/AbstractUserAdminWrapper.java new file mode 100644 index 000000000..e222656df --- /dev/null +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/AbstractUserAdminWrapper.java @@ -0,0 +1,105 @@ +package org.argeo.security.ui.admin.internal; + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.transaction.Status; +import javax.transaction.UserTransaction; + +import org.argeo.ArgeoException; +import org.argeo.cms.auth.AuthConstants; +import org.argeo.osgi.useradmin.UserAdminConf; +import org.osgi.framework.ServiceReference; +import org.osgi.service.useradmin.UserAdmin; +import org.osgi.service.useradmin.UserAdminEvent; +import org.osgi.service.useradmin.UserAdminListener; + +/** + * Base useradmin wrapper. Implementing application might extends to add + * business specific behaviour + */ +public abstract class AbstractUserAdminWrapper { + // private Log log = LogFactory.getLog(UserAdminWrapper.class); + + private UserAdmin userAdmin; + private ServiceReference userAdminServiceReference; + private UserTransaction userTransaction; + + /* USER ADMIN LISTENER MANAGEMENT */ + List listeners = new ArrayList(); + + // TODO implement safer mechanism + public void addListener(UserAdminListener userAdminListener) { + if (!listeners.contains(userAdminListener)) + listeners.add(userAdminListener); + } + + /** + * Starts a transaction if none already exists and notify the userAdmin + * listeners.Must be called from the UI Thread. + */ + public UserTransaction beginTransactionIfNeeded() { + try { + if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION) { + userTransaction.begin(); + } + return userTransaction; + } catch (Exception e) { + throw new ArgeoException("Unable to begin transaction", e); + } + } + + // Expose this? + public void removeListener(UserAdminListener userAdminListener) { + if (listeners.contains(userAdminListener)) + listeners.remove(userAdminListener); + } + + public void notifyListeners(UserAdminEvent event) { + for (UserAdminListener listener : listeners) + listener.roleChanged(event); + } + + public Map getKnownBaseDns(boolean onlyWritable) { + Map dns = new HashMap(); + for (String uri : userAdminServiceReference.getPropertyKeys()) { + if (!uri.startsWith("/")) + continue; + Dictionary props = UserAdminConf.uriAsProperties(uri); + String readOnly = UserAdminConf.readOnly.getValue(props); + String baseDn = UserAdminConf.baseDn.getValue(props); + + if (onlyWritable && "true".equals(readOnly)) + continue; + if (baseDn.equalsIgnoreCase(AuthConstants.ROLES_BASEDN)) + continue; + dns.put(baseDn, uri); + } + return dns; + } + + public UserAdmin getUserAdmin() { + return userAdmin; + } + + public UserTransaction getUserTransaction() { + return userTransaction; + } + + /* DEPENDENCY INJECTION */ + public void setUserAdmin(UserAdmin userAdmin) { + this.userAdmin = userAdmin; + } + + public void setUserTransaction(UserTransaction userTransaction) { + this.userTransaction = userTransaction; + } + + public void setUserAdminServiceReference( + ServiceReference userAdminServiceReference) { + this.userAdminServiceReference = userAdminServiceReference; + } +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminUtils.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminUtils.java new file mode 100644 index 000000000..0fc4fc11f --- /dev/null +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminUtils.java @@ -0,0 +1,242 @@ +package org.argeo.security.ui.admin.internal; + +import java.security.AccessController; +import java.util.List; +import java.util.Set; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +import org.argeo.ArgeoException; +import org.argeo.cms.CmsView; +import org.argeo.cms.auth.AuthConstants; +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.util.CmsUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.jcr.JcrUtils; +import org.argeo.osgi.useradmin.LdifName; +import org.osgi.service.useradmin.Group; +import org.osgi.service.useradmin.Role; +import org.osgi.service.useradmin.User; +import org.osgi.service.useradmin.UserAdmin; + +/** Centralise common patterns to manage roles with a user admin */ +public class UserAdminUtils { + + /** Retrieves a {@link Role} given a LDAP name */ + public final static Role getRole(UserAdmin userAdmin, LdapName dn) { + Role role = userAdmin.getRole(dn.toString()); + return role; + } + + /** Retrieves the unique local username given a {@link User}. */ + public final static String getUsername(User user) { + String username = null; + if (user instanceof Group) + username = getProperty(user, LdifName.cn.name()); + else + username = getProperty(user, LdifName.uid.name()); + return username; + } + + /** + * Easily retrieves one of the {@link Role}'s property or an empty String if + * the requested property is not defined + */ + public final static String getProperty(Role role, String key) { + Object obj = role.getProperties().get(key); + if (obj != null) + return (String) obj; + else + return ""; + } + + // CENTRALIZE SOME METHODS UNTIL API IS STABLE + /** Simply checks if current user is registered */ + public static boolean isRegistered() { + return !CurrentUser.isAnonymous(); + } + + /** Simply checks if current user as a home */ + public static boolean hasHome() { + return isRegistered(); + } + + // SELF HELPERS + /** Simply retrieves the current logged-in user display name. */ + public static User getCurrentUser(UserAdmin userAdmin) { + return (User) getRole(userAdmin, getCurrentUserLdapName()); + } + + /** Simply retrieves the current logged-in user display name. */ + public static String getCurrentUserDisplayName(UserAdmin userAdmin) { + String username = getCurrentUsername(); + return getUserDisplayName(userAdmin, username); + } + + /** Simply retrieves the current logged-in user display name. */ + public static String getCurrentUserMail(UserAdmin userAdmin) { + String username = getCurrentUsername(); + return getUserMail(userAdmin, username); + } + + /** Returns the local name of the current connected user */ + public final static String getUsername(UserAdmin userAdmin) { + LdapName dn = getCurrentUserLdapName(); + return getUsername((User) getRole(userAdmin, dn)); + } + + /** Returns true if the current user is in the specified role */ + public static boolean isUserInRole(String role) { + Set roles = CurrentUser.roles(); + return roles.contains(role); + } + + /** Simply checks if current user is the same as the passed one */ + public static boolean isCurrentUser(User user) { + String userName = getProperty(user, LdifName.dn.name()); + try { + LdapName selfUserName = getCurrentUserLdapName(); + LdapName userLdapName = new LdapName(userName); + if (userLdapName.equals(selfUserName)) + return true; + else + return false; + } catch (InvalidNameException e) { + throw new ArgeoException("User " + user + " has an unvalid dn: " + + userName, e); + } + } + + public final static LdapName getCurrentUserLdapName() { + String name = getCurrentUsername(); + return getLdapName(name); + } + + /** Simply retrieves username for current user, generally a LDAP dn */ + public static String getCurrentUsername() { + Subject subject = currentSubject(); + String name = subject.getPrincipals(X500Principal.class).iterator() + .next().toString(); + return name; + } + + /** + * Fork of the {@link CurrentUser#currentSubject} method that is private. + * TODO Enhance and factorize + */ + private static Subject currentSubject() { + CmsView cmsView = CmsUtils.getCmsView(); + if (cmsView != null) + return cmsView.getSubject(); + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject != null) + return subject; + throw new RuntimeException("Cannot find related subject"); + } + + // HOME MANAGEMENT + /** + * Simply retrieves the *relative* path to the current user home node from + * the base home node + */ + public static String getCurrentUserHomeRelPath() { + return getHomeRelPath(getCurrentUsername()); + } + + /** + * Simply retrieves the *relative* path to the home node of a user given its + * userName + */ + public static String getHomeRelPath(String userName) { + String id = getUserUid(userName); + String currHomePath = JcrUtils.firstCharsToPath(id, 2) + "/" + id; + return currHomePath; + } + + // HELPERS TO RETRIEVE REMARKABLE PROPERTIES + /** Simply retrieves the user uid from his dn with no useradmin */ + public static String getUserUid(String dn) { + LdapName ldapName = getLdapName(dn); + Rdn last = ldapName.getRdn(ldapName.size() - 1); + if (last.getType().toLowerCase().equals(LdifName.uid.name()) + || last.getType().toLowerCase().equals(LdifName.cn.name())) + return (String) last.getValue(); + else + throw new ArgeoException("Cannot retrieve user uid, " + + "non valid dn: " + dn); + } + + /** + * Returns the local username if no user with this dn is found or if the + * found user has no defined display name + */ + public static String getUserDisplayName(UserAdmin userAdmin, String dn) { + Role user = getRole(userAdmin, getLdapName(dn)); + if (user == null) + return getUserUid(dn); + String displayName = getProperty(user, LdifName.displayName.name()); + if (EclipseUiUtils.isEmpty(displayName)) + displayName = getProperty(user, LdifName.cn.name()); + if (EclipseUiUtils.isEmpty(displayName)) + return getUserUid(dn); + else + return displayName; + } + + /** + * Returns null if no user with this dn is found or if the found user has no + * defined mail + */ + public static String getUserMail(UserAdmin userAdmin, String dn) { + Role user = getRole(userAdmin, getLdapName(dn)); + if (user == null) + return null; + else + return getProperty(user, LdifName.mail.name()); + } + + // VARIOUS UI HELPERS + public final static String buildDefaultCn(String firstName, String lastName) { + return (firstName.trim() + " " + lastName.trim() + " ").trim(); + } + + /** Simply retrieves a display name of the relevant domain */ + public final static String getDomainName(User user) { + String dn = user.getName(); + if (dn.endsWith(AuthConstants.ROLES_BASEDN)) + return "System roles"; + try { + LdapName name = new LdapName(dn); + List rdns = name.getRdns(); + String dname = null; + int i = 0; + loop: while (i < rdns.size()) { + Rdn currrRdn = rdns.get(i); + if (!LdifName.dc.name().equals(currrRdn.getType())) + break loop; + else { + String currVal = (String) currrRdn.getValue(); + dname = dname == null ? currVal : currVal + "." + dname; + } + i++; + } + return dname; + } catch (InvalidNameException e) { + throw new ArgeoException("Unable to get domain name for " + dn, e); + } + } + + // Local Helpers + /** Simply retrieves a LDAP name from a dn with no exception */ + public static LdapName getLdapName(String dn) { + try { + return new LdapName(dn); + } catch (InvalidNameException e) { + throw new ArgeoException("Cannot parse LDAP name " + dn, e); + } + } +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminWrapper.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminWrapper.java index 43ce58da9..ff4018a2c 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminWrapper.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminWrapper.java @@ -12,7 +12,7 @@ import org.osgi.service.useradmin.UserAdminListener; /** Centralize interaction with the UserAdmin in this bundle */ public class UserAdminWrapper extends - org.argeo.cms.util.useradmin.UserAdminWrapper { + org.argeo.security.ui.admin.internal.AbstractUserAdminWrapper { // private Log log = LogFactory.getLog(UserAdminWrapper.class); // Registered listeners diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteGroups.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteGroups.java index 868aa0fc7..d21cc48b1 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteGroups.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteGroups.java @@ -19,8 +19,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.parts.UserEditorInput; import org.eclipse.core.commands.AbstractHandler; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteUsers.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteUsers.java index 87da43cdf..3e2644f6f 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteUsers.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/DeleteUsers.java @@ -19,8 +19,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.parts.UserEditorInput; import org.eclipse.core.commands.AbstractHandler; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/NewUser.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/NewUser.java index e408b1bee..77230390b 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/NewUser.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/NewUser.java @@ -24,13 +24,13 @@ import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import org.argeo.ArgeoException; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.argeo.jcr.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java index 4a441a1a2..952747988 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java @@ -19,13 +19,13 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; import org.argeo.jcr.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminImages; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.parts.UserEditor.GroupChangeListener; import org.argeo.security.ui.admin.internal.parts.UserEditor.MainInfoListener; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java index 6b193f444..620e1d378 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java @@ -22,7 +22,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; @@ -30,6 +29,7 @@ import org.argeo.jcr.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminPlugin; import org.argeo.security.ui.admin.internal.UiUserAdminListener; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.providers.CommonNameLP; import org.argeo.security.ui.admin.internal.providers.DomainNameLP; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java index d2dbadd08..6f581853c 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java @@ -12,13 +12,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; import org.argeo.jcr.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.internal.UiAdminUtils; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.providers.CommonNameLP; import org.argeo.security.ui.admin.internal.providers.DomainNameLP; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserEditor.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserEditor.java index 715d34310..796d2cdd4 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserEditor.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserEditor.java @@ -19,10 +19,10 @@ import java.util.ArrayList; import java.util.List; import org.argeo.ArgeoException; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminPlugin; import org.argeo.security.ui.admin.internal.UiUserAdminListener; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.swt.events.ModifyEvent; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java index 833ae32a7..06b430f74 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java @@ -21,13 +21,13 @@ import java.util.List; import org.argeo.ArgeoException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; import org.argeo.jcr.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminImages; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.parts.UserEditor.GroupChangeListener; import org.argeo.security.ui.admin.internal.parts.UserEditor.MainInfoListener; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UsersView.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UsersView.java index edafa2851..5bb50a40f 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UsersView.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UsersView.java @@ -20,7 +20,6 @@ import java.util.List; import org.argeo.ArgeoException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; @@ -28,6 +27,7 @@ import org.argeo.jcr.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminPlugin; import org.argeo.security.ui.admin.internal.UiUserAdminListener; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.providers.CommonNameLP; import org.argeo.security.ui.admin.internal.providers.DomainNameLP; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/CommonNameLP.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/CommonNameLP.java index d45c0b603..5b6fbdd3e 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/CommonNameLP.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/CommonNameLP.java @@ -1,7 +1,7 @@ package org.argeo.security.ui.admin.internal.providers; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.osgi.useradmin.LdifName; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.osgi.service.useradmin.User; /** Simply declare a label provider that returns the common name of a user */ diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/DomainNameLP.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/DomainNameLP.java index 795fd0af3..b1d84a155 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/DomainNameLP.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/DomainNameLP.java @@ -1,6 +1,6 @@ package org.argeo.security.ui.admin.internal.providers; -import org.argeo.cms.util.useradmin.UserAdminUtils; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.osgi.service.useradmin.User; /** The human friendly domain name for the corresponding user. */ diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/MailLP.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/MailLP.java index 0a6dcb604..d24cab67a 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/MailLP.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/MailLP.java @@ -1,7 +1,7 @@ package org.argeo.security.ui.admin.internal.providers; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.osgi.useradmin.LdifName; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.osgi.service.useradmin.User; /** Simply declare a label provider that returns the Primary Mail of a user */ diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserAdminAbstractLP.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserAdminAbstractLP.java index 39bac0a2a..5ca476a7d 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserAdminAbstractLP.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserAdminAbstractLP.java @@ -4,7 +4,7 @@ import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import org.argeo.ArgeoException; -import org.argeo.cms.util.useradmin.UserAdminUtils; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.swt.SWT; diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserFilter.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserFilter.java index 5f753d1c3..2a230dd6b 100644 --- a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserFilter.java +++ b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/providers/UserFilter.java @@ -3,8 +3,8 @@ package org.argeo.security.ui.admin.internal.providers; import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty; import org.argeo.cms.auth.AuthConstants; -import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.osgi.useradmin.LdifName; +import org.argeo.security.ui.admin.internal.UserAdminUtils; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.osgi.service.useradmin.User; -- 2.30.2