LDAP support for hierarchy unit. Code clean up.
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 22 Jun 2022 04:17:26 +0000 (06:17 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 22 Jun 2022 04:17:26 +0000 (06:17 +0200)
20 files changed:
org.argeo.util/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java
org.argeo.util/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java
org.argeo.util/src/org/argeo/osgi/useradmin/DigestUtils.java
org.argeo.util/src/org/argeo/osgi/useradmin/IpaUtils.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdapConnection.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdapUserAdmin.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifAuthorization.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifGroup.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifHierarchyUnit.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifUser.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
org.argeo.util/src/org/argeo/osgi/useradmin/OsUserDirectory.java
org.argeo.util/src/org/argeo/osgi/useradmin/TokenUtils.java
org.argeo.util/src/org/argeo/osgi/useradmin/UserAdminConf.java
org.argeo.util/src/org/argeo/osgi/useradmin/UserDirectoryException.java [deleted file]
org.argeo.util/src/org/argeo/osgi/useradmin/UserDirectoryWorkingCopy.java
org.argeo.util/src/org/argeo/osgi/useradmin/WcXaResource.java
org.argeo.util/src/org/argeo/util/naming/AuthPassword.java
org.argeo.util/src/org/argeo/util/naming/LdifParser.java
org.argeo.util/src/org/argeo/util/naming/LdifWriter.java

index e13f56289ce8b44b2f9629d2e297aadccbf03c03..dde39e0abd287fa0ddcb3f69cf6927574f1c26c0 100644 (file)
@@ -129,6 +129,10 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory {
                        disabled = false;
        }
 
+       /*
+        * ABSTRACT METHODS
+        */
+
        /** Returns the groups this user is a direct member of. */
        protected abstract List<LdapName> getDirectGroups(LdapName dn);
 
@@ -140,6 +144,14 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory {
 
        protected abstract AbstractUserDirectory scope(User user);
 
+       protected abstract HierarchyUnit doGetHierarchyUnit(LdapName dn);
+
+       protected abstract Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly);
+
+       /*
+        * INITIALIZATION
+        */
+
        public void init() {
 
        }
@@ -500,55 +512,25 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory {
        /*
         * HIERARCHY
         */
-//     @Override
-//     public int getHierarchyChildCount() {
-//             return 0;
-//     }
-//
-//     @Override
-//     public HierarchyUnit getHierarchyChild(int i) {
-//             throw new IllegalArgumentException("No child hierarchy unit available");
-//     }
-//
-//     @Override
-//     public HierarchyUnit getParent() {
-//             return null;
-//     }
-//
-//     @Override
-//     public int getHierarchyUnitType() {
-//             return 0;
-//     }
-//
-//     @Override
-//     public String getHierarchyUnitName() {
-//             String name = LdapNameUtils.getLastRdnValue(baseDn);
-//             // TODO check ou, o, etc.
-//             return name;
-//     }
-
        @Override
        public HierarchyUnit getHierarchyUnit(String path) {
-               throw new UnsupportedOperationException();
+               LdapName dn = pathToName(path);
+               return doGetHierarchyUnit(dn);
        }
 
        @Override
        public HierarchyUnit getHierarchyUnit(Role role) {
-               throw new UnsupportedOperationException();
+               LdapName dn = LdapNameUtils.toLdapName(role.getName());
+               LdapName huDn = LdapNameUtils.getParent(dn);
+               HierarchyUnit hierarchyUnit = doGetHierarchyUnit(huDn);
+               if (hierarchyUnit == null)
+                       throw new IllegalStateException("No hierarchy unit found for " + role);
+               return hierarchyUnit;
        }
 
-//     @Override
-//     public List<? extends Role> getHierarchyUnitRoles(String filter, boolean deep) {
-//             try {
-//                     return getRoles(getBaseDn(), filter, deep);
-//             } catch (InvalidSyntaxException e) {
-//                     throw new IllegalArgumentException("Cannot filter " + filter + " " + getBaseDn(), e);
-//             }
-//     }
-
        @Override
        public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
-               throw new UnsupportedOperationException();
+               return doGetDirectHierarchyUnits(baseDn, functionalOnly);
        }
 
        /*
@@ -562,7 +544,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory {
        protected DirectoryGroup newGroup(LdapName name, Attributes attrs) {
                if (LdapNameUtils.getParentRdn(name).equals(getSystemRoleBaseRdn()))
                        return new LdifGroup.LdifSystemPermissions(this, name, attrs);
-               
+
                if (hasObjectClass(attrs, LdapObjs.organization))
                        return new LdifGroup.LdifOrganization(this, name, attrs);
                else
index ca1fa338bab58e785dbda260e8431f908c1bd811..ac641de97cf6a128b5c2781f9c053cba8e98a7d7 100644 (file)
@@ -43,7 +43,7 @@ public class AggregatingUserAdmin implements UserAdmin {
                        else
                                this.tokensBaseDn = null;
                } catch (InvalidNameException e) {
-                       throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin.class, e);
+                       throw new IllegalStateException("Cannot initialize " + AggregatingUserAdmin.class, e);
                }
        }
 
@@ -170,7 +170,7 @@ public class AggregatingUserAdmin implements UserAdmin {
                } else {
                        LdapName baseDn = toLdapName(basePath);
                        if (businessRoles.containsKey(baseDn))
-                               throw new UserDirectoryException("There is already a user admin for " + baseDn);
+                               throw new IllegalStateException("There is already a user admin for " + baseDn);
                        businessRoles.put(baseDn, userDirectory);
                }
                userDirectory.init();
@@ -185,7 +185,7 @@ public class AggregatingUserAdmin implements UserAdmin {
                try {
                        return findUserAdmin(new LdapName(name));
                } catch (InvalidNameException e) {
-                       throw new UserDirectoryException("Badly formatted name " + name, e);
+                       throw new IllegalArgumentException("Badly formatted name " + name, e);
                }
        }
 
@@ -213,9 +213,9 @@ public class AggregatingUserAdmin implements UserAdmin {
                        }
                }
                if (res.size() == 0)
-                       throw new UserDirectoryException("Cannot find user admin for " + name);
+                       throw new IllegalStateException("Cannot find user admin for " + name);
                if (res.size() > 1)
-                       throw new UserDirectoryException("Multiple user admin found for " + name);
+                       throw new IllegalStateException("Multiple user admin found for " + name);
                return res.get(0);
        }
 
@@ -256,10 +256,10 @@ public class AggregatingUserAdmin implements UserAdmin {
 
        protected void removeUserDirectory(String basePath) {
                if (isSystemRolesBaseDn(basePath))
-                       throw new UserDirectoryException("System roles cannot be removed ");
+                       throw new IllegalArgumentException("System roles cannot be removed ");
                LdapName baseDn = toLdapName(basePath);
                if (!businessRoles.containsKey(baseDn))
-                       throw new UserDirectoryException("No user directory registered for " + baseDn);
+                       throw new IllegalStateException("No user directory registered for " + baseDn);
                AbstractUserDirectory userDirectory = businessRoles.remove(baseDn);
                destroy(userDirectory);
        }
index 511c2fede5e747e8e7e3adef942a09063793c579..55d24d994c7a3c681382def8e6efd93da1819682 100644 (file)
@@ -5,6 +5,8 @@ import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
 import java.security.spec.KeySpec;
 import java.util.Arrays;
 
@@ -22,8 +24,8 @@ class DigestUtils {
                        digest.update(bytes);
                        byte[] checksum = digest.digest();
                        return checksum;
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot SHA1 digest", e);
+               } catch (NoSuchAlgorithmException e) {
+                       throw new IllegalStateException("Cannot SHA1 digest", e);
                }
        }
 
@@ -56,8 +58,8 @@ class DigestUtils {
                        } else {
                                throw new UnsupportedOperationException("Unkown password scheme " + passwordScheme);
                        }
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot digest", e);
+               } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+                       throw new IllegalStateException("Cannot digest", e);
                }
        }
 
index 076f26949c49b0ca6f20dfc9cef8dc06093c9818..780215a9cc0871b543bdb9d5911e0da5026cdbc6 100644 (file)
@@ -82,8 +82,8 @@ public class IpaUtils {
                        String dnsZone = hostname.substring(hostname.indexOf('.') + 1);
                        kerberosDomain = dnsBrowser.getRecord("_kerberos." + dnsZone, "TXT");
                        return kerberosDomain;
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot determine Kerberos domain from DNS", e);
+               } catch (NamingException | IOException e) {
+                       throw new IllegalStateException("Cannot determine Kerberos domain from DNS", e);
                }
 
        }
@@ -98,7 +98,7 @@ public class IpaUtils {
                }
 
                if (kerberosRealm == null)
-                       throw new UserDirectoryException("No Kerberos domain available for " + uri);
+                       throw new IllegalStateException("No Kerberos domain available for " + uri);
                // TODO intergrate CA certificate in truststore
                // String schemeToUse = SCHEME_LDAPS;
                String schemeToUse = UserAdminConf.SCHEME_LDAP;
@@ -109,12 +109,12 @@ public class IpaUtils {
                                ldapHosts = dnsBrowser.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm.toLowerCase(),
                                                schemeToUse.equals(UserAdminConf.SCHEME_LDAP) ? true : false);
                                if (ldapHosts == null || ldapHosts.size() == 0) {
-                                       throw new UserDirectoryException("Cannot configure LDAP for IPA " + uri);
+                                       throw new IllegalStateException("Cannot configure LDAP for IPA " + uri);
                                } else {
                                        ldapHostsStr = ldapHosts.get(0);
                                }
                        } catch (NamingException | IOException e) {
-                               throw new UserDirectoryException("cannot convert IPA uri " + uri, e);
+                               throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
                        }
                } else {
                        ldapHosts = new ArrayList<>();
@@ -128,7 +128,7 @@ public class IpaUtils {
                                uriStr.append(convertedUri).append(' ');
                        }
                } catch (URISyntaxException e) {
-                       throw new UserDirectoryException("cannot convert IPA uri " + uri, e);
+                       throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
                }
 
                Hashtable<String, Object> res = new Hashtable<>();
index ed69eb16b09443409757a9c6584a4909a5dcfc66..1eaf1e7d65470e8377e072727b0fb8069f375ebd 100644 (file)
@@ -49,8 +49,8 @@ class LdapConnection {
                                        initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
                                }
                        }
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot connect to LDAP", e);
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot connect to LDAP", e);
                }
 
        }
@@ -105,17 +105,17 @@ class LdapConnection {
                // delete
                for (LdapName dn : wc.getDeletedUsers().keySet()) {
                        if (!entryExists(dn))
-                               throw new UserDirectoryException("User to delete no found " + dn);
+                               throw new IllegalStateException("User to delete no found " + dn);
                }
                // add
                for (LdapName dn : wc.getNewUsers().keySet()) {
                        if (entryExists(dn))
-                               throw new UserDirectoryException("User to create found " + dn);
+                               throw new IllegalStateException("User to create found " + dn);
                }
                // modify
                for (LdapName dn : wc.getModifiedUsers().keySet()) {
                        if (!wc.getNewUsers().containsKey(dn) && !entryExists(dn))
-                               throw new UserDirectoryException("User to modify not found " + dn);
+                               throw new IllegalStateException("User to modify not found " + dn);
                }
 
        }
index 138eb39e9a49dc03ec7c02b7fbda001703c6e7a7..52fa38b110a68c1616eb046be0a93dcf69e51a19 100644 (file)
@@ -19,6 +19,7 @@ import javax.naming.directory.SearchControls;
 import javax.naming.directory.SearchResult;
 import javax.naming.ldap.LdapName;
 
+import org.argeo.util.naming.LdapObjs;
 import org.osgi.framework.Filter;
 import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
@@ -81,11 +82,11 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                        int roleType = roleType(name);
                        DirectoryUser res;
                        if (roleType == Role.GROUP)
-                               res = newGroup( name, attrs);
+                               res = newGroup(name, attrs);
                        else if (roleType == Role.USER)
-                               res = newUser( name, attrs);
+                               res = newUser(name, attrs);
                        else
-                               throw new UserDirectoryException("Unsupported LDAP type for " + name);
+                               throw new IllegalArgumentException("Unsupported LDAP type for " + name);
                        return res;
                } catch (NameNotFoundException e) {
                        throw e;
@@ -116,10 +117,10 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                                DirectoryUser role;
                                if (objectClassAttr.contains(getGroupObjectClass())
                                                || objectClassAttr.contains(getGroupObjectClass().toLowerCase()))
-                                       role = newGroup( dn, attrs);
+                                       role = newGroup(dn, attrs);
                                else if (objectClassAttr.contains(getUserObjectClass())
                                                || objectClassAttr.contains(getUserObjectClass().toLowerCase()))
-                                       role = newUser( dn, attrs);
+                                       role = newUser(dn, attrs);
                                else {
 //                                     log.warn("Unsupported LDAP type for " + searchResult.getName());
                                        continue results;
@@ -131,9 +132,8 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                        // ignore (typically an unsupported anonymous bind)
                        // TODO better logging
                        return res;
-               } catch (Exception e) {
-                       e.printStackTrace();
-                       throw new UserDirectoryException("Cannot get roles for filter " + f, e);
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot get roles for filter " + f, e);
                }
        }
 
@@ -159,8 +159,8 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                                directGroups.add(toDn(searchBase, searchResult));
                        }
                        return directGroups;
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot populate direct members of " + dn, e);
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot populate direct members of " + dn, e);
                }
        }
 
@@ -169,7 +169,7 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                try {
                        ldapConnection.prepareChanges(wc);
                } catch (NamingException e) {
-                       throw new UserDirectoryException("Cannot prepare LDAP", e);
+                       throw new IllegalStateException("Cannot prepare LDAP", e);
                }
        }
 
@@ -178,7 +178,7 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                try {
                        ldapConnection.commitChanges(wc);
                } catch (NamingException e) {
-                       throw new UserDirectoryException("Cannot commit LDAP", e);
+                       throw new IllegalStateException("Cannot commit LDAP", e);
                }
        }
 
@@ -187,11 +187,44 @@ public class LdapUserAdmin extends AbstractUserDirectory {
                // prepare not impacting
        }
 
-//     @Override
-//     public HierarchyUnit getHierarchyUnit(String path) {
-//             LdapName dn = LdapNameUtils.toLdapName(path);
-//             Attributes attrs = ldapConnection.getAttributes(dn);
-//             
-//     }
+       /*
+        * HIERARCHY
+        */
+
+       @Override
+       protected Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+               List<HierarchyUnit> res = new ArrayList<>();
+               try {
+                       String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
+                                       + "=" + LdapObjs.organization.name() + "))";
+
+                       SearchControls searchControls = new SearchControls();
+                       searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+
+                       NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
+
+                       while (results.hasMoreElements()) {
+                               SearchResult searchResult = (SearchResult) results.nextElement();
+                               LdapName dn = toDn(searchBase, searchResult);
+                               Attributes attrs = searchResult.getAttributes();
+                               LdifHierarchyUnit hierarchyUnit = new LdifHierarchyUnit(this, dn, attrs);
+                               if (hierarchyUnit.isFunctional())
+                                       res.add(hierarchyUnit);
+                       }
+                       return res;
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot get direct hierarchy units ", e);
+               }
+       }
+
+       @Override
+       protected HierarchyUnit doGetHierarchyUnit(LdapName dn) {
+               try {
+                       Attributes attrs = ldapConnection.getAttributes(dn);
+                       return new LdifHierarchyUnit(this, dn, attrs);
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot get hierarchy unit " + dn, e);
+               }
+       }
 
 }
