X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FLdifUser.java;h=cd5401a55794273ffd350c9e341d025d4bd6425c;hb=25071ab6bcb2df1fa4057c2c04137f2d606772e7;hp=379ac23ab2ca6349203655b318b4166efc8e620d;hpb=3439a3b6aba14618b06c72cf59b220e216135c96;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java index 379ac23ab..cd5401a55 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUser.java @@ -1,24 +1,44 @@ package org.argeo.osgi.useradmin; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Iterator; import java.util.List; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; import javax.naming.ldap.LdapName; -import org.osgi.service.useradmin.User; - -class LdifUser implements User { - // optimisation - List directMemberOf = new ArrayList(); +class LdifUser implements DirectoryUser { + private final AbstractUserDirectory userAdmin; private final LdapName dn; - private Attributes attributes; - LdifUser(LdapName dn, Attributes attributes) { + private final boolean frozen; + private Attributes publishedAttributes; + private Attributes modifiedAttributes = null; + + private final AttributeDictionary properties; + private final AttributeDictionary credentials; + + LdifUser(AbstractUserDirectory userAdmin, LdapName dn, Attributes attributes) { + this(userAdmin, dn, attributes, false); + } + + private LdifUser(AbstractUserDirectory userAdmin, LdapName dn, + Attributes attributes, boolean frozen) { + this.userAdmin = userAdmin; this.dn = dn; - this.attributes = attributes; + this.publishedAttributes = attributes; + properties = new AttributeDictionary(false); + credentials = new AttributeDictionary(true); + this.frozen = frozen; } @Override @@ -33,30 +53,60 @@ class LdifUser implements User { @Override public Dictionary getProperties() { - if (attributes == null) - throw new ArgeoUserAdminException( - "Must be loaded from user admin service"); - return new AttributeDictionary(attributes); + return properties; } @Override public Dictionary getCredentials() { - // TODO Auto-generated method stub - return null; + return credentials; } @Override public boolean hasCredential(String key, Object value) { - // TODO Auto-generated method stub + Object storedValue = getCredentials().get(key); + if (storedValue == null || value == null) + return false; + if (!(value instanceof String || value instanceof byte[])) + return false; + if (storedValue instanceof String && value instanceof String) + return storedValue.equals(value); + if (storedValue instanceof byte[] && value instanceof byte[]) + return Arrays.equals((byte[]) storedValue, (byte[]) value); return false; } - protected LdapName getDn() { + @Override + public LdapName getDn() { return dn; } - protected Attributes getAttributes() { - return attributes; + @Override + public synchronized Attributes getAttributes() { + return isEditing() ? modifiedAttributes : publishedAttributes; + } + + protected synchronized boolean isEditing() { + return userAdmin.isEditing() && modifiedAttributes != null; + } + + protected synchronized void startEditing() { + if (frozen) + throw new UserDirectoryException("Cannot edit frozen view"); + if (getUserAdmin().isReadOnly()) + throw new UserDirectoryException("User directory is read-only"); + assert modifiedAttributes == null; + modifiedAttributes = (Attributes) publishedAttributes.clone(); + } + + protected synchronized void stopEditing(boolean apply) { + assert modifiedAttributes != null; + if (apply) + publishedAttributes = modifiedAttributes; + modifiedAttributes = null; + } + + public DirectoryUser getPublished() { + return new LdifUser(userAdmin, dn, publishedAttributes, true); } @Override @@ -80,4 +130,139 @@ class LdifUser implements User { return dn.toString(); } + protected AbstractUserDirectory getUserAdmin() { + return userAdmin; + } + + private class AttributeDictionary extends Dictionary { + private final List effectiveKeys = new ArrayList(); + private final List attrFilter; + private final Boolean includeFilter; + + public AttributeDictionary(Boolean includeFilter) { + this.attrFilter = userAdmin.getCredentialAttributeIds(); + this.includeFilter = includeFilter; + try { + NamingEnumeration ids = getAttributes().getIDs(); + while (ids.hasMore()) { + String id = ids.next(); + if (includeFilter && attrFilter.contains(id)) + effectiveKeys.add(id); + else if (!includeFilter && !attrFilter.contains(id)) + effectiveKeys.add(id); + } + } catch (NamingException e) { + throw new UserDirectoryException( + "Cannot initialise attribute dictionary", e); + } + } + + @Override + public int size() { + return effectiveKeys.size(); + } + + @Override + public boolean isEmpty() { + return effectiveKeys.size() == 0; + } + + @Override + public Enumeration keys() { + return Collections.enumeration(effectiveKeys); + } + + @Override + public Enumeration elements() { + final Iterator it = effectiveKeys.iterator(); + return new Enumeration() { + + @Override + public boolean hasMoreElements() { + return it.hasNext(); + } + + @Override + public Object nextElement() { + String key = it.next(); + try { + return getAttributes().get(key).get(); + } catch (NamingException e) { + throw new UserDirectoryException( + "Cannot get value for key " + key, e); + } + } + + }; + } + + @Override + public Object get(Object key) { + try { + Attribute attr = getAttributes().get(key.toString()); + if (attr == null) + return null; + return attr.get(); + } catch (NamingException e) { + throw new UserDirectoryException( + "Cannot get value for attribute " + key, e); + } + } + + @Override + public Object put(String key, Object value) { + userAdmin.checkEdit(); + if (!isEditing()) + startEditing(); + + if (!(value instanceof String || value instanceof byte[])) + throw new IllegalArgumentException( + "Value must be String or byte[]"); + + if (includeFilter && !attrFilter.contains(key)) + throw new IllegalArgumentException("Key " + key + + " not included"); + else if (!includeFilter && attrFilter.contains(key)) + throw new IllegalArgumentException("Key " + key + " excluded"); + + try { + Attribute attribute = modifiedAttributes.get(key.toString()); + attribute = new BasicAttribute(key.toString()); + attribute.add(value); + Attribute previousAttribute = modifiedAttributes.put(attribute); + if (previousAttribute != null) + return previousAttribute.get(); + else + return null; + } catch (NamingException e) { + throw new UserDirectoryException( + "Cannot get value for attribute " + key, e); + } + } + + @Override + public Object remove(Object key) { + userAdmin.checkEdit(); + if (!isEditing()) + startEditing(); + + if (includeFilter && !attrFilter.contains(key)) + throw new IllegalArgumentException("Key " + key + + " not included"); + else if (!includeFilter && attrFilter.contains(key)) + throw new IllegalArgumentException("Key " + key + " excluded"); + + try { + Attribute attr = modifiedAttributes.remove(key.toString()); + if (attr != null) + return attr.get(); + else + return null; + } catch (NamingException e) { + throw new UserDirectoryException("Cannot remove attribute " + + key, e); + } + } + } + }