X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FAbstractUserDirectory.java;h=884e4ce09ff0ccd1e550f01fe3c402dadae12608;hb=268e023a9de5db2549431a4415e584ac68a4f98b;hp=d034e2233e90edfd4a55159dd39645042570f8ae;hpb=4fe1d843a422b0b616683c15b7b1cfb9c0538ee7;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index d034e2233..884e4ce09 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -1,8 +1,17 @@ package org.argeo.osgi.useradmin; +import static org.argeo.osgi.useradmin.LdifName.inetOrgPerson; +import static org.argeo.osgi.useradmin.LdifName.objectClass; +import static org.argeo.osgi.useradmin.LdifName.organizationalPerson; +import static org.argeo.osgi.useradmin.LdifName.person; +import static org.argeo.osgi.useradmin.LdifName.top; + +import java.io.File; import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Dictionary; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -17,7 +26,6 @@ import javax.naming.ldap.Rdn; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; -import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; @@ -28,42 +36,64 @@ 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.Group; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; -public abstract class AbstractUserDirectory implements UserAdmin { +/** Base class for a {@link UserDirectory}. */ +abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { private final static Log log = LogFactory .getLog(AbstractUserDirectory.class); + + private Dictionary properties; + private String baseDn = "dc=example,dc=com"; + private String userObjectClass; + private String groupObjectClass; + private boolean isReadOnly; private URI uri; private UserAdmin externalRoles; private List indexedUserProperties = Arrays.asList(new String[] { - "uid", "mail", "cn" }); + LdifName.uid.name(), LdifName.mail.name(), LdifName.cn.name() }); private String memberAttributeId = "member"; private List credentialAttributeIds = Arrays - .asList(new String[] { "userpassword" }); - - // private TransactionSynchronizationRegistry syncRegistry; - // private Object editingTransactionKey = null; + .asList(new String[] { LdifName.userpassword.name() }); private TransactionManager transactionManager; private ThreadLocal workingCopy = new ThreadLocal(); private Xid editingTransactionXid = null; - public AbstractUserDirectory() { - } + AbstractUserDirectory(Dictionary properties) { + // TODO make a copy? + this.properties = properties; - public AbstractUserDirectory(URI uri, boolean isReadOnly) { - this.uri = uri; - this.isReadOnly = isReadOnly; + String uriStr = UserAdminConf.uri.getValue(properties); + if (uriStr == null) + uri = null; + else + try { + uri = new URI(uriStr); + } catch (URISyntaxException e) { + throw new UserDirectoryException("Badly formatted URI", e); + } + + baseDn = UserAdminConf.baseDn.getValue(properties).toString(); + String isReadOnly = UserAdminConf.readOnly.getValue(properties); + if (isReadOnly == null) + this.isReadOnly = readOnlyDefault(uri); + else + this.isReadOnly = new Boolean(isReadOnly); + + this.userObjectClass = UserAdminConf.userObjectClass + .getValue(properties); + this.groupObjectClass = UserAdminConf.groupObjectClass + .getValue(properties); } - /** Returns the {@link Group}s this user is a direct member of. */ - protected abstract List getDirectGroups(User user); + /** Returns the groups this user is a direct member of. */ + protected abstract List getDirectGroups(LdapName dn); protected abstract Boolean daoHasRole(LdapName dn); @@ -71,9 +101,6 @@ public abstract class AbstractUserDirectory implements UserAdmin { protected abstract List doGetRoles(Filter f); - protected abstract void doGetUser(String key, String value, - List collectedUsers); - public void init() { } @@ -86,10 +113,6 @@ public abstract class AbstractUserDirectory implements UserAdmin { if (editingTransactionXid == null) return false; return workingCopy.get() != null; - // Object currentTrKey = syncRegistry.getTransactionKey(); - // if (currentTrKey == null) - // return false; - // return editingTransactionKey.equals(currentTrKey); } protected WorkingCopy getWorkingCopy() { @@ -133,7 +156,7 @@ public abstract class AbstractUserDirectory implements UserAdmin { } } - List getAllRoles(User user) { + List getAllRoles(DirectoryUser user) { List allRoles = new ArrayList(); if (user != null) { collectRoles(user, allRoles); @@ -143,9 +166,10 @@ public abstract class AbstractUserDirectory implements UserAdmin { return allRoles; } - private void collectRoles(User user, List allRoles) { - for (Group group : getDirectGroups(user)) { + private void collectRoles(DirectoryUser user, List allRoles) { + for (LdapName groupDn : getDirectGroups(user.getDn())) { // TODO check for loops + DirectoryUser group = doGetRole(groupDn); allRoles.add(group); collectRoles(group, allRoles); } @@ -158,18 +182,22 @@ public abstract class AbstractUserDirectory implements UserAdmin { // USER ADMIN @Override public Role getRole(String name) { - LdapName key = toDn(name); + return doGetRole(toDn(name)); + } + + protected DirectoryUser doGetRole(LdapName dn) { WorkingCopy wc = getWorkingCopy(); - DirectoryUser user = daoGetRole(key); + DirectoryUser user = daoGetRole(dn); if (wc != null) { - if (user == null && wc.getNewUsers().containsKey(key)) - user = wc.getNewUsers().get(key); - else if (wc.getDeletedUsers().containsKey(key)) + if (user == null && wc.getNewUsers().containsKey(dn)) + user = wc.getNewUsers().get(dn); + else if (wc.getDeletedUsers().containsKey(dn)) user = null; } return user; } + @SuppressWarnings("unchecked") @Override public Role[] getRoles(String filter) throws InvalidSyntaxException { WorkingCopy wc = getWorkingCopy(); @@ -218,6 +246,19 @@ public abstract class AbstractUserDirectory implements UserAdmin { return null; } + protected void doGetUser(String key, String value, + List collectedUsers) { + try { + Filter f = FrameworkUtil.createFilter("(&(" + objectClass + "=" + + getUserObjectClass() + ")(" + key + "=" + value + "))"); + List users = doGetRoles(f); + collectedUsers.addAll(users); + } catch (InvalidSyntaxException e) { + throw new UserDirectoryException("Cannot get user with " + key + + "=" + value, e); + } + } + @Override public Authorization getAuthorization(User user) { return new LdifAuthorization((DirectoryUser) user, @@ -250,18 +291,23 @@ public abstract class AbstractUserDirectory implements UserAdmin { protected DirectoryUser newRole(LdapName dn, int type, Attributes attrs) { LdifUser newRole; - BasicAttribute objectClass = new BasicAttribute("objectClass"); + BasicAttribute objClass = new BasicAttribute(objectClass.name()); if (type == Role.USER) { - objectClass.add("inetOrgPerson"); - objectClass.add("organizationalPerson"); - objectClass.add("person"); - objectClass.add("top"); - attrs.put(objectClass); + String userObjClass = getUserObjectClass(); + objClass.add(userObjClass); + if (inetOrgPerson.name().equals(userObjClass)) { + objClass.add(organizationalPerson.name()); + objClass.add(person.name()); + } else if (organizationalPerson.name().equals(userObjClass)) { + objClass.add(person.name()); + } + objClass.add(top); + attrs.put(objClass); newRole = new LdifUser(this, dn, attrs); } else if (type == Role.GROUP) { - objectClass.add("groupOfNames"); - objectClass.add("top"); - attrs.put(objectClass); + objClass.add(getGroupObjectClass()); + objClass.add(top); + attrs.put(objClass); newRole = new LdifGroup(this, dn, attrs); } else throw new UserDirectoryException("Unsupported type " + type); @@ -273,16 +319,20 @@ public abstract class AbstractUserDirectory implements UserAdmin { checkEdit(); WorkingCopy wc = getWorkingCopy(); LdapName dn = toDn(name); - if (!daoHasRole(dn) && !wc.getNewUsers().containsKey(dn)) - return false; - DirectoryUser user = (DirectoryUser) getRole(name); - wc.getDeletedUsers().put(dn, user); - // FIXME clarify directgroups - for (DirectoryGroup group : getDirectGroups(user)) { + boolean actuallyDeleted; + if (daoHasRole(dn) || wc.getNewUsers().containsKey(dn)) { + DirectoryUser user = (DirectoryUser) getRole(name); + wc.getDeletedUsers().put(dn, user); + actuallyDeleted = true; + } else {// just removing from groups (e.g. system roles) + actuallyDeleted = false; + } + for (LdapName groupDn : getDirectGroups(dn)) { + DirectoryUser group = doGetRole(groupDn); group.getAttributes().get(getMemberAttributeId()) .remove(dn.toString()); } - return true; + return actuallyDeleted; } // TRANSACTION @@ -337,6 +387,16 @@ public abstract class AbstractUserDirectory implements UserAdmin { this.isReadOnly = isReadOnly; } + private static boolean readOnlyDefault(URI uri) { + if (uri == null) + return true; + if (uri.getScheme().equals("file")) { + File file = new File(uri); + return !file.canWrite(); + } + return true; + } + public boolean isReadOnly() { return isReadOnly; } @@ -345,12 +405,24 @@ public abstract class AbstractUserDirectory implements UserAdmin { return externalRoles; } - public void setExternalRoles(UserAdmin externalRoles) { - this.externalRoles = externalRoles; + public String getBaseDn() { + return baseDn; + } + + protected String getUserObjectClass() { + return userObjectClass; + } + + protected String getGroupObjectClass() { + return groupObjectClass; } - public void setSyncRegistry(TransactionSynchronizationRegistry syncRegistry) { - // this.syncRegistry = syncRegistry; + public Dictionary getProperties() { + return properties; + } + + public void setExternalRoles(UserAdmin externalRoles) { + this.externalRoles = externalRoles; } public void setTransactionManager(TransactionManager transactionManager) {