index 15afe08b1fbfbced1f9c2f6e58d07f0fa0f1ca8a..80a9eea30e32ff19eeaae7aa2c94f1895f81da52 100644 (file)
@@ -79,7 +79,7 @@ class LdifAuthorization implements Authorization {
                if (displayName == null)
                        displayName = user.getName();
                if (displayName == null)
-                       throw new UserDirectoryException("Cannot set display name for " + user);
+                       throw new IllegalStateException("Cannot set display name for " + user);
                return displayName.toString();
        }
 }
index b7167ea134684bacf63b25618446e8b198db27a5..80bff59472a7799ca5fdd1ada85ebd91215ac2cb 100644 (file)
@@ -5,6 +5,7 @@ import java.util.List;
 
 import javax.naming.InvalidNameException;
 import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
 import javax.naming.ldap.LdapName;
@@ -73,7 +74,7 @@ abstract class LdifGroup extends LdifUser implements DirectoryGroup {
                for (LdapName ldapName : getMemberNames()) {
                        Role role = findRole(ldapName);
                        if (role == null) {
-                               throw new UserDirectoryException("Role " + ldapName + " cannot be added.");
+                               throw new IllegalStateException("Role " + ldapName + " not found.");
                        }
                        directMembers.add(role);
                }
@@ -107,8 +108,8 @@ abstract class LdifGroup extends LdifUser implements DirectoryGroup {
                                roles.add(dn);
                        }
                        return roles;
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot get members", e);
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot get members", e);
                }
        }
 
