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<LdapName, DirectoryUser> users = new TreeMap<LdapName, DirectoryUser>();
- private SortedMap<LdapName, DirectoryGroup> groups = new TreeMap<LdapName, DirectoryGroup>();
+ private NavigableMap<LdapName, DirectoryUser> users = new TreeMap<>();
+ private NavigableMap<LdapName, DirectoryGroup> groups = new TreeMap<>();
+
+ private NavigableMap<LdapName, LdifHierarchyUnit> hierarchy = new TreeMap<>();
+// private List<HierarchyUnit> rootHierarchyUnits = new ArrayList<>();
public LdifUserAdmin(String uri, String baseDn) {
this(fromUri(uri, baseDn), false);
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<String, Object> 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;
}
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())
try {
users.clear();
groups.clear();
+ hierarchy.clear();
LdifParser ldifParser = new LdifParser();
SortedMap<LdapName, Attributes> allEntries = ldifParser.read(in);
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);
}
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))
return users.containsKey(dn) || groups.containsKey(dn);
}
- protected List<DirectoryUser> doGetRoles(Filter f) {
+ @Override
+ protected List<DirectoryUser> doGetRoles(LdapName searchBase, Filter f, boolean deep) {
+ Objects.requireNonNull(searchBase);
ArrayList<DirectoryUser> res = new ArrayList<DirectoryUser>();
- 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<LdapName, ? extends DirectoryUser> map, LdapName searchBase, Filter f,
+ boolean deep, List<DirectoryUser> 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
}
@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<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+ List<HierarchyUnit> 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<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
+// if (functionalOnly) {
+// List<HierarchyUnit> res = new ArrayList<>();
+// for (HierarchyUnit hu : rootHierarchyUnits) {
+// if (hu.isFunctional())
+// res.add(hu);
+// }
+// return res;
+//
+// } else {
+// return rootHierarchyUnits;
+// }
+// }
+
}