X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FLdifUserAdmin.java;h=4613ef5289fbb331ecc61e8d982c93c6d3e41c87;hb=ea63d7d123a50ff10657946ce3d928a57944621d;hp=acbf1112f1e24d92b35926420aabc538406ecf5c;hpb=062d7f43d0208823ac81160c517ab6a2d7404765;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 acbf1112f..4613ef528 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,71 +1,99 @@ package org.argeo.osgi.useradmin; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; +import java.io.OutputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.Dictionary; -import java.util.LinkedHashMap; +import java.util.Hashtable; 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.ldap.LdapName; +import javax.transaction.TransactionManager; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.service.useradmin.Authorization; +import org.apache.commons.io.IOUtils; +import org.osgi.framework.Filter; import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -/** User admin implementation using LDIF file(s) as backend. */ -public class LdifUserAdmin implements UserAdmin { - SortedMap users = new TreeMap(); - SortedMap groups = new TreeMap(); +/** + * A user admin based on a LDIF files. Requires a {@link TransactionManager} and + * an open transaction for write access. + */ +public class LdifUserAdmin extends AbstractUserDirectory { + private SortedMap users = new TreeMap(); + private SortedMap groups = new TreeMap(); - private final boolean isReadOnly; - private final URI uri; - - private List indexedUserProperties = Arrays.asList(new String[] { - "uid", "mail", "cn" }); - private Map> userIndexes = new LinkedHashMap>(); + public LdifUserAdmin(String uri, String baseDn) { + this(fromUri(uri, baseDn)); + } - public LdifUserAdmin(String uri) { - this(uri, true); + public LdifUserAdmin(Dictionary properties) { + super(properties); } - public LdifUserAdmin(String uri, boolean isReadOnly) { - this.isReadOnly = isReadOnly; - try { - this.uri = new URI(uri); - } catch (URISyntaxException e) { - throw new ArgeoUserAdminException("Invalid URI " + uri, e); - } + public LdifUserAdmin(InputStream in) { + super(new Hashtable()); + load(in); + } - if (!isReadOnly && !this.uri.getScheme().equals("file:")) - throw new UnsupportedOperationException(this.uri.getScheme() - + "not supported read-write."); + private static Dictionary fromUri(String uri, String baseDn) { + Hashtable res = new Hashtable(); + res.put(UserAdminConf.uri.property(), uri); + res.put(UserAdminConf.baseDn.property(), baseDn); + return res; + } + public void init() { try { - load(this.uri.toURL().openStream()); + if (getUri().getScheme().equals("file")) { + File file = new File(getUri()); + if (!file.exists()) + return; + } + load(getUri().toURL().openStream()); } catch (Exception e) { - throw new ArgeoUserAdminException("Cannot open URL " + this.uri, e); + throw new UserDirectoryException("Cannot open URL " + getUri(), e); } } - public LdifUserAdmin(InputStream in) { - load(in); - isReadOnly = true; - this.uri = null; + public void save() { + if (getUri() == null) + throw new UserDirectoryException( + "Cannot save LDIF user admin: no URI is set"); + if (isReadOnly()) + throw new UserDirectoryException("Cannot save LDIF user admin: " + + getUri() + " is read-only"); + try (FileOutputStream out = new FileOutputStream(new File(getUri()))) { + save(out); + } catch (IOException e) { + throw new UserDirectoryException("Cannot save user admin to " + + getUri(), e); + } + } + + public void save(OutputStream out) throws IOException { + try { + LdifWriter ldifWriter = new LdifWriter(out); + for (LdapName name : groups.keySet()) + ldifWriter.writeEntry(name, groups.get(name).getAttributes()); + for (LdapName name : users.keySet()) + ldifWriter.writeEntry(name, users.get(name).getAttributes()); + } finally { + IOUtils.closeQuietly(out); + } } protected void load(InputStream in) { try { + users.clear(); + groups.clear(); + LdifParser ldifParser = new LdifParser(); SortedMap allEntries = ldifParser.read(in); for (LdapName key : allEntries.keySet()) { @@ -75,40 +103,16 @@ public class LdifUserAdmin implements UserAdmin { objectClasses: while (objectClasses.hasMore()) { String objectClass = objectClasses.next().toString(); if (objectClass.equals("inetOrgPerson")) { - users.put(key, new LdifUser(key, attributes)); + users.put(key, new LdifUser(this, key, attributes)); break objectClasses; } else if (objectClass.equals("groupOfNames")) { - groups.put(key, new LdifGroup(key, attributes)); + groups.put(key, new LdifGroup(this, key, attributes)); break objectClasses; } } } - - // optimise - for (LdifGroup group : groups.values()) - group.loadMembers(this); - - // indexes - for (String attr : indexedUserProperties) - userIndexes.put(attr, new TreeMap()); - - for (LdifUser user : users.values()) { - Dictionary properties = user.getProperties(); - for (String attr : indexedUserProperties) { - 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 habe property " + attr - + " set to " + value); - } - } - } } catch (Exception e) { - throw new ArgeoUserAdminException( + throw new UserDirectoryException( "Cannot load user admin service from LDIF", e); } } @@ -120,17 +124,7 @@ public class LdifUserAdmin implements UserAdmin { groups = null; } - @Override - public Role getRole(String name) { - LdapName key; - try { - key = new LdapName(name); - } catch (InvalidNameException e) { - // TODO implements default base DN - throw new IllegalArgumentException("Badly formatted role name: " - + name, e); - } - + protected DirectoryUser daoGetRole(LdapName key) { if (groups.containsKey(key)) return groups.get(key); if (users.containsKey(key)) @@ -138,67 +132,85 @@ public class LdifUserAdmin implements UserAdmin { return null; } - @Override - public Authorization getAuthorization(User user) { - return new LdifAuthorization((LdifUser) user); - } - - @Override - public Role createRole(String name, int type) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeRole(String name) { - throw new UnsupportedOperationException(); + protected Boolean daoHasRole(LdapName dn) { + return users.containsKey(dn) || groups.containsKey(dn); } - @Override - public Role[] getRoles(String filter) throws InvalidSyntaxException { - if (filter == null) { - ArrayList res = new ArrayList(); + @SuppressWarnings("unchecked") + protected List doGetRoles(Filter f) { + ArrayList res = new ArrayList(); + if (f == null) { res.addAll(users.values()); res.addAll(groups.values()); - return res.toArray(new Role[res.size()]); + } else { + // Filter f = FrameworkUtil.createFilter(filter); + for (DirectoryUser user : users.values()) + if (f.match(user.getProperties())) + res.add(user); + for (DirectoryUser group : groups.values()) + if (f.match(group.getProperties())) + res.add(group); } - throw new UnsupportedOperationException(); + return res; } @Override - public User getUser(String key, String value) { - // TODO check value null or empty - if (key != null) { - if (!userIndexes.containsKey(key)) - return null; - return userIndexes.get(key).get(value); + protected List getDirectGroups(LdapName dn) { + List directGroups = new ArrayList(); + for (LdapName name : groups.keySet()) { + DirectoryGroup group = groups.get(name); + if (group.getMemberNames().contains(dn)) + directGroups.add(group.getDn()); } + return directGroups; + } - // Try all indexes - List collectedUsers = new ArrayList( - indexedUserProperties.size()); - // try dn - LdifUser user = null; - try { - user = (LdifUser) getRole(value); - if (user != null) - collectedUsers.add(user); - } catch (Exception e) { - // silent + @Override + protected void prepare(WorkingCopy wc) { + // delete + for (LdapName dn : wc.getDeletedUsers().keySet()) { + if (users.containsKey(dn)) + users.remove(dn); + else if (groups.containsKey(dn)) + groups.remove(dn); + else + throw new UserDirectoryException("User to delete no found " + + dn); } - for (String attr : userIndexes.keySet()) { - user = userIndexes.get(attr).get(value); - if (user != null) - collectedUsers.add(user); + // add + for (LdapName dn : wc.getNewUsers().keySet()) { + DirectoryUser user = wc.getNewUsers().get(dn); + if (Role.USER == user.getType()) + users.put(dn, user); + else if (Role.GROUP == user.getType()) + groups.put(dn, (DirectoryGroup) user); + else + throw new UserDirectoryException("Unsupported role type " + + user.getType() + " for new user " + dn); } + // modify + for (LdapName dn : wc.getModifiedUsers().keySet()) { + Attributes modifiedAttrs = wc.getModifiedUsers().get(dn); + DirectoryUser user; + if (users.containsKey(dn)) + user = users.get(dn); + else if (groups.containsKey(dn)) + user = groups.get(dn); + else + throw new UserDirectoryException("User to modify no found " + + dn); + user.publishAttributes(modifiedAttrs); + } + } - if (collectedUsers.size() == 1) - return collectedUsers.get(0); - return null; - // throw new UnsupportedOperationException(); + @Override + protected void commit(WorkingCopy wc) { + save(); } - public boolean getIsReadOnly() { - return isReadOnly; + @Override + protected void rollback(WorkingCopy wc) { + init(); } }