index d4259c87d5714a4d829fecd03c390b0af843ca9f..a847e49ae7f3d66afd13644889dc859961abc248 100644 (file)
@@ -1,7 +1,5 @@
 package org.argeo.osgi.useradmin;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -20,8 +18,8 @@ class LdifHierarchyUnit implements HierarchyUnit {
        private final boolean functional;
        private final Attributes attributes;
 
-       HierarchyUnit parent;
-       List<HierarchyUnit> children = new ArrayList<>();
+//     HierarchyUnit parent;
+//     List<HierarchyUnit> children = new ArrayList<>();
 
        LdifHierarchyUnit(AbstractUserDirectory directory, LdapName dn, Attributes attributes) {
                Objects.requireNonNull(directory);
@@ -38,20 +36,21 @@ class LdifHierarchyUnit implements HierarchyUnit {
 
        @Override
        public HierarchyUnit getParent() {
-               return parent;
+               return directory.doGetHierarchyUnit(LdapNameUtils.getParent(dn));
        }
 
        @Override
        public Iterable<HierarchyUnit> getDirectHierachyUnits(boolean functionalOnly) {
-               List<HierarchyUnit> res = new ArrayList<>();
-               if (functionalOnly)
-                       for (HierarchyUnit hu : children) {
-                               if (hu.isFunctional())
-                                       res.add(hu);
-                       }
-               else
-                       res.addAll(children);
-               return Collections.unmodifiableList(res);
+//             List<HierarchyUnit> res = new ArrayList<>();
+//             if (functionalOnly)
+//                     for (HierarchyUnit hu : children) {
+//                             if (hu.isFunctional())
+//                                     res.add(hu);
+//                     }
+//             else
+//                     res.addAll(children);
+//             return Collections.unmodifiableList(res);
+               return directory.doGetDirectHierarchyUnits(dn, functionalOnly);
        }
 
        @Override
index c4c02a748f8e0eb4130eb9da2cc9bbce4ab70496..db83b81e47b99a9e247a1e141c6bc22b219fe964 100644 (file)
@@ -195,9 +195,9 @@ abstract class LdifUser implements DirectoryUser {
 
        protected synchronized void startEditing() {
                if (frozen)
-                       throw new UserDirectoryException("Cannot edit frozen view");
+                       throw new IllegalStateException("Cannot edit frozen view");
                if (getUserAdmin().isReadOnly())
-                       throw new UserDirectoryException("User directory is read-only");
+                       throw new IllegalStateException("User directory is read-only");
                assert getModifiedAttributes() == null;
                getWc().startEditing(this);
                // modifiedAttributes = (Attributes) publishedAttributes.clone();
@@ -254,7 +254,7 @@ abstract class LdifUser implements DirectoryUser {
                                                effectiveKeys.add(id);
                                }
                        } catch (NamingException e) {
-                               throw new UserDirectoryException("Cannot initialise attribute dictionary", e);
+                               throw new IllegalStateException("Cannot initialise attribute dictionary", e);
                        }
                        if (!credentials)
                                effectiveKeys.add(LdapAttrs.objectClasses.name());
@@ -383,7 +383,7 @@ abstract class LdifUser implements DirectoryUser {
                                else
                                        return null;
                        } catch (NamingException e) {
-                               throw new UserDirectoryException("Cannot get value for attribute " + key, e);
+                               throw new IllegalStateException("Cannot get value for attribute " + key, e);
                        }
                }
 
@@ -405,7 +405,7 @@ abstract class LdifUser implements DirectoryUser {
                                else
                                        return null;
                        } catch (NamingException e) {
-                               throw new UserDirectoryException("Cannot remove attribute " + key, e);
+                               throw new IllegalStateException("Cannot remove attribute " + key, e);
                        }
                }
        }
index 0a925e4eb41b3612f531f3ace8534a198065d72d..ef487594c409a059f622cf2080268a3821ed4788 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Dictionary;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.NavigableMap;
 import java.util.Objects;
 import java.util.Set;
 import java.util.SortedMap;
@@ -23,6 +24,7 @@ import java.util.TreeMap;
 
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
 import javax.naming.directory.Attributes;
 import javax.naming.ldap.LdapName;
 
@@ -35,11 +37,11 @@ import org.osgi.service.useradmin.User;
 
 /** A user admin based on a LDIF files. */
 public class LdifUserAdmin extends AbstractUserDirectory {
-       private SortedMap<LdapName, DirectoryUser> users = new TreeMap<>();
-       private SortedMap<LdapName, DirectoryGroup> groups = new TreeMap<>();
+       private NavigableMap<LdapName, DirectoryUser> users = new TreeMap<>();
+       private NavigableMap<LdapName, DirectoryGroup> groups = new TreeMap<>();
 
-       private SortedMap<LdapName, LdifHierarchyUnit> hierarchy = new TreeMap<>();
-       private List<HierarchyUnit> rootHierarchyUnits = new ArrayList<>();
+       private NavigableMap<LdapName, LdifHierarchyUnit> hierarchy = new TreeMap<>();
+//     private List<HierarchyUnit> rootHierarchyUnits = new ArrayList<>();
 
        public LdifUserAdmin(String uri, String baseDn) {
                this(fromUri(uri, baseDn), false);
@@ -69,15 +71,15 @@ public class LdifUserAdmin extends AbstractUserDirectory {
                        char[] password = DigestUtils.bytesToChars(pwd);
                        User directoryUser = (User) getRole(username);
                        if (!directoryUser.hasCredential(null, password))
-                               throw new UserDirectoryException("Invalid credentials");
+                               throw new IllegalStateException("Invalid credentials");
                } else {
-                       throw new UserDirectoryException("Password is required");
+                       throw new IllegalStateException("Password is required");
                }
                Dictionary<String, Object> properties = cloneProperties();
                properties.put(UserAdminConf.readOnly.name(), "true");
                LdifUserAdmin scopedUserAdmin = new LdifUserAdmin(properties, true);
-               scopedUserAdmin.groups = Collections.unmodifiableSortedMap(groups);
-               scopedUserAdmin.users = Collections.unmodifiableSortedMap(users);
+               scopedUserAdmin.groups = Collections.unmodifiableNavigableMap(groups);
+               scopedUserAdmin.users = Collections.unmodifiableNavigableMap(users);
                return scopedUserAdmin;
        }
 
@@ -98,20 +100,20 @@ public class LdifUserAdmin extends AbstractUserDirectory {
                                        return;
                        }
                        load(u.toURL().openStream());
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot open URL " + getUri(), e);
+               } catch (IOException | URISyntaxException e) {
+                       throw new IllegalStateException("Cannot open URL " + getUri(), e);
                }
        }
 
        public void save() {
                if (getUri() == null)
-                       throw new UserDirectoryException("Cannot save LDIF user admin: no URI is set");
+                       throw new IllegalStateException("Cannot save LDIF user admin: no URI is set");
                if (isReadOnly())
-                       throw new UserDirectoryException("Cannot save LDIF user admin: " + getUri() + " is read-only");
+                       throw new IllegalStateException("Cannot save LDIF user admin: " + getUri() + " is read-only");
                try (FileOutputStream out = new FileOutputStream(new File(new URI(getUri())))) {
                        save(out);
                } catch (IOException | URISyntaxException e) {
-                       throw new UserDirectoryException("Cannot save user admin to " + getUri(), e);
+                       throw new IllegalStateException("Cannot save user admin to " + getUri(), e);
                }
        }
 
