X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;ds=inline;f=org.argeo.util%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FLdifUserAdmin.java;h=26d3d134c511561016333f9273458967d7446fc9;hb=d74f9b604d0132a6b66c7a2dc189be2c2798b7c4;hp=8b1206a72b1655b38c6f111e8bd335dc954222ff;hpb=b71546ddc74d6ca49d252806aafd491c75dfe1fb;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.util/src/org/argeo/osgi/useradmin/LdifUserAdmin.java b/org.argeo.util/src/org/argeo/osgi/useradmin/LdifUserAdmin.java index 8b1206a72..26d3d134c 100644 --- a/org.argeo.util/src/org/argeo/osgi/useradmin/LdifUserAdmin.java +++ b/org.argeo.util/src/org/argeo/osgi/useradmin/LdifUserAdmin.java @@ -16,25 +16,32 @@ import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; import java.util.List; +import java.util.NavigableMap; +import java.util.Objects; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import javax.naming.NameNotFoundException; import javax.naming.NamingEnumeration; +import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.ldap.LdapName; -import org.argeo.util.naming.LdifParser; -import org.argeo.util.naming.LdifWriter; +import org.argeo.util.naming.LdapObjs; +import org.argeo.util.naming.ldap.LdifParser; +import org.argeo.util.naming.ldap.LdifWriter; import org.osgi.framework.Filter; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; /** A user admin based on a LDIF files. */ public class LdifUserAdmin extends AbstractUserDirectory { - private SortedMap users = new TreeMap(); - private SortedMap groups = new TreeMap(); + private NavigableMap users = new TreeMap<>(); + private NavigableMap groups = new TreeMap<>(); + + private NavigableMap hierarchy = new TreeMap<>(); +// private List rootHierarchyUnits = new ArrayList<>(); public LdifUserAdmin(String uri, String baseDn) { this(fromUri(uri, baseDn), false); @@ -64,15 +71,15 @@ public class LdifUserAdmin extends AbstractUserDirectory { char[] password = DigestUtils.bytesToChars(pwd); User directoryUser = (User) getRole(username); if (!directoryUser.hasCredential(null, password)) - throw new UserDirectoryException("Invalid credentials"); + throw new IllegalStateException("Invalid credentials"); } else { - throw new UserDirectoryException("Password is required"); + throw new IllegalStateException("Password is required"); } Dictionary properties = cloneProperties(); properties.put(UserAdminConf.readOnly.name(), "true"); LdifUserAdmin scopedUserAdmin = new LdifUserAdmin(properties, true); - scopedUserAdmin.groups = Collections.unmodifiableSortedMap(groups); - scopedUserAdmin.users = Collections.unmodifiableSortedMap(users); + scopedUserAdmin.groups = Collections.unmodifiableNavigableMap(groups); + scopedUserAdmin.users = Collections.unmodifiableNavigableMap(users); return scopedUserAdmin; } @@ -93,26 +100,28 @@ public class LdifUserAdmin extends AbstractUserDirectory { return; } load(u.toURL().openStream()); - } catch (Exception e) { - throw new UserDirectoryException("Cannot open URL " + getUri(), e); + } catch (IOException | URISyntaxException e) { + throw new IllegalStateException("Cannot open URL " + getUri(), e); } } public void save() { if (getUri() == null) - throw new UserDirectoryException("Cannot save LDIF user admin: no URI is set"); + throw new IllegalStateException("Cannot save LDIF user admin: no URI is set"); if (isReadOnly()) - throw new UserDirectoryException("Cannot save LDIF user admin: " + getUri() + " is read-only"); + throw new IllegalStateException("Cannot save LDIF user admin: " + getUri() + " is read-only"); try (FileOutputStream out = new FileOutputStream(new File(new URI(getUri())))) { save(out); } catch (IOException | URISyntaxException e) { - throw new UserDirectoryException("Cannot save user admin to " + getUri(), e); + throw new IllegalStateException("Cannot save user admin to " + getUri(), e); } } public void save(OutputStream out) throws IOException { try { LdifWriter ldifWriter = new LdifWriter(out); + for (LdapName name : hierarchy.keySet()) + ldifWriter.writeEntry(name, hierarchy.get(name).getAttributes()); for (LdapName name : groups.keySet()) ldifWriter.writeEntry(name, groups.get(name).getAttributes()); for (LdapName name : users.keySet()) @@ -126,6 +135,7 @@ public class LdifUserAdmin extends AbstractUserDirectory { try { users.clear(); groups.clear(); + hierarchy.clear(); LdifParser ldifParser = new LdifParser(); SortedMap allEntries = ldifParser.read(in); @@ -137,7 +147,7 @@ public class LdifUserAdmin extends AbstractUserDirectory { while (ids.hasMoreElements()) { String id = ids.nextElement().toLowerCase(); if (lowerCase.contains(id)) - throw new UserDirectoryException(key + " has duplicate id " + id); + throw new IllegalStateException(key + " has duplicate id " + id); lowerCase.add(id); } @@ -148,26 +158,55 @@ public class LdifUserAdmin extends AbstractUserDirectory { String objectClass = objectClasses.next().toString(); // System.out.println(" " + objectClass); if (objectClass.toLowerCase().equals(inetOrgPerson.name().toLowerCase())) { - users.put(key, new LdifUser(this, key, attributes)); + users.put(key, newUser(key, attributes)); break objectClasses; } else if (objectClass.toLowerCase().equals(getGroupObjectClass().toLowerCase())) { - groups.put(key, new LdifGroup(this, key, attributes)); + groups.put(key, newGroup(key, attributes)); + break objectClasses; +// } else if (objectClass.equalsIgnoreCase(LdapObjs.organization.name())) { +// // we only consider organizations which are not groups +// hierarchy.put(key, new LdifHierarchyUnit(this, key, HierarchyUnit.ORGANIZATION, attributes)); +// break objectClasses; + } else if (objectClass.equalsIgnoreCase(LdapObjs.organizationalUnit.name())) { +// String name = key.getRdn(key.size() - 1).toString(); +// if (getUserBase().equalsIgnoreCase(name) || getGroupBase().equalsIgnoreCase(name)) +// break objectClasses; // skip + // TODO skip if it does not contain groups or users + hierarchy.put(key, new LdifHierarchyUnit(this, key, attributes)); break objectClasses; } } } - } catch (Exception e) { - throw new UserDirectoryException("Cannot load user admin service from LDIF", e); + + // link hierarchy +// hierachyUnits: for (LdapName dn : hierarchy.keySet()) { +// LdifHierarchyUnit unit = hierarchy.get(dn); +// LdapName parentDn = (LdapName) dn.getPrefix(dn.size() - 1); +// LdifHierarchyUnit parent = hierarchy.get(parentDn); +// if (parent == null) { +// rootHierarchyUnits.add(unit); +// unit.parent = null; +// continue hierachyUnits; +// } +// parent.children.add(unit); +// unit.parent = parent; +// } + } catch (NamingException | IOException e) { + throw new IllegalStateException("Cannot load user admin service from LDIF", e); } } public void destroy() { if (users == null || groups == null) - throw new UserDirectoryException("User directory " + getBaseDn() + " is already destroyed"); + throw new IllegalStateException("User directory " + getBaseDn() + " is already destroyed"); users = null; groups = null; } + /* + * USER ADMIN + */ + @Override protected DirectoryUser daoGetRole(LdapName key) throws NameNotFoundException { if (groups.containsKey(key)) @@ -182,21 +221,35 @@ public class LdifUserAdmin extends AbstractUserDirectory { return users.containsKey(dn) || groups.containsKey(dn); } - protected List doGetRoles(Filter f) { + @Override + protected List doGetRoles(LdapName searchBase, Filter f, boolean deep) { + Objects.requireNonNull(searchBase); ArrayList res = new ArrayList(); - if (f == null) { + if (f == null && deep && getBaseDn().equals(searchBase)) { res.addAll(users.values()); res.addAll(groups.values()); } else { - for (DirectoryUser user : users.values()) { - if (f.match(user.getProperties())) + filterRoles(users, searchBase, f, deep, res); + filterRoles(groups, searchBase, f, deep, res); + } + return res; + } + + private void filterRoles(SortedMap map, LdapName searchBase, Filter f, + boolean deep, List res) { + // TODO reduce map with search base ? + roles: for (DirectoryUser user : map.values()) { + LdapName dn = user.getDn(); + if (dn.startsWith(searchBase)) { + if (!deep && dn.size() != (searchBase.size() + 1)) + continue roles; + if (f == null) + res.add(user); + else if (f.match(user.getProperties())) res.add(user); } - for (DirectoryUser group : groups.values()) - if (f.match(group.getProperties())) - res.add(group); } - return res; + } @Override @@ -211,50 +264,102 @@ public class LdifUserAdmin extends AbstractUserDirectory { } @Override - protected void prepare(UserDirectoryWorkingCopy wc) { + public void prepare(DirectoryUserWorkingCopy wc) { // delete - for (LdapName dn : wc.getDeletedUsers().keySet()) { + for (LdapName dn : wc.getDeletedData().keySet()) { if (users.containsKey(dn)) users.remove(dn); else if (groups.containsKey(dn)) groups.remove(dn); else - throw new UserDirectoryException("User to delete not found " + dn); + throw new IllegalStateException("User to delete not found " + dn); } // add - for (LdapName dn : wc.getNewUsers().keySet()) { - DirectoryUser user = wc.getNewUsers().get(dn); + for (LdapName dn : wc.getNewData().keySet()) { + DirectoryUser user = wc.getNewData().get(dn); if (users.containsKey(dn) || groups.containsKey(dn)) - throw new UserDirectoryException("User to create found " + dn); + throw new IllegalStateException("User to create found " + dn); else 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); + throw new IllegalStateException("Unsupported role type " + user.getType() + " for new user " + dn); } // modify - for (LdapName dn : wc.getModifiedUsers().keySet()) { - Attributes modifiedAttrs = wc.getModifiedUsers().get(dn); + for (LdapName dn : wc.getModifiedData().keySet()) { + Attributes modifiedAttrs = wc.getModifiedData().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); + throw new IllegalStateException("User to modify no found " + dn); user.publishAttributes(modifiedAttrs); } } @Override - protected void commit(UserDirectoryWorkingCopy wc) { + public void commit(DirectoryUserWorkingCopy wc) { save(); } @Override - protected void rollback(UserDirectoryWorkingCopy wc) { + public void rollback(DirectoryUserWorkingCopy wc) { init(); } + /* + * HIERARCHY + */ + +// @Override +// public int getHierarchyChildCount() { +// return rootHierarchyUnits.size(); +// } +// +// @Override +// public HierarchyUnit getHierarchyChild(int i) { +// return rootHierarchyUnits.get(i); +// } + @Override + protected HierarchyUnit doGetHierarchyUnit(LdapName dn) { + return hierarchy.get(dn); + } + + @Override + protected Iterable doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) { + List res = new ArrayList<>(); + for (LdapName n : hierarchy.keySet()) { + if (n.size() == searchBase.size() + 1) { + if (n.startsWith(searchBase)) { + HierarchyUnit hu = hierarchy.get(n); + if (functionalOnly) { + if (hu.isFunctional()) + res.add(hu); + } else { + res.add(hu); + } + } + } + } + return res; + } + +// @Override +// public Iterable getDirectHierarchyUnits(boolean functionalOnly) { +// if (functionalOnly) { +// List res = new ArrayList<>(); +// for (HierarchyUnit hu : rootHierarchyUnits) { +// if (hu.isFunctional()) +// res.add(hu); +// } +// return res; +// +// } else { +// return rootHierarchyUnits; +// } +// } + }