Remove dependency to OSGi user admin from API
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 10 Mar 2024 09:10:59 +0000 (10:10 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 10 Mar 2024 09:10:59 +0000 (10:10 +0100)
25 files changed:
org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsAuthorization.java
org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsGroup.java
org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsRole.java [new file with mode: 0644]
org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUser.java
org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUserManager.java
org.argeo.api.cms/src/org/argeo/api/cms/directory/UserDirectory.java
org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java
org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContentProvider.java
org.argeo.cms/src/org/argeo/cms/acr/directory/HierarchyUnitContent.java
org.argeo.cms/src/org/argeo/cms/acr/directory/RoleContent.java
org.argeo.cms/src/org/argeo/cms/auth/CmsRole.java [deleted file]
org.argeo.cms/src/org/argeo/cms/auth/CmsSystemRole.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/UserAdminUtils.java
org.argeo.cms/src/org/argeo/cms/directory/ldap/DefaultLdapEntry.java
org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserManagerImpl.java
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/AggregatingAuthorization.java
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiAuthorization.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiGroup.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiRole.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiUser.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/DirectoryUserAdmin.java
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifAuthorization.java
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifGroup.java
org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifUser.java
org.argeo.cms/src/org/argeo/cms/util/LangUtils.java

index 5d3a69575b82b1815b03a9637dd0753dc6bbb98a..6aaff8dcd04b2a323f440f2ee92102bab811ca92 100644 (file)
@@ -1,9 +1,7 @@
 package org.argeo.api.cms.directory;
 
-import org.osgi.service.useradmin.Authorization;
-
 /** An authorisation to a CMS system. */
-public interface CmsAuthorization extends Authorization {
+public interface CmsAuthorization {
        /** The role which did imply this role, <code>null</code> if a direct role. */
        default String getImplyingRole(String role) {
                return null;
index 410d391ba71bcc9f0a7c88cc7e4f7ac46828432b..f41ae6f82eb1571f73868a4767f2b4a07e6badc5 100644 (file)
@@ -1,8 +1,8 @@
 package org.argeo.api.cms.directory;
 
-import org.osgi.service.useradmin.Group;
+import java.util.Set;
 
-/** A group in a user directroy. */
-public interface CmsGroup extends Group, CmsUser {
-//     List<LdapName> getMemberNames();
+/** A group in a user directory. */
+public interface CmsGroup extends CmsUser {
+       Set<? extends CmsRole> getDirectMembers();
 }
diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsRole.java b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsRole.java
new file mode 100644 (file)
index 0000000..7060eb0
--- /dev/null
@@ -0,0 +1,12 @@
+package org.argeo.api.cms.directory;
+
+import java.util.Dictionary;
+
+/** Parent of user/group hierarchy */
+public interface CmsRole {
+       String getName();
+
+       // TODO replace with Map or ACR content
+       @Deprecated
+       Dictionary<String, Object> getProperties();
+}
index f8f40a1a685698c07506b2c2f6e5f615c223e8f1..c6e9f34c88363b34be6853d5930b771d1bce5198 100644 (file)
@@ -1,10 +1,9 @@
 package org.argeo.api.cms.directory;
 
-import org.osgi.service.useradmin.User;
-
 /**
  * An entity with credentials which can log in to a system. Can be a real person
  * or not.
  */
-public interface CmsUser extends User {
+public interface CmsUser extends CmsRole {
+       String getDisplayName();
 }
index 7693f6710ae840be75e8eb85677d83f17b00c31e..5af777975769c9f6d10b45eaa7bf6ea72e8a9759 100644 (file)
@@ -8,9 +8,6 @@ import java.util.Set;
 import javax.security.auth.Subject;
 import javax.xml.namespace.QName;
 
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
 /**
  * Provide method interfaces to manage user concepts without accessing directly
  * the userAdmin.
@@ -21,11 +18,11 @@ public interface CmsUserManager {
        Set<UserDirectory> getUserDirectories();
 
        // CurrentUser
-       /** Returns the e-mail of the current logged in user */
-       String getMyMail();
+//     /** Returns the e-mail of the current logged in user */
+//     String getMyMail();
 
        // Other users
-       /** Returns a {@link User} given a username */
+       /** Returns a {@link CmsUser} given a username */
        CmsUser getUser(String username);
 
        /** Can be a group or a user */
@@ -42,7 +39,7 @@ public interface CmsUserManager {
 
        // Search
        /** Returns a filtered list of roles */
-       Role[] getRoles(String filter);
+       CmsRole[] getRoles(String filter);
 
        /** Recursively lists users in a given group. */
        Set<CmsUser> listUsersInGroup(String groupDn, String filter);
@@ -73,18 +70,18 @@ public interface CmsUserManager {
        CmsGroup getOrCreateSystemRole(HierarchyUnit roles, QName systemRole);
 
        /** Add additional object classes to this role. */
-       void addObjectClasses(Role role, Set<String> objectClasses, Map<String, Object> additionalProperties);
+       void addObjectClasses(CmsRole role, Set<String> objectClasses, Map<String, Object> additionalProperties);
 
        /** Add additional object classes to this hierarchy unit. */
        void addObjectClasses(HierarchyUnit hierarchyUnit, Set<String> objectClasses,
                        Map<String, Object> additionalProperties);
 
        /** Add a member to this group. */
-       void addMember(CmsGroup group, Role role);
+       void addMember(CmsGroup group, CmsRole role);
 
        /** Remove a member from this group. */
-       void removeMember(CmsGroup group, Role role);
-       
+       void removeMember(CmsGroup group, CmsRole role);
+
        void edit(Runnable action);
 
        /* MISCELLANEOUS */
@@ -95,7 +92,7 @@ public interface CmsUserManager {
        String getDefaultDomainName();
 
        /**
-        * Search for a {@link User} (might also be a group) whose uid or cn is equals
+        * Search for a {@link CmsUser} (might also be a group) whose uid or cn is equals
         * to localId within the various user repositories defined in the current
         * context.
         */
@@ -118,7 +115,7 @@ public interface CmsUserManager {
 
        void expireAuthTokens(Subject subject);
 
-       UserDirectory getDirectory(Role role);
+       UserDirectory getDirectory(CmsRole role);
 
        /** Create a new hierarchy unit. Does nothing if it already exists. */
        HierarchyUnit getOrCreateHierarchyUnit(UserDirectory directory, String path);
index 1f0ecdf75ca2b2abf14f29cd257156caa2ef1cc9..3058e58007fabc63fd8dc75ccb20f10c4715dbc7 100644 (file)
@@ -1,17 +1,15 @@
 package org.argeo.api.cms.directory;
 
-import org.osgi.service.useradmin.Role;
-
 /** Information about a user directory. */
 public interface UserDirectory extends CmsDirectory {
 
-       HierarchyUnit getHierarchyUnit(Role role);
+       HierarchyUnit getHierarchyUnit(CmsRole role);
 
-       Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep);
+       Iterable<? extends CmsRole> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep);
 
-       String getRolePath(Role role);
+       String getRolePath(CmsRole role);
 
-       String getRoleSimpleName(Role role);
+       String getRoleSimpleName(CmsRole role);
 
-       Role getRoleByPath(String path);
+       CmsRole getRoleByPath(String path);
 }
index f01a3b017569e78dc7796748b1deb70d12195790..b3f81454734be5e1d2e86cc1805c8d272fdad86c 100644 (file)
@@ -22,11 +22,11 @@ import org.argeo.api.cms.CmsAuth;
 import org.argeo.api.cms.CmsConstants;
 import org.argeo.api.cms.CmsSession;
 import org.argeo.api.cms.directory.CmsDirectory;
+import org.argeo.api.cms.directory.CmsRole;
 import org.argeo.api.cms.directory.CmsUserManager;
 import org.argeo.api.cms.directory.HierarchyUnit;
 import org.argeo.api.cms.directory.UserDirectory;
 import org.argeo.cms.util.CurrentSubject;
-import org.osgi.service.useradmin.Role;
 
 /** Utilities and routines around {@link Content}. */
 public class ContentUtils {
@@ -147,7 +147,7 @@ public class ContentUtils {
         * DIRECTORY
         */
 
-       public static Content roleToContent(CmsUserManager userManager, ContentSession contentSession, Role role) {
+       public static Content roleToContent(CmsUserManager userManager, ContentSession contentSession, CmsRole role) {
                UserDirectory userDirectory = userManager.getDirectory(role);
                String path = directoryPath(userDirectory) + userDirectory.getRolePath(role);
                Content content = contentSession.get(path);
index ab84aef37131b4a780fb92644f9ed4a96754161f..fc48dace5ca6ffd850fbf2ae3f40c7b372c35185 100644 (file)
@@ -10,12 +10,12 @@ import org.argeo.api.acr.ContentNotFoundException;
 import org.argeo.api.acr.spi.ContentProvider;
 import org.argeo.api.acr.spi.ProvidedContent;
 import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.api.cms.directory.CmsUser;
 import org.argeo.api.cms.directory.CmsUserManager;
 import org.argeo.api.cms.directory.HierarchyUnit;
 import org.argeo.api.cms.directory.UserDirectory;
 import org.argeo.cms.acr.AbstractSimpleContentProvider;
 import org.argeo.cms.acr.ContentUtils;
-import org.osgi.service.useradmin.User;
 
 /** A {@link ContentProvider} based on a {@link CmsUserManager} service. */
 public class DirectoryContentProvider extends AbstractSimpleContentProvider<CmsUserManager> {
@@ -62,7 +62,7 @@ public class DirectoryContentProvider extends AbstractSimpleContentProvider<CmsU
 //                     } catch (InvalidNameException e) {
 //                             throw new IllegalStateException("Cannot interpret " + segments + " as DN", e);
 //                     }
-                       User user = (User) userDirectory.getRoleByPath(pathWithinUserDirectory);
+                       CmsUser user = (CmsUser) userDirectory.getRoleByPath(pathWithinUserDirectory);
                        if (user != null) {
                                HierarchyUnit parent = userDirectory.getHierarchyUnit(user);
                                return new RoleContent(session, this, new HierarchyUnitContent(session, this, parent), user);
index 5acf8ab63fc07711f1956ed4fa3380c952f294a5..e4c637f20b8fd2fca0cdccaf0f295e3594d2f8e0 100644 (file)
@@ -10,13 +10,12 @@ import javax.xml.namespace.QName;
 
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentName;
-import org.argeo.api.acr.CrName;
 import org.argeo.api.acr.DName;
 import org.argeo.api.acr.spi.ProvidedSession;
 import org.argeo.api.cms.directory.CmsDirectory;
+import org.argeo.api.cms.directory.CmsRole;
 import org.argeo.api.cms.directory.HierarchyUnit;
 import org.argeo.api.cms.directory.UserDirectory;
-import org.osgi.service.useradmin.Role;
 
 class HierarchyUnitContent extends AbstractDirectoryContent {
        private HierarchyUnit hierarchyUnit;
@@ -58,7 +57,7 @@ class HierarchyUnitContent extends AbstractDirectoryContent {
                for (HierarchyUnit hu : hierarchyUnit.getDirectHierarchyUnits(false))
                        lst.add(new HierarchyUnitContent(getSession(), provider, hu));
 
-               for (Role role : ((UserDirectory) hierarchyUnit.getDirectory()).getHierarchyUnitRoles(hierarchyUnit, null,
+               for (CmsRole role : ((UserDirectory) hierarchyUnit.getDirectory()).getHierarchyUnitRoles(hierarchyUnit, null,
                                false))
                        lst.add(new RoleContent(getSession(), provider, this, role));
                return lst.iterator();
index 64feb1d6735955310ee458a00c50a53adbe842c8..c72ea37607c92ff26369aeee211bf0ae83286728 100644 (file)
@@ -7,22 +7,24 @@ import javax.xml.namespace.QName;
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentName;
 import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.api.cms.directory.CmsRole;
 import org.argeo.api.cms.directory.UserDirectory;
 import org.osgi.service.useradmin.Role;
 
 class RoleContent extends AbstractDirectoryContent {
 
        private HierarchyUnitContent parent;
-       private Role role;
+       private CmsRole role;
 
        public RoleContent(ProvidedSession session, DirectoryContentProvider provider, HierarchyUnitContent parent,
-                       Role role) {
+                       CmsRole role) {
                super(session, provider);
                this.parent = parent;
                this.role = role;
        }
 
        @Override
+       @Deprecated
        Dictionary<String, Object> doGetProperties() {
                return role.getProperties();
        }
@@ -41,8 +43,11 @@ class RoleContent extends AbstractDirectoryContent {
        @SuppressWarnings("unchecked")
        @Override
        public <A> A adapt(Class<A> clss) {
-               if (Role.class.isAssignableFrom(clss))
+               if (CmsRole.class.isAssignableFrom(clss))
                        return (A) role;
+               // TODO do we need this?
+//             if (Role.class.isAssignableFrom(clss))
+//                     return (A) role;
                return super.adapt(clss);
        }
 
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsRole.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsRole.java
deleted file mode 100644 (file)
index 8834f35..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.argeo.cms.auth;
-
-import javax.xml.namespace.QName;
-
-import org.argeo.api.acr.ArgeoNamespace;
-import org.argeo.api.acr.ContentName;
-import org.argeo.cms.SystemRole;
-
-/** Standard CMS system roles. */
-public enum CmsRole implements SystemRole {
-       userAdmin, //
-       groupAdmin, //
-       //
-       ;
-
-       private final static String QUALIFIER = "cms.";
-
-       private final ContentName name;
-
-       CmsRole() {
-               name = new ContentName(ArgeoNamespace.ROLE_NAMESPACE_URI, QUALIFIER + name());
-       }
-
-       @Override
-       public QName qName() {
-               return name;
-       }
-
-       @Override
-       public String toString() {
-               return name.toPrefixedString();
-       }
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsSystemRole.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsSystemRole.java
new file mode 100644 (file)
index 0000000..64dbd0f
--- /dev/null
@@ -0,0 +1,33 @@
+package org.argeo.cms.auth;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.ArgeoNamespace;
+import org.argeo.api.acr.ContentName;
+import org.argeo.cms.SystemRole;
+
+/** Standard CMS system roles. */
+public enum CmsSystemRole implements SystemRole {
+       userAdmin, //
+       groupAdmin, //
+       //
+       ;
+
+       private final static String QUALIFIER = "cms.";
+
+       private final ContentName name;
+
+       CmsSystemRole() {
+               name = new ContentName(ArgeoNamespace.ROLE_NAMESPACE_URI, QUALIFIER + name());
+       }
+
+       @Override
+       public QName qName() {
+               return name;
+       }
+
+       @Override
+       public String toString() {
+               return name.toPrefixedString();
+       }
+}
index bef6d7f0a187718c914fc6084f193a3aa7e29137..84e75e32515f0f14bfc3e9907c3949c9fada3e7d 100644 (file)
@@ -14,6 +14,8 @@ import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
 /** Centralise common patterns to manage users with a {@link UserAdmin} */
+@Deprecated
+// TODO use CmsRole after migrating to qualified properties
 public class UserAdminUtils {
 
        // CURRENTUSER HELPERS
@@ -73,6 +75,10 @@ public class UserAdminUtils {
                return getUserDisplayName(user);
        }
 
+       public static String getUserDisplayName(org.argeo.api.cms.directory.CmsRole user) {
+               return getUserDisplayName((Role) user);
+       }
+
        public static String getUserDisplayName(Role user) {
                String dName = getProperty(user, LdapAttr.displayName.name());
                if (isEmpty(dName))
index 697ad441fb89f4887d6de83563cd63166bbae3b5..f919fa6c843050d7a8564d133e91c3e91173c7db 100644 (file)
@@ -22,6 +22,7 @@ import javax.naming.directory.Attributes;
 import javax.naming.directory.BasicAttribute;
 import javax.naming.ldap.LdapName;
 
+import org.argeo.api.acr.QNamed;
 import org.argeo.api.acr.ldap.LdapAttr;
 import org.argeo.api.acr.ldap.LdapObj;
 import org.argeo.api.cms.directory.DirectoryDigestUtils;
@@ -145,6 +146,17 @@ public class DefaultLdapEntry implements LdapEntry {
                return credentials;
        }
 
+       protected String getPropertyAsString(QNamed key) {
+               return getPropertyAsString(key.localName());
+       }
+
+       protected String getPropertyAsString(String key) {
+               Object res = getProperties().get(key);
+               if (res == null)
+                       return null;
+               return res.toString();
+       }
+
        /*
         * CREDENTIALS
         */
index 1eb227b0e6588e755b0fe8e77f62f42a79d915d4..64d3fab2583e8ffb7259133f894f00044f23ccb0 100644 (file)
@@ -31,6 +31,7 @@ import org.argeo.api.acr.ldap.NamingUtils;
 import org.argeo.api.cms.CmsConstants;
 import org.argeo.api.cms.CmsLog;
 import org.argeo.api.cms.directory.CmsGroup;
+import org.argeo.api.cms.directory.CmsRole;
 import org.argeo.api.cms.directory.CmsUser;
 import org.argeo.api.cms.directory.CmsUserManager;
 import org.argeo.api.cms.directory.HierarchyUnit;
@@ -85,15 +86,19 @@ public class CmsUserManagerImpl implements CmsUserManager {
 
        }
 
-       @Override
-       public String getMyMail() {
-               return getUserMail(CurrentUser.getUsername());
-       }
+//     @Override
+//     public String getMyMail() {
+//             return getUserMail(CurrentUser.getUsername());
+//     }
 
        @Override
-       public Role[] getRoles(String filter) {
+       public CmsRole[] getRoles(String filter) {
                try {
-                       return userAdmin.getRoles(filter);
+                       Role[] roles = userAdmin.getRoles(filter);
+                       CmsRole[] res = new CmsRole[roles.length];
+                       for (int i = 0; i < roles.length; i++)
+                               res[i] = (CmsRole) roles[i];
+                       return res;
                } catch (InvalidSyntaxException e) {
                        throw new IllegalArgumentException("Invalid filter " + filter, e);
                }
@@ -124,7 +129,7 @@ public class CmsUserManagerImpl implements CmsUserManager {
        /** Lists all roles of the given user */
        @Override
        public String[] getUserRoles(String dn) {
-               Authorization currAuth = getUserAdmin().getAuthorization(getUser(dn));
+               Authorization currAuth = getUserAdmin().getAuthorization((User) getUser(dn));
                return currAuth.getRoles();
        }
 
@@ -147,28 +152,12 @@ public class CmsUserManagerImpl implements CmsUserManager {
                return users;
        }
 
-//     @Override
-//     public Set<User> listAccounts(HierarchyUnit hierarchyUnit, boolean deep) {
-//             if(!hierarchyUnit.isFunctional())
-//                     throw new IllegalArgumentException("Hierarchy unit "+hierarchyUnit.getBase()+" is not functional");
-//             UserDirectory directory = (UserDirectory)hierarchyUnit.getDirectory();
-//             Set<User> res = new HashSet<>();
-//             for(HierarchyUnit technicalHu:hierarchyUnit.getDirectHierarchyUnits(false)) {
-//                     if(technicalHu.isFunctional())
-//                             continue;
-//                     for(Role role:directory.getHierarchyUnitRoles(technicalHu, null, false)) {
-//                             if(role)
-//                     }
-//             }
-//             return res;
-//     }
-
        /** Recursively add users to list */
        private void addUsers(Set<CmsUser> users, Group group, String filter) {
-               Role[] roles = group.getMembers();
+               Role[] roles = ((Group) group).getMembers();
                for (Role role : roles) {
                        if (role.getType() == Role.GROUP) {
-                               addUsers(users, (CmsGroup) role, filter);
+                               addUsers(users, (Group) role, filter);
                        } else if (role.getType() == Role.USER) {
                                if (match(role, filter))
                                        users.add((CmsUser) role);
@@ -240,7 +229,7 @@ public class CmsUserManagerImpl implements CmsUserManager {
        public CmsUser createUser(String username, Map<String, Object> properties, Map<String, Object> credentials) {
                try {
                        userTransaction.begin();
-                       CmsUser user = (CmsUser) userAdmin.createRole(username, Role.USER);
+                       User user = (User) userAdmin.createRole(username, Role.USER);
                        if (properties != null) {
                                for (String key : properties.keySet())
                                        user.getProperties().put(key, properties.get(key));
@@ -250,7 +239,7 @@ public class CmsUserManagerImpl implements CmsUserManager {
                                        user.getCredentials().put(key, credentials.get(key));
                        }
                        userTransaction.commit();
-                       return user;
+                       return (CmsUser) user;
                } catch (Exception e) {
                        try {
                                userTransaction.rollback();
@@ -355,7 +344,7 @@ public class CmsUserManagerImpl implements CmsUserManager {
        }
 
        @Override
-       public void addObjectClasses(Role role, Set<String> objectClasses, Map<String, Object> additionalProperties) {
+       public void addObjectClasses(CmsRole role, Set<String> objectClasses, Map<String, Object> additionalProperties) {
                try {
                        userTransaction.begin();
                        LdapEntry.addObjectClasses(role.getProperties(), objectClasses);
@@ -417,10 +406,10 @@ public class CmsUserManagerImpl implements CmsUserManager {
        }
 
        @Override
-       public void addMember(CmsGroup group, Role role) {
+       public void addMember(CmsGroup group, CmsRole role) {
                try {
                        userTransaction.begin();
-                       group.addMember(role);
+                       ((Group) group).addMember((Role) role);
                        userTransaction.commit();
                } catch (Exception e1) {
                        try {
@@ -435,10 +424,10 @@ public class CmsUserManagerImpl implements CmsUserManager {
        }
 
        @Override
-       public void removeMember(CmsGroup group, Role role) {
+       public void removeMember(CmsGroup group, CmsRole role) {
                try {
                        userTransaction.begin();
-                       group.removeMember(role);
+                       ((Group) group).removeMember((Role) role);
                        userTransaction.commit();
                } catch (Exception e1) {
                        try {
@@ -675,7 +664,7 @@ public class CmsUserManagerImpl implements CmsUserManager {
        }
 
        @Override
-       public UserDirectory getDirectory(Role user) {
+       public UserDirectory getDirectory(CmsRole user) {
                String name = user.getName();
                NavigableMap<String, UserDirectory> possible = new TreeMap<>();
                for (UserDirectory userDirectory : userDirectories) {
index 72c4336e31abd40c098a2e476ad719755ad0edfc..c5cb904fa2191594dae3465fb4ab17aca27b9d74 100644 (file)
@@ -12,7 +12,7 @@ import org.argeo.api.cms.directory.CmsAuthorization;
 import org.osgi.service.useradmin.Authorization;
 
 /** An {@link Authorization} which combines roles form various auth sources. */
-class AggregatingAuthorization implements CmsAuthorization {
+class AggregatingAuthorization implements CmsAuthorization, Authorization {
        private final String name;
        private final String displayName;
        private final Set<String> systemRoles;
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiAuthorization.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiAuthorization.java
new file mode 100644 (file)
index 0000000..1f2d215
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.cms.osgi.useradmin;
+
+import org.argeo.api.cms.directory.CmsAuthorization;
+import org.osgi.service.useradmin.Authorization;
+
+/** Merging interface between CMS and OSGi user management APIs. */
+interface CmsOsgiAuthorization extends CmsAuthorization, Authorization {
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiGroup.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiGroup.java
new file mode 100644 (file)
index 0000000..0db368e
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.cms.osgi.useradmin;
+
+import org.argeo.api.cms.directory.CmsGroup;
+import org.osgi.service.useradmin.Group;
+
+/** Merging interface between CMS and OSGi user management APIs. */
+interface CmsOsgiGroup extends CmsOsgiUser, CmsGroup, Group {
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiRole.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiRole.java
new file mode 100644 (file)
index 0000000..b2a18c8
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.cms.osgi.useradmin;
+
+import org.argeo.api.cms.directory.CmsRole;
+import org.osgi.service.useradmin.Role;
+
+/** Merging interface between CMS and OSGi user management APIs. */
+interface CmsOsgiRole extends CmsRole, Role {
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiUser.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiUser.java
new file mode 100644 (file)
index 0000000..14d4a9d
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.cms.osgi.useradmin;
+
+import org.argeo.api.cms.directory.CmsUser;
+import org.osgi.service.useradmin.User;
+
+/** Merging interface between CMS and OSGi user management APIs. */
+interface CmsOsgiUser extends CmsOsgiRole, CmsUser, User {
+
+}
index 03f17e61f35b1405956203a863ee158394b09442..e5fb01242bf7c690ca9d5f3cdae294ea47f6bca0 100644 (file)
@@ -25,8 +25,8 @@ import javax.naming.ldap.Rdn;
 import javax.security.auth.Subject;
 import javax.security.auth.kerberos.KerberosTicket;
 
+import org.argeo.api.cms.directory.CmsRole;
 import org.argeo.api.cms.directory.DirectoryDigestUtils;
-import org.argeo.api.cms.directory.CmsUser;
 import org.argeo.api.cms.directory.HierarchyUnit;
 import org.argeo.api.cms.directory.UserDirectory;
 import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
@@ -126,30 +126,30 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
        }
 
        @Override
-       public String getRolePath(Role role) {
+       public String getRolePath(CmsRole role) {
                return nameToRelativePath(LdapNameUtils.toLdapName(role.getName()));
        }
 
        @Override
-       public String getRoleSimpleName(Role role) {
+       public String getRoleSimpleName(CmsRole role) {
                LdapName dn = LdapNameUtils.toLdapName(role.getName());
                String name = LdapNameUtils.getLastRdnValue(dn);
                return name;
        }
 
        @Override
-       public Role getRoleByPath(String path) {
+       public CmsRole getRoleByPath(String path) {
                LdapEntry entry = doGetRole(pathToName(path));
-               if (!(entry instanceof Role)) {
+               if (!(entry instanceof CmsRole)) {
                        return null;
 //                     throw new IllegalStateException("Path must be a UserAdmin Role.");
                } else {
-                       return (Role) entry;
+                       return (CmsRole) entry;
                }
        }
 
-       protected List<Role> getAllRoles(CmsUser user) {
-               List<Role> allRoles = new ArrayList<Role>();
+       protected List<CmsOsgiRole> getAllRoles(CmsOsgiUser user) {
+               List<CmsOsgiRole> allRoles = new ArrayList<CmsOsgiRole>();
                if (user != null) {
                        collectRoles((LdapEntry) user, allRoles);
                        allRoles.add(user);
@@ -158,17 +158,17 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                return allRoles;
        }
 
-       private void collectRoles(LdapEntry user, List<Role> allRoles) {
+       private void collectRoles(LdapEntry user, List<CmsOsgiRole> allRoles) {
                List<LdapEntry> allEntries = new ArrayList<>();
                LdapEntry entry = user;
                collectGroups(entry, allEntries);
                for (LdapEntry e : allEntries) {
-                       if (e instanceof Role)
-                               allRoles.add((Role) e);
+                       if (e instanceof CmsOsgiRole)
+                               allRoles.add((CmsOsgiRole) e);
                }
        }
 
-       private void collectAnonymousRoles(List<Role> allRoles) {
+       private void collectAnonymousRoles(List<CmsOsgiRole> allRoles) {
                // TODO gather anonymous roles
        }
 
@@ -184,23 +184,23 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                return res.toArray(new Role[res.size()]);
        }
 
-       List<CmsUser> getRoles(LdapName searchBase, String filter, boolean deep) throws InvalidSyntaxException {
+       List<CmsOsgiUser> getRoles(LdapName searchBase, String filter, boolean deep) throws InvalidSyntaxException {
                LdapEntryWorkingCopy wc = getWorkingCopy();
 //             Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null;
                List<LdapEntry> searchRes = getDirectoryDao().doGetEntries(searchBase, filter, deep);
-               List<CmsUser> res = new ArrayList<>();
+               List<CmsOsgiUser> res = new ArrayList<>();
                for (LdapEntry entry : searchRes)
-                       res.add((CmsUser) entry);
+                       res.add((CmsOsgiUser) entry);
                if (wc != null) {
-                       for (Iterator<CmsUser> it = res.iterator(); it.hasNext();) {
-                               CmsUser user = (CmsUser) it.next();
+                       for (Iterator<CmsOsgiUser> it = res.iterator(); it.hasNext();) {
+                               CmsOsgiUser user = it.next();
                                LdapName dn = LdapNameUtils.toLdapName(user.getName());
                                if (wc.getDeletedData().containsKey(dn))
                                        it.remove();
                        }
                        Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null;
                        for (LdapEntry ldapEntry : wc.getNewData().values()) {
-                               CmsUser user = (CmsUser) ldapEntry;
+                               CmsOsgiUser user = (CmsOsgiUser) ldapEntry;
                                if (f == null || f.match(user.getProperties()))
                                        res.add(user);
                        }
@@ -213,7 +213,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
        @Override
        public User getUser(String key, String value) {
                // TODO check value null or empty
-               List<CmsUser> collectedUsers = new ArrayList<CmsUser>();
+               List<CmsOsgiUser> collectedUsers = new ArrayList<>();
                if (key != null) {
                        doGetUser(key, value, collectedUsers);
                } else {
@@ -229,11 +229,11 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                return null;
        }
 
-       protected void doGetUser(String key, String value, List<CmsUser> collectedUsers) {
+       protected void doGetUser(String key, String value, List<CmsOsgiUser> collectedUsers) {
                String f = "(" + key + "=" + value + ")";
                List<LdapEntry> users = getDirectoryDao().doGetEntries(getBaseDn(), f, true);
                for (LdapEntry entry : users)
-                       collectedUsers.add((CmsUser) entry);
+                       collectedUsers.add((CmsOsgiUser) entry);
        }
 
        @Override
@@ -242,9 +242,9 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                        return new LdifAuthorization(user, getAllRoles(null));
                }
                LdapName userName = toLdapName(user.getName());
-               if (isExternal(userName) && user instanceof LdapEntry) {
-                       List<Role> allRoles = new ArrayList<Role>();
-                       collectRoles((LdapEntry) user, allRoles);
+               if (isExternal(userName) && user instanceof LdapEntry ldapEntry) {
+                       List<CmsOsgiRole> allRoles = new ArrayList<>();
+                       collectRoles(ldapEntry, allRoles);
                        return new LdifAuthorization(user, allRoles);
                } else {
 
@@ -263,8 +263,8 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                                return getAuthorizationFromScoped(scopedUserAdmin, user);
                        }
 
-                       if (user instanceof CmsUser) {
-                               return new LdifAuthorization(user, getAllRoles((CmsUser) user));
+                       if (user instanceof CmsOsgiUser u) {
+                               return new LdifAuthorization(user, getAllRoles(u));
                        } else {
                                // bind with authenticating user
                                DirectoryUserAdmin scopedUserAdmin = scope(user).orElseThrow();
@@ -275,7 +275,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
 
        private Authorization getAuthorizationFromScoped(DirectoryUserAdmin scopedUserAdmin, User user) {
                try {
-                       CmsUser directoryUser = (CmsUser) scopedUserAdmin.getRole(user.getName());
+                       CmsOsgiUser directoryUser = (CmsOsgiUser) scopedUserAdmin.getRole(user.getName());
                        if (directoryUser == null)
                                throw new IllegalStateException("No scoped user found for " + user);
                        LdifAuthorization authorization = new LdifAuthorization(directoryUser,
@@ -348,7 +348,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
         * HIERARCHY
         */
        @Override
-       public HierarchyUnit getHierarchyUnit(Role role) {
+       public HierarchyUnit getHierarchyUnit(CmsRole role) {
                LdapName dn = LdapNameUtils.toLdapName(role.getName());
                LdapName huDn = LdapNameUtils.getParent(dn);
                HierarchyUnit hierarchyUnit = getDirectoryDao().doGetHierarchyUnit(huDn);
@@ -358,7 +358,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
        }
 
        @Override
-       public Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) {
+       public Iterable<? extends CmsRole> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) {
                LdapName dn = LdapNameUtils.toLdapName(hierarchyUnit.getBase());
                try {
                        return getRoles(dn, filter, deep);
index a54050bc65bdca36ce8d2298364eebe77c433b61..59e5df93110b3327ab1b413fb8bc8cd51429b6d8 100644 (file)
@@ -7,16 +7,15 @@ import java.util.List;
 
 import org.argeo.api.acr.ldap.LdapAttr;
 import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 
 /** Basic authorization. */
-class LdifAuthorization implements Authorization {
+class LdifAuthorization implements CmsOsgiAuthorization {
        private final String name;
        private final String displayName;
        private final List<String> allRoles;
 
-       public LdifAuthorization(User user, List<Role> allRoles) {
+       public LdifAuthorization(User user, List<CmsOsgiRole> allRoles) {
                if (user == null) {
                        this.name = null;
                        this.displayName = "anonymous";
index 99aca1f2f4ea20d2d7460464068dc72d79f3f72f..fd665149926c2287839e45d5b4638bfd3ca4f99d 100644 (file)
@@ -1,18 +1,18 @@
 package org.argeo.cms.osgi.useradmin;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.naming.InvalidNameException;
 import javax.naming.directory.Attribute;
 import javax.naming.ldap.LdapName;
 
-import org.argeo.api.cms.directory.CmsGroup;
+import org.argeo.api.cms.directory.CmsRole;
 import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
 import org.osgi.service.useradmin.Role;
 
 /** Directory group implementation */
-class LdifGroup extends LdifUser implements CmsGroup {
+class LdifGroup extends LdifUser implements CmsOsgiGroup {
        private final String memberAttributeId;
 
        LdifGroup(AbstractLdapDirectory userAdmin, LdapName dn) {
@@ -69,9 +69,9 @@ class LdifGroup extends LdifUser implements CmsGroup {
 
        @Override
        public Role[] getMembers() {
-               List<Role> directMembers = new ArrayList<Role>();
+               Set<CmsOsgiRole> directMembers = new HashSet<>();
                for (LdapName ldapName : getReferences(memberAttributeId)) {
-                       Role role = findRole(ldapName);
+                       CmsOsgiRole role = findRole(ldapName);
                        if (role == null) {
                                throw new IllegalStateException("Role " + ldapName + " not found.");
                        }
@@ -80,18 +80,35 @@ class LdifGroup extends LdifUser implements CmsGroup {
                return directMembers.toArray(new Role[directMembers.size()]);
        }
 
+       @Override
+       public Set<? extends CmsRole> getDirectMembers() {
+               return doGetDirectMembers();
+       }
+
+       protected Set<CmsOsgiRole> doGetDirectMembers() {
+               Set<CmsOsgiRole> directMembers = new HashSet<>();
+               for (LdapName ldapName : getReferences(memberAttributeId)) {
+                       CmsOsgiRole role = findRole(ldapName);
+                       if (role == null) {
+                               throw new IllegalStateException("Role " + ldapName + " not found.");
+                       }
+                       directMembers.add(role);
+               }
+               return directMembers;
+       }
+
        /**
         * Whether a role with this name can be found from this context.
         * 
         * @return The related {@link Role} or <code>null</code>.
         */
-       protected Role findRole(LdapName ldapName) {
+       protected CmsOsgiRole findRole(LdapName ldapName) {
                Role role = getUserAdmin().getRole(ldapName.toString());
                if (role == null) {
                        if (getUserAdmin().getExternalRoles() != null)
                                role = getUserAdmin().getExternalRoles().getRole(ldapName.toString());
                }
-               return role;
+               return (CmsOsgiRole) role;
        }
 
 //     @Override
index e48869a0113cc149f4bb59d48414457f5fa9bbc6..de383bde8a4f46a726f1ed2a1906f60047c434e4 100644 (file)
@@ -2,12 +2,14 @@ package org.argeo.cms.osgi.useradmin;
 
 import javax.naming.ldap.LdapName;
 
-import org.argeo.api.cms.directory.CmsUser;
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.cms.auth.UserAdminUtils;
 import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
 import org.argeo.cms.directory.ldap.DefaultLdapEntry;
+import org.argeo.cms.util.LangUtils;
 
 /** Directory user implementation */
-class LdifUser extends DefaultLdapEntry implements CmsUser {
+class LdifUser extends DefaultLdapEntry implements CmsOsgiUser {
        LdifUser(AbstractLdapDirectory userAdmin, LdapName dn) {
                super(userAdmin, dn);
        }
@@ -22,4 +24,15 @@ class LdifUser extends DefaultLdapEntry implements CmsUser {
                return USER;
        }
 
+       public String getDisplayName() {
+               String dName = getPropertyAsString(LdapAttr.displayName);
+               if (LangUtils.isEmpty(dName))
+                       dName = getPropertyAsString(LdapAttr.cn);
+               if (LangUtils.isEmpty(dName))
+                       dName = getPropertyAsString(LdapAttr.uid);
+               if (LangUtils.isEmpty(dName))
+                       dName = UserAdminUtils.getUserLocalId(getName());
+               return dName;
+       }
+
 }
index e4cc607d666c2777c94680222c5abcb4f1476421..67748ccd7121ce2cbae24c428f12b6840f55fde7 100644 (file)
@@ -13,7 +13,6 @@ import java.time.temporal.Temporal;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -31,37 +30,16 @@ import javax.naming.ldap.LdapName;
 /** Utilities around Java basic features. */
 public class LangUtils {
        /*
-        * NON-API OSGi
+        * OBJECTS and STRINGS
         */
        /**
-        * Returns an array with the names of the provided classes. Useful when
-        * registering services with multiple interfaces in OSGi.
+        * Whether this {@link String} is <code>null</null>, empty, or only white
+        * spaces.
         */
-       public static String[] names(Class<?>... clzz) {
-               String[] res = new String[clzz.length];
-               for (int i = 0; i < clzz.length; i++)
-                       res[i] = clzz[i].getName();
-               return res;
+       public static boolean isEmpty(String str) {
+               return str == null || "".equals(str.strip());
        }
 
-//     /*
-//      * MAP
-//      */
-//     /**
-//      * Creates a new {@link Map} with one key-value pair. Key should not be null,
-//      * but if the value is null, it returns an empty {@link Map}.
-//      * 
-//      * @deprecated Use {@link Collections#singletonMap(Object, Object)} instead.
-//      */
-//     @Deprecated
-//     public static Map<String, Object> map(String key, Object value) {
-//             assert key != null;
-//             HashMap<String, Object> props = new HashMap<>();
-//             if (value != null)
-//                     props.put(key, value);
-//             return props;
-//     }
-
        /*
         * DICTIONARY
         */
@@ -345,6 +323,20 @@ public class LangUtils {
                return count > 1 ? count + " seconds" : count + " second";
        }
 
+       /*
+        * NON-API OSGi
+        */
+       /**
+        * Returns an array with the names of the provided classes. Useful when
+        * registering services with multiple interfaces in OSGi.
+        */
+       public static String[] names(Class<?>... clzz) {
+               String[] res = new String[clzz.length];
+               for (int i = 0; i < clzz.length; i++)
+                       res[i] = clzz[i].getName();
+               return res;
+       }
+
        /** Singleton constructor. */
        private LangUtils() {