@@ -145,7 +147,7 @@ public class LdifUserAdmin extends AbstractUserDirectory {
                                while (ids.hasMoreElements()) {
                                        String id = ids.nextElement().toLowerCase();
                                        if (lowerCase.contains(id))
-                                               throw new UserDirectoryException(key + " has duplicate id " + id);
+                                               throw new IllegalStateException(key + " has duplicate id " + id);
                                        lowerCase.add(id);
                                }
 
@@ -177,26 +179,26 @@ public class LdifUserAdmin extends AbstractUserDirectory {
                        }
 
                        // link hierarchy
-                       hierachyUnits: for (LdapName dn : hierarchy.keySet()) {
-                               LdifHierarchyUnit unit = hierarchy.get(dn);
-                               LdapName parentDn = (LdapName) dn.getPrefix(dn.size() - 1);
-                               LdifHierarchyUnit parent = hierarchy.get(parentDn);
-                               if (parent == null) {
-                                       rootHierarchyUnits.add(unit);
-                                       unit.parent = null;
-                                       continue hierachyUnits;
-                               }
-                               parent.children.add(unit);
-                               unit.parent = parent;
-                       }
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot load user admin service from LDIF", e);
+//                     hierachyUnits: for (LdapName dn : hierarchy.keySet()) {
+//                             LdifHierarchyUnit unit = hierarchy.get(dn);
+//                             LdapName parentDn = (LdapName) dn.getPrefix(dn.size() - 1);
+//                             LdifHierarchyUnit parent = hierarchy.get(parentDn);
+//                             if (parent == null) {
+//                                     rootHierarchyUnits.add(unit);
+//                                     unit.parent = null;
+//                                     continue hierachyUnits;
+//                             }
+//                             parent.children.add(unit);
+//                             unit.parent = parent;
+//                     }
+               } catch (NamingException | IOException e) {
+                       throw new IllegalStateException("Cannot load user admin service from LDIF", e);
                }
        }
 
        public void destroy() {
                if (users == null || groups == null)
-                       throw new UserDirectoryException("User directory " + getBaseDn() + " is already destroyed");
+                       throw new IllegalStateException("User directory " + getBaseDn() + " is already destroyed");
                users = null;
                groups = null;
        }
