package org.argeo.osgi.useradmin; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.useradmin.Authorization; import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; /** * Aggregates multiple {@link UserDirectory} and integrates them with system * roles. */ public class AggregatingUserAdmin implements UserAdmin { private final LdapName systemRolesBaseDn; private final LdapName tokensBaseDn; // DAOs private AbstractUserDirectory systemRoles = null; private AbstractUserDirectory tokens = null; private Map businessRoles = new HashMap(); public AggregatingUserAdmin(String systemRolesBaseDn, String tokensBaseDn) { try { this.systemRolesBaseDn = new LdapName(systemRolesBaseDn); if (tokensBaseDn != null) this.tokensBaseDn = new LdapName(tokensBaseDn); else this.tokensBaseDn = null; } catch (InvalidNameException e) { throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin.class, e); } } @Override public Role createRole(String name, int type) { return findUserAdmin(name).createRole(name, type); } @Override public boolean removeRole(String name) { boolean actuallyDeleted = findUserAdmin(name).removeRole(name); systemRoles.removeRole(name); return actuallyDeleted; } @Override public Role getRole(String name) { return findUserAdmin(name).getRole(name); } @Override public Role[] getRoles(String filter) throws InvalidSyntaxException { List res = new ArrayList(); for (UserAdmin userAdmin : businessRoles.values()) { res.addAll(Arrays.asList(userAdmin.getRoles(filter))); } res.addAll(Arrays.asList(systemRoles.getRoles(filter))); return res.toArray(new Role[res.size()]); } @Override public User getUser(String key, String value) { List res = new ArrayList(); for (UserAdmin userAdmin : businessRoles.values()) { User u = userAdmin.getUser(key, value); if (u != null) res.add(u); } // Note: node roles cannot contain users, so it is not searched return res.size() == 1 ? res.get(0) : null; } @Override public Authorization getAuthorization(User user) { if (user == null) {// anonymous return systemRoles.getAuthorization(null); } UserAdmin userAdmin = findUserAdmin(user.getName()); Authorization rawAuthorization = userAdmin.getAuthorization(user); String usernameToUse; String displayNameToUse; if (user instanceof Group) { String ownerDn = TokenUtils.userDn((Group) user); if (ownerDn != null) {// tokens UserAdmin ownerUserAdmin = findUserAdmin(ownerDn); User ownerUser = (User) ownerUserAdmin.getRole(ownerDn); usernameToUse = ownerDn; displayNameToUse = LdifAuthorization.extractDisplayName(ownerUser); } else { usernameToUse = rawAuthorization.getName(); displayNameToUse = rawAuthorization.toString(); } } else {// regular users usernameToUse = rawAuthorization.getName(); displayNameToUse = rawAuthorization.toString(); } // gather system roles Set sysRoles = new HashSet(); for (String role : rawAuthorization.getRoles()) { Authorization auth = systemRoles.getAuthorization((User) userAdmin.getRole(role)); systemRoles: for (String systemRole : auth.getRoles()) { if (role.equals(systemRole)) continue systemRoles; sysRoles.add(systemRole); } // sysRoles.addAll(Arrays.asList(auth.getRoles())); } addAbstractSystemRoles(rawAuthorization, sysRoles); Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles, rawAuthorization.getRoles()); return authorization; } /** * Enrich with application-specific roles which are strictly programmatic, such * as anonymous/user semantics. */ protected void addAbstractSystemRoles(Authorization rawAuthorization, Set sysRoles) { } // // USER ADMIN AGGREGATOR // protected void addUserDirectory(AbstractUserDirectory userDirectory) { LdapName baseDn = userDirectory.getBaseDn(); if (isSystemRolesBaseDn(baseDn)) { this.systemRoles = userDirectory; systemRoles.setExternalRoles(this); } else if (isTokensBaseDn(baseDn)) { this.tokens = userDirectory; tokens.setExternalRoles(this); } else { if (businessRoles.containsKey(baseDn)) throw new UserDirectoryException("There is already a user admin for " + baseDn); businessRoles.put(baseDn, userDirectory); } userDirectory.init(); postAdd(userDirectory); } /** Called after a new user directory has been added */ protected void postAdd(AbstractUserDirectory userDirectory) { } private UserAdmin findUserAdmin(String name) { try { UserAdmin userAdmin = findUserAdmin(new LdapName(name)); return userAdmin; } catch (InvalidNameException e) { throw new UserDirectoryException("Badly formatted name " + name, e); } } private UserAdmin findUserAdmin(LdapName name) { if (name.startsWith(systemRolesBaseDn)) return systemRoles; if (tokensBaseDn != null && name.startsWith(tokensBaseDn)) return tokens; List res = new ArrayList<>(1); userDirectories: for (LdapName baseDn : businessRoles.keySet()) { AbstractUserDirectory userDirectory = businessRoles.get(baseDn); if (name.startsWith(baseDn)) { if (userDirectory.isDisabled()) continue userDirectories; // if (res.isEmpty()) { res.add(userDirectory); // } else { // for (AbstractUserDirectory ud : res) { // LdapName bd = ud.getBaseDn(); // if (userDirectory.getBaseDn().startsWith(bd)) { // // child user directory // } // } // } } } if (res.size() == 0) throw new UserDirectoryException("Cannot find user admin for " + name); if (res.size() > 1) throw new UserDirectoryException("Multiple user admin found for " + name); return res.get(0); } protected boolean isSystemRolesBaseDn(LdapName baseDn) { return baseDn.equals(systemRolesBaseDn); } protected boolean isTokensBaseDn(LdapName baseDn) { return tokensBaseDn != null && baseDn.equals(tokensBaseDn); } // protected Dictionary currentState() { // Dictionary res = new Hashtable(); // // res.put(NodeConstants.CN, NodeConstants.DEFAULT); // for (LdapName name : businessRoles.keySet()) { // AbstractUserDirectory userDirectory = businessRoles.get(name); // String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString(); // res.put(uri, ""); // } // return res; // } public void destroy() { for (LdapName name : businessRoles.keySet()) { AbstractUserDirectory userDirectory = businessRoles.get(name); destroy(userDirectory); } businessRoles.clear(); businessRoles = null; destroy(systemRoles); systemRoles = null; } private void destroy(AbstractUserDirectory userDirectory) { preDestroy(userDirectory); userDirectory.destroy(); } protected void removeUserDirectory(LdapName baseDn) { if (isSystemRolesBaseDn(baseDn)) throw new UserDirectoryException("System roles cannot be removed "); if (!businessRoles.containsKey(baseDn)) throw new UserDirectoryException("No user directory registered for " + baseDn); AbstractUserDirectory userDirectory = businessRoles.remove(baseDn); destroy(userDirectory); } /** * Called before each user directory is destroyed, so that additional actions * can be performed. */ protected void preDestroy(AbstractUserDirectory userDirectory) { } }