X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FLdifUserAdmin.java;h=dacae7964f1ee74a24415529655fbd7940133a44;hb=e86e3691db8b4a426a6d5fd3cf255dc82fe05fc1;hp=440e93d9d1f3fc9fcb3b28049ec69609a795376a;hpb=3439a3b6aba14618b06c72cf59b220e216135c96;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java index 440e93d9d..dacae7964 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java @@ -1,32 +1,77 @@ package org.argeo.osgi.useradmin; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.naming.InvalidNameException; import javax.naming.NamingEnumeration; import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttributes; import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.useradmin.Authorization; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -public class LdifUserAdmin implements UserAdmin { +/** User admin implementation using LDIF file(s) as backend. */ +public class LdifUserAdmin extends AbstractLdapUserAdmin { SortedMap users = new TreeMap(); SortedMap groups = new TreeMap(); + private Map> userIndexes = new LinkedHashMap>(); + + public LdifUserAdmin(String uri) { + this(uri, true); + } + + public LdifUserAdmin(String uri, boolean isReadOnly) { + setReadOnly(isReadOnly); + try { + setUri(new URI(uri)); + } catch (URISyntaxException e) { + throw new ArgeoUserAdminException("Invalid URI " + uri, e); + } + + if (!isReadOnly && !getUri().getScheme().equals("file:")) + throw new UnsupportedOperationException(getUri().getScheme() + + "not supported read-write."); + + } + public LdifUserAdmin(InputStream in) { + load(in); + setReadOnly(true); + setUri(null); + } + + public void init() { + try { + load(getUri().toURL().openStream()); + } catch (Exception e) { + throw new ArgeoUserAdminException("Cannot open URL " + getUri(), e); + } + } + + protected void load(InputStream in) { try { LdifParser ldifParser = new LdifParser(); SortedMap allEntries = ldifParser.read(in); for (LdapName key : allEntries.keySet()) { Attributes attributes = allEntries.get(key); - NamingEnumeration objectClasses = attributes.get("objectClass") - .getAll(); + NamingEnumeration objectClasses = attributes.get( + "objectClass").getAll(); objectClasses: while (objectClasses.hasMore()) { String objectClass = objectClasses.next().toString(); if (objectClass.equals("inetOrgPerson")) { @@ -40,15 +85,41 @@ public class LdifUserAdmin implements UserAdmin { } // optimise - for (LdifGroup group : groups.values()) { - group.loadMembers(this); + for (LdifGroup group : groups.values()) + loadMembers(group); + + // indexes + for (String attr : getIndexedUserProperties()) + userIndexes.put(attr, new TreeMap()); + + for (LdifUser user : users.values()) { + Dictionary properties = user.getProperties(); + for (String attr : getIndexedUserProperties()) { + Object value = properties.get(attr); + if (value != null) { + LdifUser otherUser = userIndexes.get(attr).put( + value.toString(), user); + if (otherUser != null) + throw new ArgeoUserAdminException("User " + user + + " and user " + otherUser + + " both have property " + attr + + " set to " + value); + } + } } } catch (Exception e) { throw new ArgeoUserAdminException( - "Cannot initialise user admin service from LDIF", e); + "Cannot load user admin service from LDIF", e); } } + public void destroy() { + users.clear(); + users = null; + groups.clear(); + groups = null; + } + @Override public Role getRole(String name) { LdapName key; @@ -74,22 +145,132 @@ public class LdifUserAdmin implements UserAdmin { @Override public Role createRole(String name, int type) { - throw new UnsupportedOperationException(); + try { + LdapName dn = new LdapName(name); + if (users.containsKey(dn) || groups.containsKey(dn)) + throw new ArgeoUserAdminException("Already a role " + name); + + BasicAttributes attrs = new BasicAttributes(); + attrs.put("dn", dn.toString()); + Rdn nameRdn = dn.getRdn(dn.size() - 1); + // TODO deal with multiple attr RDN + attrs.put(nameRdn.getType(), nameRdn.getValue()); + LdifUser newRole; + if (type == Role.USER) { + newRole = new LdifUser(dn, attrs); + users.put(dn, newRole); + } else if (type == Role.GROUP) { + newRole = new LdifGroup(dn, attrs); + groups.put(dn, (LdifGroup) newRole); + } else + throw new ArgeoUserAdminException("Unsupported type " + type); + return newRole; + } catch (InvalidNameException e) { + throw new ArgeoUserAdminException("Cannot create role " + name, e); + } } @Override public boolean removeRole(String name) { - throw new UnsupportedOperationException(); + try { + LdapName dn = new LdapName(name); + LdifUser role = null; + if (users.containsKey(dn)) + role = users.remove(dn); + else if (groups.containsKey(dn)) + role = groups.remove(dn); + else + throw new ArgeoUserAdminException("There is no role " + name); + if (role == null) + return false; + for (LdifGroup group : role.directMemberOf) { + group.directMembers.remove(role); + group.getAttributes().get(group.getMemberAttrName()) + .remove(dn.toString()); + } + if (role instanceof LdifGroup) { + LdifGroup group = (LdifGroup) role; + for (Role user : group.directMembers) { + if (user instanceof LdifUser) + ((LdifUser) user).directMemberOf.remove(group); + } + } + return true; + } catch (InvalidNameException e) { + throw new ArgeoUserAdminException("Cannot create role " + name, e); + } } @Override public Role[] getRoles(String filter) throws InvalidSyntaxException { - throw new UnsupportedOperationException(); + ArrayList res = new ArrayList(); + if (filter == null) { + res.addAll(users.values()); + res.addAll(groups.values()); + } else { + Filter f = FrameworkUtil.createFilter(filter); + for (LdifUser user : users.values()) + if (f.match(user.getProperties())) + res.add(user); + for (LdifUser group : groups.values()) + if (f.match(group.getProperties())) + res.add(group); + } + return res.toArray(new Role[res.size()]); } @Override public User getUser(String key, String value) { - throw new UnsupportedOperationException(); + // TODO check value null or empty + if (key != null) { + if (!userIndexes.containsKey(key)) + return null; + return userIndexes.get(key).get(value); + } + + // Try all indexes + List collectedUsers = new ArrayList( + getIndexedUserProperties().size()); + // try dn + LdifUser user = null; + try { + user = (LdifUser) getRole(value); + if (user != null) + collectedUsers.add(user); + } catch (Exception e) { + // silent + } + for (String attr : userIndexes.keySet()) { + user = userIndexes.get(attr).get(value); + if (user != null) + collectedUsers.add(user); + } + + if (collectedUsers.size() == 1) + return collectedUsers.get(0); + return null; + // throw new UnsupportedOperationException(); + } + + protected void loadMembers(LdifGroup group) { + group.directMembers = new ArrayList(); + for (LdapName ldapName : group.getMemberNames()) { + LdifUser role = null; + if (groups.containsKey(ldapName)) + role = groups.get(ldapName); + else if (users.containsKey(ldapName)) + role = users.get(ldapName); + else { + if (getExternalRoles() != null) + role = (LdifUser) getExternalRoles().getRole( + ldapName.toString()); + if (role == null) + throw new ArgeoUserAdminException("No role found for " + + ldapName); + } + role.directMemberOf.add(group); + group.directMembers.add(role); + } } }