@@ -270,19 +272,19 @@ public class LdifUserAdmin extends AbstractUserDirectory {
                        else if (groups.containsKey(dn))
                                groups.remove(dn);
                        else
-                               throw new UserDirectoryException("User to delete not found " + dn);
+                               throw new IllegalStateException("User to delete not found " + dn);
                }
                // add
                for (LdapName dn : wc.getNewUsers().keySet()) {
                        DirectoryUser user = wc.getNewUsers().get(dn);
                        if (users.containsKey(dn) || groups.containsKey(dn))
-                               throw new UserDirectoryException("User to create found " + dn);
+                               throw new IllegalStateException("User to create found " + dn);
                        else if (Role.USER == user.getType())
                                users.put(dn, user);
                        else if (Role.GROUP == user.getType())
                                groups.put(dn, (DirectoryGroup) user);
                        else
-                               throw new UserDirectoryException("Unsupported role type " + user.getType() + " for new user " + dn);
+                               throw new IllegalStateException("Unsupported role type " + user.getType() + " for new user " + dn);
                }
                // modify
                for (LdapName dn : wc.getModifiedUsers().keySet()) {
@@ -293,7 +295,7 @@ public class LdifUserAdmin extends AbstractUserDirectory {
                        else if (groups.containsKey(dn))
                                user = groups.get(dn);
                        else
-                               throw new UserDirectoryException("User to modify no found " + dn);
+                               throw new IllegalStateException("User to modify no found " + dn);
                        user.publishAttributes(modifiedAttrs);
                }
        }
