X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fauth%2FCmsUserManagerImpl.java;h=dfb0a56a27a554691706907b22f014f22a63ff23;hb=e9d0731a65b0d3523906c58f987ad9610c4286b7;hp=109a0d4066e65561a76d4801f3ed035989a685ff;hpb=b7c2f2cc2f6f74762031567e9e636ff277ebc7c7;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java index 109a0d406..dfb0a56a2 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java @@ -1,8 +1,8 @@ package org.argeo.cms.internal.auth; -import static org.argeo.naming.LdapAttrs.cn; -import static org.argeo.naming.LdapAttrs.description; -import static org.argeo.naming.LdapAttrs.owner; +import static org.argeo.util.naming.LdapAttrs.cn; +import static org.argeo.util.naming.LdapAttrs.description; +import static org.argeo.util.naming.LdapAttrs.owner; import java.time.ZoneOffset; import java.time.ZonedDateTime; @@ -13,30 +13,30 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NavigableMap; import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.UUID; -import javax.jcr.Node; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.security.auth.Subject; -import javax.transaction.Status; -import javax.transaction.UserTransaction; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsLog; import org.argeo.cms.CmsUserManager; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.jcr.JcrUtils; -import org.argeo.naming.LdapAttrs; -import org.argeo.naming.NamingUtils; -import org.argeo.naming.SharedSecret; -import org.argeo.node.NodeConstants; +import org.argeo.osgi.useradmin.AggregatingUserAdmin; import org.argeo.osgi.useradmin.TokenUtils; -import org.argeo.osgi.useradmin.UserAdminConf; +import org.argeo.osgi.useradmin.UserDirectory; +import org.argeo.util.directory.DirectoryConf; +import org.argeo.util.directory.ldap.SharedSecret; +import org.argeo.util.naming.LdapAttrs; +import org.argeo.util.naming.NamingUtils; +import org.argeo.util.transaction.WorkTransaction; import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; import org.osgi.service.useradmin.Authorization; import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; @@ -56,13 +56,24 @@ import org.osgi.service.useradmin.UserAdmin; * */ public class CmsUserManagerImpl implements CmsUserManager { - private final static Log log = LogFactory.getLog(CmsUserManagerImpl.class); + private final static CmsLog log = CmsLog.getLog(CmsUserManagerImpl.class); private UserAdmin userAdmin; - @Deprecated - private ServiceReference userAdminServiceReference; - private Map serviceProperties; - private UserTransaction userTransaction; +// private Map serviceProperties; + private WorkTransaction userTransaction; + +// private Map> userDirectories = Collections +// .synchronizedMap(new LinkedHashMap<>()); + + private Set userDirectories = new HashSet<>(); + + public void start() { + log.debug(() -> "CMS user manager available"); + } + + public void stop() { + + } @Override public String getMyMail() { @@ -151,7 +162,7 @@ public class CmsUserManagerImpl implements CmsUserManager { List users = new ArrayList(); for (Role role : roles) { if ((includeUsers && role.getType() == Role.USER || role.getType() == Role.GROUP) && !users.contains(role) - && (includeSystemRoles || !role.getName().toLowerCase().endsWith(NodeConstants.ROLES_BASEDN))) { + && (includeSystemRoles || !role.getName().toLowerCase().endsWith(CmsConstants.ROLES_BASEDN))) { if (match(role, filter)) users.add((User) role); } @@ -204,36 +215,59 @@ public class CmsUserManagerImpl implements CmsUserManager { + dns.keySet().toString() + ". Unable to chose a default one."); } +// public Map getKnownBaseDns(boolean onlyWritable) { +// Map dns = new HashMap(); +// String[] propertyKeys = serviceProperties.keySet().toArray(new String[serviceProperties.size()]); +// for (String uri : propertyKeys) { +// if (!uri.startsWith("/")) +// continue; +// Dictionary props = UserAdminConf.uriAsProperties(uri); +// String readOnly = UserAdminConf.readOnly.getValue(props); +// String baseDn = UserAdminConf.baseDn.getValue(props); +// +// if (onlyWritable && "true".equals(readOnly)) +// continue; +// if (baseDn.equalsIgnoreCase(NodeConstants.ROLES_BASEDN)) +// continue; +// if (baseDn.equalsIgnoreCase(NodeConstants.TOKENS_BASEDN)) +// continue; +// dns.put(baseDn, uri); +// } +// return dns; +// } + public Map getKnownBaseDns(boolean onlyWritable) { Map dns = new HashMap(); - String[] propertyKeys = userAdminServiceReference != null ? userAdminServiceReference.getPropertyKeys() - : serviceProperties.keySet().toArray(new String[serviceProperties.size()]); - for (String uri : propertyKeys) { - if (!uri.startsWith("/")) - continue; - Dictionary props = UserAdminConf.uriAsProperties(uri); - String readOnly = UserAdminConf.readOnly.getValue(props); - String baseDn = UserAdminConf.baseDn.getValue(props); + for (UserDirectory userDirectory : userDirectories) { + Boolean readOnly = userDirectory.isReadOnly(); + String baseDn = userDirectory.getContext(); - if (onlyWritable && "true".equals(readOnly)) + if (onlyWritable && readOnly) continue; - if (baseDn.equalsIgnoreCase(NodeConstants.ROLES_BASEDN)) + if (baseDn.equalsIgnoreCase(CmsConstants.ROLES_BASEDN)) continue; - if (baseDn.equalsIgnoreCase(NodeConstants.TOKENS_BASEDN)) + if (baseDn.equalsIgnoreCase(CmsConstants.TOKENS_BASEDN)) continue; - dns.put(baseDn, uri); + dns.put(baseDn, DirectoryConf.propertiesAsUri(userDirectory.getProperties()).toString()); + } return dns; } + public Set getUserDirectories() { + TreeSet res = new TreeSet<>((o1, o2) -> o1.getContext().compareTo(o2.getContext())); + res.addAll(userDirectories); + return res; + } + public String buildDistinguishedName(String localId, String baseDn, int type) { Map dns = getKnownBaseDns(true); - Dictionary props = UserAdminConf.uriAsProperties(dns.get(baseDn)); + Dictionary props = DirectoryConf.uriAsProperties(dns.get(baseDn)); String dn = null; if (Role.GROUP == type) - dn = LdapAttrs.cn.name() + "=" + localId + "," + UserAdminConf.groupBase.getValue(props) + "," + baseDn; + dn = LdapAttrs.cn.name() + "=" + localId + "," + DirectoryConf.groupBase.getValue(props) + "," + baseDn; else if (Role.USER == type) - dn = LdapAttrs.uid.name() + "=" + localId + "," + UserAdminConf.userBase.getValue(props) + "," + baseDn; + dn = LdapAttrs.uid.name() + "=" + localId + "," + DirectoryConf.userBase.getValue(props) + "," + baseDn; else throw new IllegalStateException("Unknown role type. " + "Cannot deduce dn for " + localId); return dn; @@ -332,7 +366,7 @@ public class CmsUserManagerImpl implements CmsUserManager { return tokenStr; } catch (Exception e1) { try { - if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION) + if (!userTransaction.isNoTransactionStatus()) userTransaction.rollback(); } catch (Exception e2) { if (log.isTraceEnabled()) @@ -346,7 +380,7 @@ public class CmsUserManagerImpl implements CmsUserManager { public void expireAuthToken(String token) { try { userTransaction.begin(); - String dn = cn + "=" + token + "," + NodeConstants.TOKENS_BASEDN; + String dn = cn + "=" + token + "," + CmsConstants.TOKENS_BASEDN; Group tokenGroup = (Group) userAdmin.getRole(dn); String ldapDate = NamingUtils.instantToLdapDate(ZonedDateTime.now(ZoneOffset.UTC)); tokenGroup.getProperties().put(description.name(), ldapDate); @@ -355,7 +389,7 @@ public class CmsUserManagerImpl implements CmsUserManager { log.debug("Token " + token + " expired."); } catch (Exception e1) { try { - if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION) + if (!userTransaction.isNoTransactionStatus()) userTransaction.rollback(); } catch (Exception e2) { if (log.isTraceEnabled()) @@ -367,38 +401,44 @@ public class CmsUserManagerImpl implements CmsUserManager { @Override public void expireAuthTokens(Subject subject) { - Set tokens = TokenUtils.tokensUsed(subject, NodeConstants.TOKENS_BASEDN); + Set tokens = TokenUtils.tokensUsed(subject, CmsConstants.TOKENS_BASEDN); for (String token : tokens) expireAuthToken(token); } @Override public void addAuthToken(String userDn, String token, Integer hours, String... roles) { + addAuthToken(userDn, token, ZonedDateTime.now().plusHours(hours), roles); + } + + @Override + public void addAuthToken(String userDn, String token, ZonedDateTime expiryDate, String... roles) { try { userTransaction.begin(); User user = (User) userAdmin.getRole(userDn); - String tokenDn = cn + "=" + token + "," + NodeConstants.TOKENS_BASEDN; + String tokenDn = cn + "=" + token + "," + CmsConstants.TOKENS_BASEDN; Group tokenGroup = (Group) userAdmin.createRole(tokenDn, Role.GROUP); - for (String role : roles) { - Role r = userAdmin.getRole(role); - if (r != null) - tokenGroup.addMember(r); - else { - if (!role.equals(NodeConstants.ROLE_USER)) { - throw new IllegalStateException( - "Cannot add role " + role + " to token " + token + " for " + userDn); + if (roles != null) + for (String role : roles) { + Role r = userAdmin.getRole(role); + if (r != null) + tokenGroup.addMember(r); + else { + if (!role.equals(CmsConstants.ROLE_USER)) { + throw new IllegalStateException( + "Cannot add role " + role + " to token " + token + " for " + userDn); + } } } - } tokenGroup.getProperties().put(owner.name(), user.getName()); - if (hours != null) { - String ldapDate = NamingUtils.instantToLdapDate(ZonedDateTime.now().plusHours(hours)); + if (expiryDate != null) { + String ldapDate = NamingUtils.instantToLdapDate(expiryDate); tokenGroup.getProperties().put(description.name(), ldapDate); } userTransaction.commit(); } catch (Exception e1) { try { - if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION) + if (!userTransaction.isNoTransactionStatus()) userTransaction.rollback(); } catch (Exception e2) { if (log.isTraceEnabled()) @@ -408,52 +448,82 @@ public class CmsUserManagerImpl implements CmsUserManager { } } - public User createUserFromPerson(Node person) { - String email = JcrUtils.get(person, LdapAttrs.mail.property()); - String dn = buildDefaultDN(email, Role.USER); - User user; - try { - userTransaction.begin(); - user = (User) userAdmin.createRole(dn, Role.USER); - Dictionary userProperties = user.getProperties(); - String name = JcrUtils.get(person, LdapAttrs.displayName.property()); - userProperties.put(LdapAttrs.cn.name(), name); - userProperties.put(LdapAttrs.displayName.name(), name); - String givenName = JcrUtils.get(person, LdapAttrs.givenName.property()); - String surname = JcrUtils.get(person, LdapAttrs.sn.property()); - userProperties.put(LdapAttrs.givenName.name(), givenName); - userProperties.put(LdapAttrs.sn.name(), surname); - userProperties.put(LdapAttrs.mail.name(), email.toLowerCase()); - userTransaction.commit(); - } catch (Exception e) { - try { - userTransaction.rollback(); - } catch (Exception e1) { - log.error("Could not roll back", e1); + @Override + public UserDirectory getDirectory(Role user) { + String name = user.getName(); + NavigableMap possible = new TreeMap<>(); + for (UserDirectory userDirectory : userDirectories) { + if (name.endsWith(userDirectory.getContext())) { + possible.put(userDirectory.getContext(), userDirectory); } - if (e instanceof RuntimeException) - throw (RuntimeException) e; - else - throw new RuntimeException("Cannot create user", e); } - return user; + if (possible.size() == 0) + throw new IllegalStateException("No user directory found for user " + name); + return possible.lastEntry().getValue(); } +// public User createUserFromPerson(Node person) { +// String email = JcrUtils.get(person, LdapAttrs.mail.property()); +// String dn = buildDefaultDN(email, Role.USER); +// User user; +// try { +// userTransaction.begin(); +// user = (User) userAdmin.createRole(dn, Role.USER); +// Dictionary userProperties = user.getProperties(); +// String name = JcrUtils.get(person, LdapAttrs.displayName.property()); +// userProperties.put(LdapAttrs.cn.name(), name); +// userProperties.put(LdapAttrs.displayName.name(), name); +// String givenName = JcrUtils.get(person, LdapAttrs.givenName.property()); +// String surname = JcrUtils.get(person, LdapAttrs.sn.property()); +// userProperties.put(LdapAttrs.givenName.name(), givenName); +// userProperties.put(LdapAttrs.sn.name(), surname); +// userProperties.put(LdapAttrs.mail.name(), email.toLowerCase()); +// userTransaction.commit(); +// } catch (Exception e) { +// try { +// userTransaction.rollback(); +// } catch (Exception e1) { +// log.error("Could not roll back", e1); +// } +// if (e instanceof RuntimeException) +// throw (RuntimeException) e; +// else +// throw new RuntimeException("Cannot create user", e); +// } +// return user; +// } + public UserAdmin getUserAdmin() { return userAdmin; } - public UserTransaction getUserTransaction() { - return userTransaction; - } +// public UserTransaction getUserTransaction() { +// return userTransaction; +// } /* DEPENDENCY INJECTION */ - public void setUserAdmin(UserAdmin userAdmin, Map serviceProperties) { + public void setUserAdmin(UserAdmin userAdmin) { this.userAdmin = userAdmin; - this.serviceProperties = serviceProperties; + + if (userAdmin instanceof AggregatingUserAdmin) { + userDirectories = ((AggregatingUserAdmin) userAdmin).getUserDirectories(); + } else { + throw new IllegalArgumentException("Only " + AggregatingUserAdmin.class.getName() + " is supported."); + } + +// this.serviceProperties = serviceProperties; } - public void setUserTransaction(UserTransaction userTransaction) { + public void setUserTransaction(WorkTransaction userTransaction) { this.userTransaction = userTransaction; } + +// public void addUserDirectory(UserDirectory userDirectory, Map properties) { +// userDirectories.put(userDirectory, new Hashtable<>(properties)); +// } +// +// public void removeUserDirectory(UserDirectory userDirectory, Map properties) { +// userDirectories.remove(userDirectory); +// } + }