From: Mathieu Baudier Date: Sun, 10 Mar 2024 09:10:59 +0000 (+0100) Subject: Remove dependency to OSGi user admin from API X-Git-Tag: v2.3.28~14 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=654cb2ca43dd4513a4d6a5bbe81762eaf6675496 Remove dependency to OSGi user admin from API --- diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsAuthorization.java b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsAuthorization.java index 5d3a69575..6aaff8dcd 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsAuthorization.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsAuthorization.java @@ -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, null if a direct role. */ default String getImplyingRole(String role) { return null; diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsGroup.java b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsGroup.java index 410d391ba..f41ae6f82 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsGroup.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsGroup.java @@ -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 getMemberNames(); +/** A group in a user directory. */ +public interface CmsGroup extends CmsUser { + Set 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 index 000000000..7060eb005 --- /dev/null +++ b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsRole.java @@ -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 getProperties(); +} diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUser.java b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUser.java index f8f40a1a6..c6e9f34c8 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUser.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUser.java @@ -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(); } diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUserManager.java b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUserManager.java index 7693f6710..5af777975 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUserManager.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/directory/CmsUserManager.java @@ -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 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 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 objectClasses, Map additionalProperties); + void addObjectClasses(CmsRole role, Set objectClasses, Map additionalProperties); /** Add additional object classes to this hierarchy unit. */ void addObjectClasses(HierarchyUnit hierarchyUnit, Set objectClasses, Map 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); diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/directory/UserDirectory.java b/org.argeo.api.cms/src/org/argeo/api/cms/directory/UserDirectory.java index 1f0ecdf75..3058e5800 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/directory/UserDirectory.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/directory/UserDirectory.java @@ -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 getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep); + Iterable 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); } diff --git a/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java b/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java index f01a3b017..b3f814547 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java @@ -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); diff --git a/org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContentProvider.java b/org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContentProvider.java index ab84aef37..fc48dace5 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContentProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContentProvider.java @@ -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 { @@ -62,7 +62,7 @@ public class DirectoryContentProvider extends AbstractSimpleContentProvider doGetProperties() { return role.getProperties(); } @@ -41,8 +43,11 @@ class RoleContent extends AbstractDirectoryContent { @SuppressWarnings("unchecked") @Override public A adapt(Class 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 index 8834f3587..000000000 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsRole.java +++ /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 index 000000000..64dbd0f6e --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsSystemRole.java @@ -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(); + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminUtils.java index bef6d7f0a..84e75e325 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminUtils.java @@ -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)) diff --git a/org.argeo.cms/src/org/argeo/cms/directory/ldap/DefaultLdapEntry.java b/org.argeo.cms/src/org/argeo/cms/directory/ldap/DefaultLdapEntry.java index 697ad441f..f919fa6c8 100644 --- a/org.argeo.cms/src/org/argeo/cms/directory/ldap/DefaultLdapEntry.java +++ b/org.argeo.cms/src/org/argeo/cms/directory/ldap/DefaultLdapEntry.java @@ -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 */ diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserManagerImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserManagerImpl.java index 1eb227b0e..64d3fab25 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserManagerImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserManagerImpl.java @@ -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 listAccounts(HierarchyUnit hierarchyUnit, boolean deep) { -// if(!hierarchyUnit.isFunctional()) -// throw new IllegalArgumentException("Hierarchy unit "+hierarchyUnit.getBase()+" is not functional"); -// UserDirectory directory = (UserDirectory)hierarchyUnit.getDirectory(); -// Set 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 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 properties, Map 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 objectClasses, Map additionalProperties) { + public void addObjectClasses(CmsRole role, Set objectClasses, Map 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 possible = new TreeMap<>(); for (UserDirectory userDirectory : userDirectories) { diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/AggregatingAuthorization.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/AggregatingAuthorization.java index 72c4336e3..c5cb904fa 100644 --- a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/AggregatingAuthorization.java +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/AggregatingAuthorization.java @@ -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 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 index 000000000..1f2d2156b --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiAuthorization.java @@ -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 index 000000000..0db368efe --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiGroup.java @@ -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 index 000000000..b2a18c8fe --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiRole.java @@ -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 index 000000000..14d4a9ddf --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/CmsOsgiUser.java @@ -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 { + +} diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/DirectoryUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/DirectoryUserAdmin.java index 03f17e61f..e5fb01242 100644 --- a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/DirectoryUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/DirectoryUserAdmin.java @@ -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 getAllRoles(CmsUser user) { - List allRoles = new ArrayList(); + protected List getAllRoles(CmsOsgiUser user) { + List allRoles = new ArrayList(); 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 allRoles) { + private void collectRoles(LdapEntry user, List allRoles) { List 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 allRoles) { + private void collectAnonymousRoles(List allRoles) { // TODO gather anonymous roles } @@ -184,23 +184,23 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm return res.toArray(new Role[res.size()]); } - List getRoles(LdapName searchBase, String filter, boolean deep) throws InvalidSyntaxException { + List getRoles(LdapName searchBase, String filter, boolean deep) throws InvalidSyntaxException { LdapEntryWorkingCopy wc = getWorkingCopy(); // Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null; List searchRes = getDirectoryDao().doGetEntries(searchBase, filter, deep); - List res = new ArrayList<>(); + List res = new ArrayList<>(); for (LdapEntry entry : searchRes) - res.add((CmsUser) entry); + res.add((CmsOsgiUser) entry); if (wc != null) { - for (Iterator it = res.iterator(); it.hasNext();) { - CmsUser user = (CmsUser) it.next(); + for (Iterator 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 collectedUsers = new ArrayList(); + List 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 collectedUsers) { + protected void doGetUser(String key, String value, List collectedUsers) { String f = "(" + key + "=" + value + ")"; List 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 allRoles = new ArrayList(); - collectRoles((LdapEntry) user, allRoles); + if (isExternal(userName) && user instanceof LdapEntry ldapEntry) { + List 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 getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) { + public Iterable getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) { LdapName dn = LdapNameUtils.toLdapName(hierarchyUnit.getBase()); try { return getRoles(dn, filter, deep); diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifAuthorization.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifAuthorization.java index a54050bc6..59e5df931 100644 --- a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifAuthorization.java +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifAuthorization.java @@ -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 allRoles; - public LdifAuthorization(User user, List allRoles) { + public LdifAuthorization(User user, List allRoles) { if (user == null) { this.name = null; this.displayName = "anonymous"; diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifGroup.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifGroup.java index 99aca1f2f..fd6651499 100644 --- a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifGroup.java +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifGroup.java @@ -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 directMembers = new ArrayList(); + Set 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 getDirectMembers() { + return doGetDirectMembers(); + } + + protected Set doGetDirectMembers() { + Set 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 null. */ - 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 diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifUser.java b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifUser.java index e48869a01..de383bde8 100644 --- a/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifUser.java +++ b/org.argeo.cms/src/org/argeo/cms/osgi/useradmin/LdifUser.java @@ -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; + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/util/LangUtils.java b/org.argeo.cms/src/org/argeo/cms/util/LangUtils.java index e4cc607d6..67748ccd7 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/LangUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/util/LangUtils.java @@ -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 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 map(String key, Object value) { -// assert key != null; -// HashMap 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() {