@@ -321,36 +323,43 @@ public class LdifUserAdmin extends AbstractUserDirectory {
 //     public HierarchyUnit getHierarchyChild(int i) {
 //             return rootHierarchyUnits.get(i);
 //     }
-
        @Override
-       public HierarchyUnit getHierarchyUnit(String path) {
-               LdapName dn = pathToName(path);
+       protected HierarchyUnit doGetHierarchyUnit(LdapName dn) {
                return hierarchy.get(dn);
        }
 
        @Override
-       public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
-               if (functionalOnly) {
-                       List<HierarchyUnit> res = new ArrayList<>();
-                       for (HierarchyUnit hu : rootHierarchyUnits) {
-                               if (hu.isFunctional())
-                                       res.add(hu);
+       protected Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+               List<HierarchyUnit> res = new ArrayList<>();
+               for (LdapName n : hierarchy.keySet()) {
+                       if (n.size() == searchBase.size() + 1) {
+                               if (n.startsWith(searchBase)) {
+                                       HierarchyUnit hu = hierarchy.get(n);
+                                       if (functionalOnly) {
+                                               if (hu.isFunctional())
+                                                       res.add(hu);
+                                       } else {
+                                               res.add(hu);
+                                       }
+                               }
                        }
-                       return res;
-
-               } else {
-                       return rootHierarchyUnits;
                }
+               return res;
        }
 
-       @Override
-       public HierarchyUnit getHierarchyUnit(Role role) {
-               LdapName dn = LdapNameUtils.toLdapName(role.getName());
-               LdapName huDn = LdapNameUtils.getParent(dn);
-               HierarchyUnit hierarchyUnit = hierarchy.get(huDn);
-               if (hierarchyUnit == null)
-                       throw new IllegalStateException("No hierarchy unit found for " + role);
-               return hierarchyUnit;
-       }
+//     @Override
+//     public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
+//             if (functionalOnly) {
+//                     List<HierarchyUnit> res = new ArrayList<>();
+//                     for (HierarchyUnit hu : rootHierarchyUnits) {
+//                             if (hu.isFunctional())
+//                                     res.add(hu);
+//                     }
+//                     return res;
+//
+//             } else {
+//                     return rootHierarchyUnits;
+//             }
+//     }
 
 }
index b0a52626aa4cda31602e18b37ae8208804600d2e..3ded7a7a6a6ce28cfd277663b6efbb9e238a4810 100644 (file)
@@ -15,6 +15,7 @@ import org.argeo.util.naming.LdapAttrs;
 import org.osgi.framework.Filter;
 import org.osgi.service.useradmin.User;
 
+/** Pseudo user directory to be used when logging in as OS user. */
 public class OsUserDirectory extends AbstractUserDirectory {
        private final String osUsername = System.getProperty("user.name");
        private final LdapName osUserDn;
@@ -23,12 +24,13 @@ public class OsUserDirectory extends AbstractUserDirectory {
        public OsUserDirectory(URI uriArg, Dictionary<String, ?> props) {
                super(uriArg, props, false);
                try {
-                       osUserDn = new LdapName(LdapAttrs.uid.name() + "=" + osUsername + "," + getUserBaseRdn() + "," + getBaseDn());
+                       osUserDn = new LdapName(
+                                       LdapAttrs.uid.name() + "=" + osUsername + "," + getUserBaseRdn() + "," + getBaseDn());
                        Attributes attributes = new BasicAttributes();
                        attributes.put(LdapAttrs.uid.name(), osUsername);
                        osUser = newUser(osUserDn, attributes);
                } catch (NamingException e) {
-                       throw new UserDirectoryException("Cannot create system user", e);
+                       throw new IllegalStateException("Cannot create system user", e);
                }
        }
 
@@ -63,4 +65,14 @@ public class OsUserDirectory extends AbstractUserDirectory {
                throw new UnsupportedOperationException();
        }
 
+       @Override
+       protected HierarchyUnit doGetHierarchyUnit(LdapName dn) {
+               return null;
+       }
+
+       @Override
+       protected Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+               return new ArrayList<>();
+       }
+
 }
index 4b00e6c6ab6964a863c1b47aafd25c8bea0dd9a3..178b4ae82bf1b4b2e69ec8d25365897e72c3574d 100644 (file)
@@ -29,7 +29,7 @@ public class TokenUtils {
                                        String token = ldapName.getRdn(ldapName.size()).getValue().toString();
                                        res.add(token);
                                } catch (InvalidNameException e) {
-                                       throw new UserDirectoryException("Invalid principal " + principal, e);
+                                       throw new IllegalArgumentException("Invalid principal " + principal, e);
                                }
                        }
                }
