Multiple user referentials working with IPA.
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / osgi / useradmin / AggregatingUserAdmin.java
index c1727f7465d2e4fbdde2bdeea3671cc51da90fc0..c9479d51cd40ad7703bd0b9db09a42fc73951fe1 100644 (file)
@@ -6,14 +6,17 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
 
 import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
 
+import org.argeo.util.directory.DirectoryConf;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.useradmin.Authorization;
 import org.osgi.service.useradmin.Group;
@@ -86,6 +89,7 @@ public class AggregatingUserAdmin implements UserAdmin {
                return res.size() == 1 ? res.get(0) : null;
        }
 
+       /** Builds an authorisation by scanning all referentials. */
        @Override
        public Authorization getAuthorization(User user) {
                if (user == null) {// anonymous
@@ -114,25 +118,25 @@ public class AggregatingUserAdmin implements UserAdmin {
                }
 
                // gather roles from other referentials
-               List<String> allRoles = new ArrayList<>(Arrays.asList(rawAuthorization.getRoles()));
+               List<String> rawRoles = Arrays.asList(rawAuthorization.getRoles());
+               List<String> allRoles = new ArrayList<>(rawRoles);
                for (LdapName otherBaseDn : businessRoles.keySet()) {
                        if (otherBaseDn.equals(userReferentialOfThisUser.getBaseDn()))
                                continue;
-                       DirectoryUserAdmin otherUserAdmin = businessRoles.get(otherBaseDn);
-                       Authorization auth = otherUserAdmin.getAuthorization(retrievedUser);
-                       allRoles.addAll(Arrays.asList(auth.getRoles()));
+                       DirectoryUserAdmin otherUserAdmin = userAdminToUse(user, businessRoles.get(otherBaseDn));
+                       if (otherUserAdmin == null)
+                               continue;
+                       for (String roleStr : rawRoles) {
+                               User role = (User) findUserAdmin(roleStr).getRole(roleStr);
+                               Authorization auth = otherUserAdmin.getAuthorization(role);
+                               allRoles.addAll(Arrays.asList(auth.getRoles()));
+                       }
 
                }
 
                // integrate system roles
-               final DirectoryUserAdmin userAdminToUse;// possibly scoped when authenticating
-               if (user instanceof DirectoryUser) {
-                       userAdminToUse = userReferentialOfThisUser;
-               } else if (user instanceof AuthenticatingUser) {
-                       userAdminToUse = (DirectoryUserAdmin) userReferentialOfThisUser.scope(user);
-               } else {
-                       throw new IllegalArgumentException("Unsupported user type " + user.getClass());
-               }
+               final DirectoryUserAdmin userAdminToUse = userAdminToUse(retrievedUser, userReferentialOfThisUser);
+               Objects.requireNonNull(userAdminToUse);
 
                try {
                        Set<String> sysRoles = new HashSet<String>();
@@ -157,6 +161,20 @@ public class AggregatingUserAdmin implements UserAdmin {
                }
        }
 
+       /** Decide whether to scope or not */
+       private DirectoryUserAdmin userAdminToUse(User user, DirectoryUserAdmin userAdmin) {
+               if (userAdmin.isAuthenticated())
+                       return userAdmin;
+               if (user instanceof DirectoryUser) {
+                       return userAdmin;
+               } else if (user instanceof AuthenticatingUser) {
+                       return userAdmin.scope(user).orElse(null);
+               } else {
+                       throw new IllegalArgumentException("Unsupported user type " + user.getClass());
+               }
+
+       }
+
        /**
         * Enrich with application-specific roles which are strictly programmatic, such
         * as anonymous/user semantics.
@@ -172,7 +190,7 @@ public class AggregatingUserAdmin implements UserAdmin {
                if (!(ud instanceof DirectoryUserAdmin))
                        throw new IllegalArgumentException("Only " + DirectoryUserAdmin.class.getName() + " is supported");
                DirectoryUserAdmin userDirectory = (DirectoryUserAdmin) ud;
-               String basePath = userDirectory.getContext();
+               String basePath = userDirectory.getBase();
                if (isSystemRolesBaseDn(basePath)) {
                        this.systemRoles = userDirectory;
                        systemRoles.setExternalRoles(this);
@@ -251,7 +269,12 @@ public class AggregatingUserAdmin implements UserAdmin {
 //     }
 
        public void start() {
-
+               if (systemRoles == null) {
+                       // TODO do we really need separate system roles?
+                       Hashtable<String, Object> properties = new Hashtable<>();
+                       properties.put(DirectoryConf.baseDn.name(), "ou=roles,ou=system");
+                       systemRoles = new DirectoryUserAdmin(properties);
+               }
        }
 
        public void stop() {
@@ -296,7 +319,7 @@ public class AggregatingUserAdmin implements UserAdmin {
        }
 
        public Set<UserDirectory> getUserDirectories() {
-               TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getContext().compareTo(o2.getContext()));
+               TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getBase().compareTo(o2.getBase()));
                res.addAll(businessRoles.values());
                res.add(systemRoles);
                return res;