index 93ca94ca6deddead625a43acb0cfcbeee3813ba7..7fd9e1895ffc4f9e9fa98734f4b7db356b6af513 100644 (file)
@@ -10,6 +10,7 @@ import java.util.List;
 import java.util.Map;
 
 import javax.naming.Context;
+import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
 
 import org.argeo.util.naming.NamingUtils;
@@ -141,7 +142,7 @@ public enum UserAdminConf {
                        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 IllegalArgumentException("Cannot create URI from properties", e);
                }
        }
 
@@ -181,7 +182,7 @@ public enum UserAdminConf {
                                } else if (scheme.equals(SCHEME_IPA)) {
                                } else if (scheme.equals(SCHEME_OS)) {
                                } else
-                                       throw new UserDirectoryException("Unsupported scheme " + scheme);
+                                       throw new IllegalArgumentException("Unsupported scheme " + scheme);
                        Map<String, List<String>> query = NamingUtils.queryToMap(u);
                        for (String key : query.keySet()) {
                                UserAdminConf ldapProp = UserAdminConf.valueOf(key);
@@ -189,7 +190,7 @@ public enum UserAdminConf {
                                if (values.size() == 1) {
                                        res.put(ldapProp.name(), values.get(0));
                                } else {
-                                       throw new UserDirectoryException("Only single values are supported");
+                                       throw new IllegalArgumentException("Only single values are supported");
                                }
                        }
                        res.put(baseDn.name(), bDn);
@@ -209,8 +210,8 @@ public enum UserAdminConf {
                                }
                        }
                        return res;
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot convert " + uri + " to properties", e);
+               } catch (URISyntaxException | InvalidNameException e) {
+                       throw new IllegalArgumentException("Cannot convert " + uri + " to properties", e);
                }
        }
 
@@ -239,7 +240,7 @@ public enum UserAdminConf {
        public static String baseDnHash(Dictionary<String, Object> properties) {
                String bDn = (String) properties.get(baseDn.name());
                if (bDn == null)
-                       throw new UserDirectoryException("No baseDn in " + properties);
+                       throw new IllegalStateException("No baseDn in " + properties);
                return DigestUtils.sha1str(bDn);
        }
 }
diff --git a/org.argeo.util/src/org/argeo/osgi/useradmin/UserDirectoryException.java b/org.argeo.util/src/org/argeo/osgi/useradmin/UserDirectoryException.java
deleted file mode 100644 (file)
index 0140a19..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.argeo.osgi.useradmin;
-
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Exceptions related to Argeo's implementation of OSGi {@link UserAdmin}
- * service.
- */
-@Deprecated
-public class UserDirectoryException extends RuntimeException {
-       private static final long serialVersionUID = 1419352360062048603L;
-
-       public UserDirectoryException(String message) {
-               super(message);
-       }
-
-       public UserDirectoryException(String message, Throwable e) {
-               super(message, e);
-       }
-}
index 0e25bdfa12c441459e4f6bbee26353aa588ec5b2..35a34bdbe4425d61e9cdef09e90007613bc6354b 100644 (file)
@@ -27,8 +27,7 @@ class UserDirectoryWorkingCopy {
        }
 
        public boolean noModifications() {
-               return newUsers.size() == 0 && modifiedUsers.size() == 0
-                               && deletedUsers.size() == 0;
+               return newUsers.size() == 0 && modifiedUsers.size() == 0 && deletedUsers.size() == 0;
        }
 
        public Attributes getAttributes(LdapName dn) {
@@ -40,7 +39,7 @@ class UserDirectoryWorkingCopy {
        public void startEditing(DirectoryUser user) {
                LdapName dn = user.getDn();
                if (modifiedUsers.containsKey(dn))
-                       throw new UserDirectoryException("Already editing " + dn);
+                       throw new IllegalStateException("Already editing " + dn);
                modifiedUsers.put(dn, (Attributes) user.getAttributes().clone());
        }
 
index 1630b6bd36befa841d3968b84d260750dda8e017..af0f351c77e6b9b9105ed8f0ef3e9a0f009837d2 100644 (file)
@@ -22,10 +22,10 @@ class WcXaResource implements XAResource {
        @Override
        public synchronized void start(Xid xid, int flags) throws XAException {
                if (editingXid != null)
-                       throw new UserDirectoryException("Already editing " + editingXid);
+                       throw new IllegalStateException("Already editing " + editingXid);
                UserDirectoryWorkingCopy wc = workingCopies.put(xid, new UserDirectoryWorkingCopy());
                if (wc != null)
-                       throw new UserDirectoryException("There is already a working copy for " + xid);
+                       throw new IllegalStateException("There is already a working copy for " + xid);
                this.editingXid = xid;
        }
 
@@ -43,7 +43,7 @@ class WcXaResource implements XAResource {
                        return null;
                UserDirectoryWorkingCopy wc = workingCopies.get(editingXid);
                if (wc == null)
-                       throw new UserDirectoryException("No working copy found for " + editingXid);
+                       throw new IllegalStateException("No working copy found for " + editingXid);
                return wc;
        }
 
index 973b90f0ff0bf63873cfce7c4b33202454e824d9..d8792729f3a4248455a00b1b736f7cf5d88d5684 100644 (file)
@@ -14,8 +14,6 @@ import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 
-import org.argeo.osgi.useradmin.UserDirectoryException;
-
 /** LDAP authPassword field according to RFC 3112 */
 public class AuthPassword implements CallbackHandler {
        private final String authScheme;
@@ -118,7 +116,7 @@ public class AuthPassword implements CallbackHandler {
                        }
                        return null;
                } catch (NamingException e) {
-                       throw new UserDirectoryException("Cannot check attribute", e);
+                       throw new IllegalStateException("Cannot check attribute", e);
                }
        }
 
index d68173a2a99263df220a914e2780efb43dbaa7c3..69ceb129c60bb424f95f1ee4c955f50b2e8c1375 100644 (file)
@@ -22,8 +22,6 @@ import javax.naming.directory.BasicAttributes;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 
-import org.argeo.osgi.useradmin.UserDirectoryException;
-
 /** Basic LDIF parser. */
 public class LdifParser {
        private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
@@ -36,13 +34,13 @@ public class LdifParser {
                        if (nameAttr == null)
                                currentAttributes.put(nameRdn.getType(), nameRdn.getValue());
                        else if (!nameAttr.get().equals(nameRdn.getValue()))
-                               throw new UserDirectoryException(
+                               throw new IllegalStateException(
                                                "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + currentDn
                                                                + " (shortly before line " + lineNumber + " in LDIF file)");
                        Attributes previous = res.put(currentDn, currentAttributes);
                        return previous;
                } catch (NamingException e) {
-                       throw new UserDirectoryException("Cannot add " + currentDn, e);
+                       throw new IllegalStateException("Cannot add " + currentDn, e);
                }
        }
 
index 457380b9bf5d3a74176b4dd5d2fa2d75690ff70f..496e53b1ba83d35dfe452adf13cb54a123ec0788 100644 (file)
@@ -23,8 +23,6 @@ import javax.naming.directory.Attributes;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 
-import org.argeo.osgi.useradmin.UserDirectoryException;
-
 /** Basic LDIF writer */
 public class LdifWriter {
        private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
@@ -46,7 +44,7 @@ public class LdifWriter {
                        Rdn nameRdn = name.getRdn(name.size() - 1);
                        Attribute nameAttr = attributes.get(nameRdn.getType());
                        if (!nameAttr.get().equals(nameRdn.getValue()))
-                               throw new UserDirectoryException(
+                               throw new IllegalArgumentException(
                                                "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + name);
 
                        writer.append(DN + ": ").append(name.toString()).append('\n');
@@ -70,7 +68,7 @@ public class LdifWriter {
                        writer.append('\n');
                        writer.flush();
                } catch (NamingException e) {
-                       throw new UserDirectoryException("Cannot write LDIF", e);
+                       throw new IllegalStateException("Cannot write LDIF", e);
                }
        }