Simplify LDAP directory.
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 23 Jun 2022 07:02:49 +0000 (09:02 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 23 Jun 2022 07:02:49 +0000 (09:02 +0200)
26 files changed:
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtTabularPart.java
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/Column.java
org.argeo.cms/src/org/argeo/cms/acr/directory/AbstractDirectoryContent.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContent.java
org.argeo.cms/src/org/argeo/cms/acr/directory/DirectoryContentProvider.java
org.argeo.cms/src/org/argeo/cms/acr/directory/HierarchyUnitContent.java
org.argeo.cms/src/org/argeo/cms/acr/directory/RoleContent.java
org.argeo.cms/src/org/argeo/cms/auth/UserAdminUtils.java
org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifGroup.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifUser.java
org.argeo.util/src/org/argeo/osgi/useradmin/OsUserDirectory.java
org.argeo.util/src/org/argeo/util/directory/Directory.java
org.argeo.util/src/org/argeo/util/directory/FunctionalGroup.java [deleted file]
org.argeo.util/src/org/argeo/util/directory/HierarchyUnit.java
org.argeo.util/src/org/argeo/util/directory/Organization.java [deleted file]
org.argeo.util/src/org/argeo/util/directory/Person.java [deleted file]
org.argeo.util/src/org/argeo/util/directory/SystemPermissions.java [deleted file]
org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapDirectory.java
org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapEntry.java [deleted file]
org.argeo.util/src/org/argeo/util/directory/ldap/DefaultLdapEntry.java [new file with mode: 0644]
org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java
org.argeo.util/src/org/argeo/util/directory/ldap/LdapDirectoryDao.java
org.argeo.util/src/org/argeo/util/directory/ldap/LdapEntry.java
org.argeo.util/src/org/argeo/util/directory/ldap/LdapHierarchyUnit.java
org.argeo.util/src/org/argeo/util/directory/ldap/LdifDao.java

index 9872551be31546742f86287f520442915c53f43f..af4c68aac9793ff8c8b4eb8199fd6cc1e9760caf 100644 (file)
@@ -2,12 +2,15 @@ package org.argeo.cms.swt.widgets;
 
 import java.util.function.Consumer;
 
+import org.argeo.api.cms.ux.CmsIcon;
+import org.argeo.cms.swt.CmsSwtTheme;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ux.widgets.Column;
 import org.argeo.cms.ux.widgets.TabularPart;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
@@ -22,7 +25,10 @@ public class SwtTabularPart implements TabularPart {
        private Consumer<Object> onSelected;
        private Consumer<Object> onAction;
 
+       private CmsSwtTheme theme;
+
        public SwtTabularPart(Composite parent, int style) {
+               theme = CmsSwtUtils.getCmsTheme(parent);
                area = new Composite(parent, style);
                area.setLayout(CmsSwtUtils.noSpaceGridLayout());
                table = new Table(area, SWT.VIRTUAL | SWT.BORDER);
@@ -46,18 +52,25 @@ public class SwtTabularPart implements TabularPart {
                        @Override
                        public void widgetSelected(SelectionEvent e) {
                                if (onSelected != null)
-                                       onSelected.accept(e.item.getData());
+                                       onSelected.accept(getDataFromEvent(e));
                        }
 
                        @Override
                        public void widgetDefaultSelected(SelectionEvent e) {
                                if (onAction != null)
-                                       onAction.accept(e.item.getData());
+                                       onAction.accept(getDataFromEvent(e));
                        }
                });
 
        }
 
+       protected Object getDataFromEvent(SelectionEvent e) {
+               Object data = e.item.getData();
+               if (data == null)
+                       data = getData(getTable().indexOf((TableItem) e.item));
+               return data;
+       }
+
        @Override
        public void setInput(Object data) {
                area.setData(data);
@@ -74,8 +87,14 @@ public class SwtTabularPart implements TabularPart {
                for (int i = 0; i < item.getParent().getColumnCount(); i++) {
                        Column<Object> column = (Column<Object>) item.getParent().getColumn(i).getData();
                        Object data = getData(row);
+                       item.setData(data);
                        String text = data != null ? column.getText(data) : "";
                        item.setText(i, text);
+                       CmsIcon icon = column.getIcon(data);
+                       if (icon != null) {
+                               Image image = theme.getSmallIcon(icon);
+                               item.setImage(i, image);
+                       }
                }
        }
 
index 9bfa9620a09fc563a411710c82c6e8d4c1c6981c..973fddb5a8504a070c2968fe2643e711de6181be 100644 (file)
@@ -1,10 +1,16 @@
 package org.argeo.cms.ux.widgets;
 
+import org.argeo.api.cms.ux.CmsIcon;
+
 public interface Column<T> {
        String getText(T model);
 
        default int getWidth() {
                return 200;
        }
-       
+
+       default CmsIcon getIcon(T model) {
+               return null;
+       }
+
 }
diff --git a/org.argeo.cms/src/org/argeo/cms/acr/directory/AbstractDirectoryContent.java b/org.argeo.cms/src/org/argeo/cms/acr/directory/AbstractDirectoryContent.java
new file mode 100644 (file)
index 0000000..62148b9
--- /dev/null
@@ -0,0 +1,96 @@
+package org.argeo.cms.acr.directory;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.ContentName;
+import org.argeo.api.acr.CrName;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.spi.ContentProvider;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.cms.acr.AbstractContent;
+import org.argeo.util.naming.LdapAttrs;
+import org.argeo.util.naming.LdapObjs;
+
+abstract class AbstractDirectoryContent extends AbstractContent {
+       protected final DirectoryContentProvider provider;
+
+       public AbstractDirectoryContent(ProvidedSession session, DirectoryContentProvider provider) {
+               super(session);
+               this.provider = provider;
+       }
+
+       abstract Dictionary<String, Object> doGetProperties();
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public <A> Optional<A> get(QName key, Class<A> clss) {
+               String attrName = key.getLocalPart();
+               Object value = doGetProperties().get(attrName);
+               if (value == null)
+                       return Optional.empty();
+               // TODO deal with type and multiple
+               return Optional.of((A) value);
+       }
+
+       @Override
+       protected Iterable<QName> keys() {
+               Dictionary<String, Object> properties = doGetProperties();
+               Set<QName> keys = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR);
+               keys: for (Enumeration<String> it = properties.keys(); it.hasMoreElements();) {
+                       String key = it.nextElement();
+                       if (key.equalsIgnoreCase(LdapAttrs.objectClass.name()))
+                               continue keys;
+                       if (key.equalsIgnoreCase(LdapAttrs.objectClasses.name()))
+                               continue keys;
+                       ContentName name = new ContentName(CrName.LDAP_NAMESPACE_URI, key, provider);
+                       keys.add(name);
+               }
+               return keys;
+       }
+
+       @Override
+       public List<QName> getTypes() {
+               Dictionary<String, Object> properties = doGetProperties();
+               List<QName> contentClasses = new ArrayList<>();
+               String objectClass = properties.get(LdapAttrs.objectClass.name()).toString();
+               contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, objectClass, provider));
+
+               String[] objectClasses = properties.get(LdapAttrs.objectClasses.name()).toString().split("\\n");
+               objectClasses: for (String oc : objectClasses) {
+                       if (LdapObjs.top.name().equalsIgnoreCase(oc))
+                               continue objectClasses;
+                       if (objectClass.equalsIgnoreCase(oc))
+                               continue objectClasses;
+                       contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, oc, provider));
+               }
+               return contentClasses;
+       }
+
+       @Override
+       public Object put(QName key, Object value) {
+               Object previous = get(key);
+               // TODO deal with typing
+               doGetProperties().put(key.getLocalPart(), value);
+               return previous;
+       }
+
+       @Override
+       protected void removeAttr(QName key) {
+               doGetProperties().remove(key.getLocalPart());
+       }
+
+       @Override
+       public ContentProvider getProvider() {
+               return provider;
+       }
+
+
+}
index e1ad96077e26bfc08925b69f8a9df6b41188f2c6..4e738ae2b8399e315d68a45816373191e34725b9 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.cms.acr.directory;
 
 import java.util.ArrayList;
+import java.util.Dictionary;
 import java.util.Iterator;
 import java.util.List;
 
@@ -8,25 +9,21 @@ import javax.xml.namespace.QName;
 
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentName;
-import org.argeo.api.acr.spi.ContentProvider;
 import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.cms.acr.AbstractContent;
 import org.argeo.util.directory.Directory;
 import org.argeo.util.directory.HierarchyUnit;
 
-class DirectoryContent extends AbstractContent {
+class DirectoryContent extends AbstractDirectoryContent {
        private Directory directory;
-       private DirectoryContentProvider provider;
 
        public DirectoryContent(ProvidedSession session, DirectoryContentProvider provider, Directory directory) {
-               super(session);
-               this.provider = provider;
+               super(session, provider);
                this.directory = directory;
        }
 
        @Override
-       public ContentProvider getProvider() {
-               return provider;
+       Dictionary<String, Object> doGetProperties() {
+               return directory.getProperties();
        }
 
        @Override
index f4afbdd538e7de7b12b93d0fa7bbb166873e01d3..f4a416aa7bdfefcf38faf4126f249c4bca3638c8 100644 (file)
@@ -110,6 +110,9 @@ public class DirectoryContentProvider implements ContentProvider {
                return new UserManagerContent(session);
        }
 
+       /*
+        * COMMON UTILITIES
+        */
        class UserManagerContent extends AbstractContent {
 
                public UserManagerContent(ProvidedSession session) {
index f6a0e3b5266d30f6f1d411e2dd6357a41a6fd644..9c1a480ba66f1a8de030558fbbc7393036f32f69 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.cms.acr.directory;
 
 import java.util.ArrayList;
+import java.util.Dictionary;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
@@ -10,29 +11,24 @@ import javax.xml.namespace.QName;
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentName;
 import org.argeo.api.acr.CrName;
-import org.argeo.api.acr.spi.ContentProvider;
 import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.cms.acr.AbstractContent;
 import org.argeo.osgi.useradmin.UserDirectory;
 import org.argeo.util.directory.HierarchyUnit;
 import org.osgi.service.useradmin.Role;
 
-class HierarchyUnitContent extends AbstractContent {
+class HierarchyUnitContent extends AbstractDirectoryContent {
        private HierarchyUnit hierarchyUnit;
 
-       private DirectoryContentProvider provider;
-
        public HierarchyUnitContent(ProvidedSession session, DirectoryContentProvider provider,
                        HierarchyUnit hierarchyUnit) {
-               super(session);
+               super(session, provider);
                Objects.requireNonNull(hierarchyUnit);
-               this.provider = provider;
                this.hierarchyUnit = hierarchyUnit;
        }
 
        @Override
-       public ContentProvider getProvider() {
-               return provider;
+       Dictionary<String, Object> doGetProperties() {
+               return hierarchyUnit.getProperties();
        }
 
        @Override
@@ -69,12 +65,19 @@ class HierarchyUnitContent extends AbstractContent {
        /*
         * TYPING
         */
-
        @Override
        public List<QName> getTypes() {
-               List<QName> res = new ArrayList<>();
-               res.add(CrName.COLLECTION.get());
-               return res;
+               List<QName> contentClasses = super.getTypes();
+               contentClasses.add(CrName.COLLECTION.get());
+               return contentClasses;
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public <A> A adapt(Class<A> clss) {
+               if (clss.equals(HierarchyUnit.class))
+                       return (A) hierarchyUnit;
+               return super.adapt(clss);
        }
 
        /*
index 2a22f023cb5795f40efa7545a8a83a4ef1ca6187..7aa144633689c5d668f1297aa4ad7be81db434ac 100644 (file)
@@ -1,45 +1,32 @@
 package org.argeo.cms.acr.directory;
 
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.Dictionary;
 
-import javax.swing.GroupLayout.Group;
 import javax.xml.namespace.QName;
 
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentName;
-import org.argeo.api.acr.CrName;
-import org.argeo.api.acr.NamespaceUtils;
-import org.argeo.api.acr.spi.ContentProvider;
 import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.cms.acr.AbstractContent;
 import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
+import org.osgi.service.useradmin.Group;
 import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 
-class RoleContent extends AbstractContent {
+class RoleContent extends AbstractDirectoryContent {
 
-       private DirectoryContentProvider provider;
        private HierarchyUnitContent parent;
        private Role role;
 
        public RoleContent(ProvidedSession session, DirectoryContentProvider provider, HierarchyUnitContent parent,
                        Role role) {
-               super(session);
-               this.provider = provider;
+               super(session, provider);
                this.parent = parent;
                this.role = role;
        }
 
        @Override
-       public ContentProvider getProvider() {
-               return provider;
+       Dictionary<String, Object> doGetProperties() {
+               return role.getProperties();
        }
 
        @Override
@@ -53,60 +40,6 @@ class RoleContent extends AbstractContent {
                return parent;
        }
 
-       @SuppressWarnings("unchecked")
-       @Override
-       public <A> Optional<A> get(QName key, Class<A> clss) {
-               String attrName = key.getLocalPart();
-               Object value = role.getProperties().get(attrName);
-               if (value == null)
-                       return Optional.empty();
-               // TODO deal with type and multiple
-               return Optional.of((A) value);
-       }
-
-       @Override
-       protected Iterable<QName> keys() {
-               Set<QName> keys = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR);
-               keys: for (Enumeration<String> it = role.getProperties().keys(); it.hasMoreElements();) {
-                       String key = it.nextElement();
-                       if (key.equalsIgnoreCase(LdapAttrs.objectClass.name()))
-                               continue keys;
-                       ContentName name = new ContentName(CrName.LDAP_NAMESPACE_URI, key, provider);
-                       keys.add(name);
-               }
-               return keys;
-       }
-
-       @Override
-       public List<QName> getTypes() {
-               List<QName> contentClasses = new ArrayList<>();
-               String objectClass = role.getProperties().get(LdapAttrs.objectClass.name()).toString();
-               contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, objectClass, provider));
-
-               String[] objectClasses = role.getProperties().get(LdapAttrs.objectClasses.name()).toString().split("\\n");
-               objectClasses: for (String oc : objectClasses) {
-                       if (LdapObjs.top.name().equalsIgnoreCase(oc))
-                               continue objectClasses;
-                       if (objectClass.equalsIgnoreCase(oc))
-                               continue objectClasses;
-                       contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, oc, provider));
-               }
-               return contentClasses;
-       }
-
-       @Override
-       public Object put(QName key, Object value) {
-               Object previous = get(key);
-               // TODO deal with typing
-               role.getProperties().put(key.getLocalPart(), value);
-               return previous;
-       }
-
-       @Override
-       protected void removeAttr(QName key) {
-               role.getProperties().remove(key.getLocalPart());
-       }
-
        @SuppressWarnings("unchecked")
        @Override
        public <A> A adapt(Class<A> clss) {
index eed38cc3285aa17de5ca6563f556c0f0e21027c3..5a365721136bc07a742d4a3128a996854650f323 100644 (file)
@@ -67,16 +67,17 @@ public class UserAdminUtils {
         */
        public static String getUserDisplayName(UserAdmin userAdmin, String dn) {
                Role user = userAdmin.getRole(dn);
-               String dName;
                if (user == null)
-                       dName = getUserLocalId(dn);
-               else {
-                       dName = getProperty(user, LdapAttrs.displayName.name());
-                       if (isEmpty(dName))
-                               dName = getProperty(user, LdapAttrs.cn.name());
-                       if (isEmpty(dName))
-                               dName = getUserLocalId(dn);
-               }
+                       return getUserLocalId(dn);
+               return getUserDisplayName(user);
+       }
+
+       public static String getUserDisplayName(Role user) {
+               String dName = getProperty(user, LdapAttrs.displayName.name());
+               if (isEmpty(dName))
+                       dName = getProperty(user, LdapAttrs.cn.name());
+               if (isEmpty(dName))
+                       dName = getUserLocalId(user.getName());
                return dName;
        }
 
index 9f6d62d7a64600e85224c717786c0379335868fe..6f12195dc3c1d6ea6c52b1b056b0fecafe512b0a 100644 (file)
@@ -30,7 +30,6 @@ import org.argeo.util.directory.ldap.LdapEntry;
 import org.argeo.util.directory.ldap.LdapEntryWorkingCopy;
 import org.argeo.util.directory.ldap.LdapNameUtils;
 import org.argeo.util.directory.ldap.LdifDao;
-import org.argeo.util.naming.LdapObjs;
 import org.osgi.framework.Filter;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
@@ -74,7 +73,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                String username = (String) credentials.get(SHARED_STATE_USERNAME);
                if (username == null)
                        username = user.getName();
-               Dictionary<String, Object> properties = cloneProperties();
+               Dictionary<String, Object> properties = cloneConfigProperties();
                properties.put(Context.SECURITY_PRINCIPAL, username.toString());
                Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
                byte[] pwd = (byte[]) pwdCred;
@@ -102,7 +101,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                } else {
                        throw new IllegalStateException("Password is required");
                }
-               Dictionary<String, Object> properties = cloneProperties();
+               Dictionary<String, Object> properties = cloneConfigProperties();
                properties.put(DirectoryConf.readOnly.name(), "true");
                DirectoryUserAdmin scopedUserAdmin = new DirectoryUserAdmin(null, properties, true);
 //             scopedUserAdmin.groups = Collections.unmodifiableNavigableMap(groups);
@@ -283,7 +282,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
                checkEdit();
                LdapEntryWorkingCopy wc = getWorkingCopy();
                LdapName dn = toLdapName(name);
-               if ((getDirectoryDao().daoHasEntry(dn) && !wc.getDeletedData().containsKey(dn))
+               if ((getDirectoryDao().entryExists(dn) && !wc.getDeletedData().containsKey(dn))
                                || wc.getNewData().containsKey(dn))
                        throw new IllegalArgumentException("Already a role " + name);
                BasicAttributes attrs = new BasicAttributes(true);
@@ -380,17 +379,11 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm
         */
        protected LdapEntry newUser(LdapName name, Attributes attrs) {
                // TODO support devices, applications, etc.
-               return new LdifUser.LdifPerson(this, name, attrs);
+               return new LdifUser(this, name, attrs);
        }
 
        protected LdapEntry newGroup(LdapName name, Attributes attrs) {
-               if (LdapNameUtils.getParentRdn(name).equals(getSystemRoleBaseRdn()))
-                       return new LdifGroup.LdifSystemPermissions(this, name, attrs);
-
-               if (hasObjectClass(attrs, LdapObjs.organization))
-                       return new LdifGroup.LdifOrganization(this, name, attrs);
-               else
-                       return new LdifGroup.LdifFunctionalGroup(this, name, attrs);
+               return new LdifGroup(this, name, attrs);
 
        }
 
index 7aad15a8c4d404453079b64e2da0dbc03d9816c1..2453fcb23a837d6f4d8d52dec9a404cc810a0bdf 100644 (file)
@@ -8,14 +8,11 @@ import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
 import javax.naming.ldap.LdapName;
 
-import org.argeo.util.directory.FunctionalGroup;
-import org.argeo.util.directory.Organization;
-import org.argeo.util.directory.SystemPermissions;
 import org.argeo.util.directory.ldap.AbstractLdapDirectory;
 import org.osgi.service.useradmin.Role;
 
 /** Directory group implementation */
-abstract class LdifGroup extends LdifUser implements DirectoryGroup {
+class LdifGroup extends LdifUser implements DirectoryGroup {
        private final String memberAttributeId;
 
        LdifGroup(AbstractLdapDirectory userAdmin, LdapName dn, Attributes attributes) {
@@ -125,30 +122,7 @@ abstract class LdifGroup extends LdifUser implements DirectoryGroup {
                return GROUP;
        }
 
-       /*
-        * KIND
-        */
-       static class LdifFunctionalGroup extends LdifGroup implements FunctionalGroup {
-
-               public LdifFunctionalGroup(DirectoryUserAdmin userAdmin, LdapName dn, Attributes attributes) {
-                       super(userAdmin, dn, attributes);
-               }
-
-       }
-
-       static class LdifOrganization extends LdifGroup implements Organization {
-
-               public LdifOrganization(DirectoryUserAdmin userAdmin, LdapName dn, Attributes attributes) {
-                       super(userAdmin, dn, attributes);
-               }
-
-       }
-
-       static class LdifSystemPermissions extends LdifGroup implements SystemPermissions {
-
-               public LdifSystemPermissions(DirectoryUserAdmin userAdmin, LdapName dn, Attributes attributes) {
-                       super(userAdmin, dn, attributes);
-               }
-
+       protected DirectoryUserAdmin getUserAdmin() {
+               return (DirectoryUserAdmin) getDirectory();
        }
 }
index cceb6e4611c92fa06530c73e34471726da24df23..11de4ed5697c511eacbfb0db76cf39c36c28bbfe 100644 (file)
@@ -1,44 +1,17 @@
 package org.argeo.osgi.useradmin;
 
-import static java.nio.charset.StandardCharsets.US_ASCII;
-
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.Collections;
 import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringJoiner;
 
-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.argeo.util.directory.DirectoryDigestUtils;
-import org.argeo.util.directory.Person;
 import org.argeo.util.directory.ldap.AbstractLdapDirectory;
-import org.argeo.util.directory.ldap.AbstractLdapEntry;
-import org.argeo.util.directory.ldap.AuthPassword;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
-import org.argeo.util.naming.SharedSecret;
+import org.argeo.util.directory.ldap.DefaultLdapEntry;
 
 /** Directory user implementation */
-abstract class LdifUser extends AbstractLdapEntry implements DirectoryUser {
-       private final AttributeDictionary properties;
-       private final AttributeDictionary credentials;
-
+class LdifUser extends DefaultLdapEntry implements DirectoryUser {
        LdifUser(AbstractLdapDirectory userAdmin, LdapName dn, Attributes attributes) {
                super(userAdmin, dn, attributes);
-               properties = new AttributeDictionary(false);
-               credentials = new AttributeDictionary(true);
        }
 
        @Override
@@ -51,316 +24,8 @@ abstract class LdifUser extends AbstractLdapEntry implements DirectoryUser {
                return USER;
        }
 
-       @Override
-       public Dictionary<String, Object> getProperties() {
-               return properties;
-       }
-
        @Override
        public Dictionary<String, Object> getCredentials() {
                return credentials;
        }
-
-       @Override
-       public boolean hasCredential(String key, Object value) {
-               if (key == null) {
-                       // TODO check other sources (like PKCS12)
-                       // String pwd = new String((char[]) value);
-                       // authPassword (RFC 312 https://tools.ietf.org/html/rfc3112)
-                       char[] password = DirectoryDigestUtils.bytesToChars(value);
-
-                       if (getDirectory().getForcedPassword() != null
-                                       && getDirectory().getForcedPassword().equals(new String(password)))
-                               return true;
-
-                       AuthPassword authPassword = AuthPassword.matchAuthValue(getAttributes(), password);
-                       if (authPassword != null) {
-                               if (authPassword.getAuthScheme().equals(SharedSecret.X_SHARED_SECRET)) {
-                                       SharedSecret onceToken = new SharedSecret(authPassword);
-                                       if (onceToken.isExpired()) {
-                                               // AuthPassword.remove(getAttributes(), onceToken);
-                                               return false;
-                                       } else {
-                                               // boolean wasRemoved = AuthPassword.remove(getAttributes(), onceToken);
-                                               return true;
-                                       }
-                                       // TODO delete expired tokens?
-                               } else {
-                                       // TODO implement SHA
-                                       throw new UnsupportedOperationException(
-                                                       "Unsupported authPassword scheme " + authPassword.getAuthScheme());
-                               }
-                       }
-
-                       // Regular password
-//                     byte[] hashedPassword = hash(password, DigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256);
-                       if (hasCredential(LdapAttrs.userPassword.name(), DirectoryDigestUtils.charsToBytes(password)))
-                               return true;
-                       return false;
-               }
-
-               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[]) {
-                       String storedBase64 = new String((byte[]) storedValue, US_ASCII);
-                       String passwordScheme = null;
-                       if (storedBase64.charAt(0) == '{') {
-                               int index = storedBase64.indexOf('}');
-                               if (index > 0) {
-                                       passwordScheme = storedBase64.substring(1, index);
-                                       String storedValueBase64 = storedBase64.substring(index + 1);
-                                       byte[] storedValueBytes = Base64.getDecoder().decode(storedValueBase64);
-                                       char[] passwordValue = DirectoryDigestUtils.bytesToChars((byte[]) value);
-                                       byte[] valueBytes;
-                                       if (DirectoryDigestUtils.PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
-                                               valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, null, null,
-                                                               null);
-                                       } else if (DirectoryDigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
-                                               // see https://www.thesubtlety.com/post/a-389-ds-pbkdf2-password-checker/
-                                               byte[] iterationsArr = Arrays.copyOfRange(storedValueBytes, 0, 4);
-                                               BigInteger iterations = new BigInteger(iterationsArr);
-                                               byte[] salt = Arrays.copyOfRange(storedValueBytes, iterationsArr.length,
-                                                               iterationsArr.length + 64);
-                                               byte[] keyArr = Arrays.copyOfRange(storedValueBytes, iterationsArr.length + salt.length,
-                                                               storedValueBytes.length);
-                                               int keyLengthBits = keyArr.length * 8;
-                                               valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, salt,
-                                                               iterations.intValue(), keyLengthBits);
-                                       } else {
-                                               throw new UnsupportedOperationException("Unknown password scheme " + passwordScheme);
-                                       }
-                                       return Arrays.equals(storedValueBytes, valueBytes);
-                               }
-                       }
-               }
-//             if (storedValue instanceof byte[] && value instanceof byte[]) {
-//                     return Arrays.equals((byte[]) storedValue, (byte[]) value);
-//             }
-               return false;
-       }
-
-       /** Hash the password */
-       byte[] sha1hash(char[] password) {
-               byte[] hashedPassword = ("{SHA}" + Base64.getEncoder()
-                               .encodeToString(DirectoryDigestUtils.sha1(DirectoryDigestUtils.charsToBytes(password))))
-                               .getBytes(StandardCharsets.UTF_8);
-               return hashedPassword;
-       }
-
-//     byte[] hash(char[] password, String passwordScheme) {
-//             if (passwordScheme == null)
-//                     passwordScheme = DigestUtils.PASSWORD_SCHEME_SHA;
-//             byte[] hashedPassword = ("{" + passwordScheme + "}"
-//                             + Base64.getEncoder().encodeToString(DigestUtils.toPasswordScheme(passwordScheme, password)))
-//                                             .getBytes(US_ASCII);
-//             return hashedPassword;
-//     }
-
-       protected DirectoryUserAdmin getUserAdmin() {
-               return (DirectoryUserAdmin) getDirectory();
-       }
-
-       private class AttributeDictionary extends Dictionary<String, Object> {
-               private final List<String> effectiveKeys = new ArrayList<String>();
-               private final List<String> attrFilter;
-               private final Boolean includeFilter;
-
-               public AttributeDictionary(Boolean credentials) {
-                       this.attrFilter = getDirectory().getCredentialAttributeIds();
-                       this.includeFilter = credentials;
-                       try {
-                               NamingEnumeration<String> ids = getAttributes().getIDs();
-                               while (ids.hasMore()) {
-                                       String id = ids.next();
-                                       if (credentials && attrFilter.contains(id))
-                                               effectiveKeys.add(id);
-                                       else if (!credentials && !attrFilter.contains(id))
-                                               effectiveKeys.add(id);
-                               }
-                       } catch (NamingException e) {
-                               throw new IllegalStateException("Cannot initialise attribute dictionary", e);
-                       }
-                       if (!credentials)
-                               effectiveKeys.add(LdapAttrs.objectClasses.name());
-               }
-
-               @Override
-               public int size() {
-                       return effectiveKeys.size();
-               }
-
-               @Override
-               public boolean isEmpty() {
-                       return effectiveKeys.size() == 0;
-               }
-
-               @Override
-               public Enumeration<String> keys() {
-                       return Collections.enumeration(effectiveKeys);
-               }
-
-               @Override
-               public Enumeration<Object> elements() {
-                       final Iterator<String> it = effectiveKeys.iterator();
-                       return new Enumeration<Object>() {
-
-                               @Override
-                               public boolean hasMoreElements() {
-                                       return it.hasNext();
-                               }
-
-                               @Override
-                               public Object nextElement() {
-                                       String key = it.next();
-                                       return get(key);
-                               }
-
-                       };
-               }
-
-               @Override
-               public Object get(Object key) {
-                       try {
-                               Attribute attr = !key.equals(LdapAttrs.objectClasses.name()) ? getAttributes().get(key.toString())
-                                               : getAttributes().get(LdapAttrs.objectClass.name());
-                               if (attr == null)
-                                       return null;
-                               Object value = attr.get();
-                               if (value instanceof byte[]) {
-                                       if (key.equals(LdapAttrs.userPassword.name()))
-                                               // TODO other cases (certificates, images)
-                                               return value;
-                                       value = new String((byte[]) value, StandardCharsets.UTF_8);
-                               }
-                               if (attr.size() == 1)
-                                       return value;
-                               // special case for object class
-                               if (key.equals(LdapAttrs.objectClass.name())) {
-                                       // TODO support multiple object classes
-                                       NamingEnumeration<?> en = attr.getAll();
-                                       String first = null;
-                                       attrs: while (en.hasMore()) {
-                                               String v = en.next().toString();
-                                               if (v.equalsIgnoreCase(LdapObjs.top.name()))
-                                                       continue attrs;
-                                               if (first == null)
-                                                       first = v;
-                                               if (v.equalsIgnoreCase(getDirectory().getUserObjectClass()))
-                                                       return getDirectory().getUserObjectClass();
-                                               else if (v.equalsIgnoreCase(getDirectory().getGroupObjectClass()))
-                                                       return getDirectory().getGroupObjectClass();
-                                       }
-                                       if (first != null)
-                                               return first;
-                                       throw new IllegalStateException("Cannot find objectClass in " + value);
-                               } else {
-                                       NamingEnumeration<?> en = attr.getAll();
-                                       StringJoiner values = new StringJoiner("\n");
-                                       while (en.hasMore()) {
-                                               String v = en.next().toString();
-                                               values.add(v);
-                                       }
-                                       return values.toString();
-                               }
-//                             else
-//                                     return value;
-                       } catch (NamingException e) {
-                               throw new IllegalStateException("Cannot get value for attribute " + key, e);
-                       }
-               }
-
-               @Override
-               public Object put(String key, Object value) {
-                       if (key == null) {
-                               // TODO persist to other sources (like PKCS12)
-                               char[] password = DirectoryDigestUtils.bytesToChars(value);
-                               byte[] hashedPassword = sha1hash(password);
-                               return put(LdapAttrs.userPassword.name(), hashedPassword);
-                       }
-                       if (key.startsWith("X-")) {
-                               return put(LdapAttrs.authPassword.name(), value);
-                       }
-
-                       getDirectory().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 = getModifiedAttributes().get(key.toString());
-                               // if (attribute == null) // block unit tests
-                               attribute = new BasicAttribute(key.toString());
-                               if (value instanceof String && !isAsciiPrintable(((String) value)))
-                                       attribute.add(((String) value).getBytes(StandardCharsets.UTF_8));
-                               else
-                                       attribute.add(value);
-                               Attribute previousAttribute = getModifiedAttributes().put(attribute);
-                               if (previousAttribute != null)
-                                       return previousAttribute.get();
-                               else
-                                       return null;
-                       } catch (NamingException e) {
-                               throw new IllegalStateException("Cannot get value for attribute " + key, e);
-                       }
-               }
-
-               @Override
-               public Object remove(Object key) {
-                       getDirectory().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 = getModifiedAttributes().remove(key.toString());
-                               if (attr != null)
-                                       return attr.get();
-                               else
-                                       return null;
-                       } catch (NamingException e) {
-                               throw new IllegalStateException("Cannot remove attribute " + key, e);
-                       }
-               }
-       }
-
-       private static boolean isAsciiPrintable(String str) {
-               if (str == null) {
-                       return false;
-               }
-               int sz = str.length();
-               for (int i = 0; i < sz; i++) {
-                       if (isAsciiPrintable(str.charAt(i)) == false) {
-                               return false;
-                       }
-               }
-               return true;
-       }
-
-       private static boolean isAsciiPrintable(char ch) {
-               return ch >= 32 && ch < 127;
-       }
-
-       static class LdifPerson extends LdifUser implements Person {
-
-               public LdifPerson(DirectoryUserAdmin userAdmin, LdapName dn, Attributes attributes) {
-                       super(userAdmin, dn, attributes);
-               }
-
-       }
 }
index 1adc7e0dfe6f1806b0b7186a8a5ef2d75e6aa5f7..c052fee1b1da12bc4193a208c4d21123fc4d0e21 100644 (file)
@@ -41,12 +41,12 @@ public class OsUserDirectory extends AbstractLdapDirectoryDao {
        }
 
        @Override
-       public Boolean daoHasEntry(LdapName dn) {
+       public Boolean entryExists(LdapName dn) {
                return osUserDn.equals(dn);
        }
 
        @Override
-       public LdapEntry daoGetEntry(LdapName key) throws NameNotFoundException {
+       public LdapEntry doGetEntry(LdapName key) throws NameNotFoundException {
                if (osUserDn.equals(key))
                        return osUser;
                else
index 05808908d109adc00da816b0a19b615bc1737e33..0bbb5e53f7bdd3ff35c283596d899bdddea93ddd 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.util.directory;
 
+import java.util.Dictionary;
 import java.util.Optional;
 
 import org.argeo.util.transaction.WorkControl;
@@ -21,6 +22,11 @@ public interface Directory {
 
        void setTransactionControl(WorkControl transactionControl);
 
+       /*
+        * METADATA
+        */
+       public Dictionary<String, Object> getProperties();
+
        /*
         * HIERARCHY
         */
diff --git a/org.argeo.util/src/org/argeo/util/directory/FunctionalGroup.java b/org.argeo.util/src/org/argeo/util/directory/FunctionalGroup.java
deleted file mode 100644 (file)
index 89511ab..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.argeo.util.directory;
-
-public interface FunctionalGroup {
-
-}
index 0194ffc89165f68b5bc24fcfc55fc9e43f398c98..68cc1bb2d5de7cbe308dd1322b8c0c656f025455 100644 (file)
@@ -1,5 +1,7 @@
 package org.argeo.util.directory;
 
+import java.util.Dictionary;
+
 /** A unit within the high-level organisational structure of a directory. */
 public interface HierarchyUnit {
        String getHierarchyUnitName();
@@ -14,5 +16,5 @@ public interface HierarchyUnit {
 
        Directory getDirectory();
 
-//     Map<String,Object> getHierarchyProperties();
+       Dictionary<String, Object> getProperties();
 }
diff --git a/org.argeo.util/src/org/argeo/util/directory/Organization.java b/org.argeo.util/src/org/argeo/util/directory/Organization.java
deleted file mode 100644 (file)
index bbbdcd9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.argeo.util.directory;
-
-public interface Organization {
-
-}
diff --git a/org.argeo.util/src/org/argeo/util/directory/Person.java b/org.argeo.util/src/org/argeo/util/directory/Person.java
deleted file mode 100644 (file)
index d782ee4..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.argeo.util.directory;
-
-public interface Person {
-
-}
diff --git a/org.argeo.util/src/org/argeo/util/directory/SystemPermissions.java b/org.argeo.util/src/org/argeo/util/directory/SystemPermissions.java
deleted file mode 100644 (file)
index 3ab16b8..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.argeo.util.directory;
-
-public interface SystemPermissions {
-
-}
index d8e8e7d2127a27de54c2aa0906021c6bc6a585ee..eab82e0ec3a0ba2ea2426b01d62a6d7ab20f4c56 100644 (file)
@@ -38,7 +38,7 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
        protected static final String SHARED_STATE_PASSWORD = "javax.security.auth.login.password";
 
        protected final LdapName baseDn;
-       protected final Hashtable<String, Object> properties;
+       protected final Hashtable<String, Object> configProperties;
        private final Rdn userBaseRdn, groupBaseRdn, systemRoleBaseRdn;
        private final String userObjectClass, groupObjectClass;
        private String memberAttributeId = "member";
@@ -60,33 +60,33 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
        private LdapDirectoryDao directoryDao;
 
        public AbstractLdapDirectory(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
-               this.properties = new Hashtable<String, Object>();
+               this.configProperties = new Hashtable<String, Object>();
                for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
                        String key = keys.nextElement();
-                       properties.put(key, props.get(key));
+                       configProperties.put(key, props.get(key));
                }
-               baseDn = toLdapName(DirectoryConf.baseDn.getValue(properties));
+               baseDn = toLdapName(DirectoryConf.baseDn.getValue(configProperties));
                this.scoped = scoped;
 
                if (uriArg != null) {
                        uri = uriArg.toString();
                        // uri from properties is ignored
                } else {
-                       String uriStr = DirectoryConf.uri.getValue(properties);
+                       String uriStr = DirectoryConf.uri.getValue(configProperties);
                        if (uriStr == null)
                                uri = null;
                        else
                                uri = uriStr;
                }
 
-               forcedPassword = DirectoryConf.forcedPassword.getValue(properties);
+               forcedPassword = DirectoryConf.forcedPassword.getValue(configProperties);
 
-               userObjectClass = DirectoryConf.userObjectClass.getValue(properties);
-               groupObjectClass = DirectoryConf.groupObjectClass.getValue(properties);
+               userObjectClass = DirectoryConf.userObjectClass.getValue(configProperties);
+               groupObjectClass = DirectoryConf.groupObjectClass.getValue(configProperties);
 
-               String userBase = DirectoryConf.userBase.getValue(properties);
-               String groupBase = DirectoryConf.groupBase.getValue(properties);
-               String systemRoleBase = DirectoryConf.systemRoleBase.getValue(properties);
+               String userBase = DirectoryConf.userBase.getValue(configProperties);
+               String groupBase = DirectoryConf.groupBase.getValue(configProperties);
+               String systemRoleBase = DirectoryConf.systemRoleBase.getValue(configProperties);
                try {
 //                     baseDn = new LdapName(UserAdminConf.baseDn.getValue(properties));
                        userBaseRdn = new Rdn(userBase);
@@ -95,20 +95,20 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
 //                     groupBaseDn = new LdapName(groupBase + "," + baseDn);
                        systemRoleBaseRdn = new Rdn(systemRoleBase);
                } catch (InvalidNameException e) {
-                       throw new IllegalArgumentException("Badly formated base DN " + DirectoryConf.baseDn.getValue(properties),
-                                       e);
+                       throw new IllegalArgumentException(
+                                       "Badly formated base DN " + DirectoryConf.baseDn.getValue(configProperties), e);
                }
 
                // read only
-               String readOnlyStr = DirectoryConf.readOnly.getValue(properties);
+               String readOnlyStr = DirectoryConf.readOnly.getValue(configProperties);
                if (readOnlyStr == null) {
                        readOnly = readOnlyDefault(uri);
-                       properties.put(DirectoryConf.readOnly.name(), Boolean.toString(readOnly));
+                       configProperties.put(DirectoryConf.readOnly.name(), Boolean.toString(readOnly));
                } else
                        readOnly = Boolean.parseBoolean(readOnlyStr);
 
                // disabled
-               String disabledStr = DirectoryConf.disabled.getValue(properties);
+               String disabledStr = DirectoryConf.disabled.getValue(configProperties);
                if (disabledStr != null)
                        disabled = Boolean.parseBoolean(disabledStr);
                else
@@ -202,7 +202,7 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
                checkEdit();
                LdapEntryWorkingCopy wc = getWorkingCopy();
                boolean actuallyDeleted;
-               if (getDirectoryDao().daoHasEntry(dn) || wc.getNewData().containsKey(dn)) {
+               if (getDirectoryDao().entryExists(dn) || wc.getNewData().containsKey(dn)) {
                        LdapEntry user = doGetRole(dn);
                        wc.getDeletedData().put(dn, user);
                        actuallyDeleted = true;
@@ -224,7 +224,7 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
                LdapEntryWorkingCopy wc = getWorkingCopy();
                LdapEntry user;
                try {
-                       user = getDirectoryDao().daoGetEntry(dn);
+                       user = getDirectoryDao().doGetEntry(dn);
                } catch (NameNotFoundException e) {
                        user = null;
                }
@@ -386,12 +386,27 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
                return true;// read only by default
        }
 
+       /*
+        * AS AN ENTRY
+        */
+       public LdapEntry asLdapEntry() {
+               try {
+                       return directoryDao.doGetEntry(baseDn);
+               } catch (NameNotFoundException e) {
+                       throw new IllegalStateException("Cannot get " + baseDn + " entry", e);
+               }
+       }
+
+       public Dictionary<String, Object> getProperties() {
+               return asLdapEntry().getProperties();
+       }
+
        /*
         * ACCESSORS
         */
        @Override
        public Optional<String> getRealm() {
-               Object realm = getProperties().get(DirectoryConf.realm.name());
+               Object realm = configProperties.get(DirectoryConf.realm.name());
                if (realm == null)
                        return Optional.empty();
                return Optional.of(realm.toString());
@@ -421,12 +436,12 @@ public abstract class AbstractLdapDirectory implements Directory, XAResourceProv
                return systemRoleBaseRdn;
        }
 
-       public Dictionary<String, Object> getProperties() {
-               return properties;
-       }
+//     public Dictionary<String, Object> getConfigProperties() {
+//             return configProperties;
+//     }
 
-       public Dictionary<String, Object> cloneProperties() {
-               return new Hashtable<>(properties);
+       public Dictionary<String, Object> cloneConfigProperties() {
+               return new Hashtable<>(configProperties);
        }
 
        public String getForcedPassword() {
diff --git a/org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapEntry.java b/org.argeo.util/src/org/argeo/util/directory/ldap/AbstractLdapEntry.java
deleted file mode 100644 (file)
index 25f233a..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.argeo.util.directory.ldap;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-/** An entry in an LDAP (or LDIF) directory. */
-public abstract class AbstractLdapEntry implements LdapEntry {
-       private final AbstractLdapDirectory directory;
-
-       private final LdapName dn;
-
-       private Attributes publishedAttributes;
-
-       protected AbstractLdapEntry(AbstractLdapDirectory directory, LdapName dn, Attributes attributes) {
-               Objects.requireNonNull(directory);
-               Objects.requireNonNull(dn);
-               this.directory = directory;
-               this.dn = dn;
-               this.publishedAttributes = attributes;
-       }
-
-       @Override
-       public LdapName getDn() {
-               return dn;
-       }
-
-       public synchronized Attributes getAttributes() {
-               return isEditing() ? getModifiedAttributes() : publishedAttributes;
-       }
-       
-       @Override
-       public List<LdapName> getReferences(String attributeId){
-               Attribute memberAttribute = getAttributes().get(attributeId);
-               if (memberAttribute == null)
-                       return new ArrayList<LdapName>();
-               try {
-                       List<LdapName> roles = new ArrayList<LdapName>();
-                       NamingEnumeration<?> values = memberAttribute.getAll();
-                       while (values.hasMore()) {
-                               LdapName dn = new LdapName(values.next().toString());
-                               roles.add(dn);
-                       }
-                       return roles;
-               } catch (NamingException e) {
-                       throw new IllegalStateException("Cannot get members", e);
-               }
-               
-       }
-
-       /** Should only be called from working copy thread. */
-       protected synchronized Attributes getModifiedAttributes() {
-               assert getWc() != null;
-               return getWc().getModifiedData().get(getDn());
-       }
-
-       protected synchronized boolean isEditing() {
-               return getWc() != null && getModifiedAttributes() != null;
-       }
-
-       private synchronized LdapEntryWorkingCopy getWc() {
-               return directory.getWorkingCopy();
-       }
-
-       protected synchronized void startEditing() {
-//             if (frozen)
-//                     throw new IllegalStateException("Cannot edit frozen view");
-               if (directory.isReadOnly())
-                       throw new IllegalStateException("User directory is read-only");
-               assert getModifiedAttributes() == null;
-               getWc().startEditing(this);
-               // modifiedAttributes = (Attributes) publishedAttributes.clone();
-       }
-
-       public synchronized void publishAttributes(Attributes modifiedAttributes) {
-               publishedAttributes = modifiedAttributes;
-       }
-
-       public AbstractLdapDirectory getDirectory() {
-               return directory;
-       }
-
-       public LdapDirectoryDao getDirectoryDao() {
-               return directory.getDirectoryDao();
-       }
-
-       @Override
-       public int hashCode() {
-               return dn.hashCode();
-       }
-
-       @Override
-       public boolean equals(Object obj) {
-               if (this == obj)
-                       return true;
-               if (obj instanceof LdapEntry) {
-                       LdapEntry that = (LdapEntry) obj;
-                       return this.dn.equals(that.getDn());
-               }
-               return false;
-       }
-
-       @Override
-       public String toString() {
-               return dn.toString();
-       }
-
-}
diff --git a/org.argeo.util/src/org/argeo/util/directory/ldap/DefaultLdapEntry.java b/org.argeo.util/src/org/argeo/util/directory/ldap/DefaultLdapEntry.java
new file mode 100644 (file)
index 0000000..8eff669
--- /dev/null
@@ -0,0 +1,431 @@
+package org.argeo.util.directory.ldap;
+
+import static java.nio.charset.StandardCharsets.US_ASCII;
+
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+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.argeo.util.directory.DirectoryDigestUtils;
+import org.argeo.util.naming.LdapAttrs;
+import org.argeo.util.naming.LdapObjs;
+import org.argeo.util.naming.SharedSecret;
+
+/** An entry in an LDAP (or LDIF) directory. */
+public class DefaultLdapEntry implements LdapEntry {
+       private final AbstractLdapDirectory directory;
+
+       private final LdapName dn;
+
+       private Attributes publishedAttributes;
+
+       // Temporarily expose the fields
+       protected final AttributeDictionary properties;
+       protected final AttributeDictionary credentials;
+
+       protected DefaultLdapEntry(AbstractLdapDirectory directory, LdapName dn, Attributes attributes) {
+               Objects.requireNonNull(directory);
+               Objects.requireNonNull(dn);
+               this.directory = directory;
+               this.dn = dn;
+               this.publishedAttributes = attributes;
+               properties = new AttributeDictionary(false);
+               credentials = new AttributeDictionary(true);
+       }
+
+       @Override
+       public LdapName getDn() {
+               return dn;
+       }
+
+       public synchronized Attributes getAttributes() {
+               return isEditing() ? getModifiedAttributes() : publishedAttributes;
+       }
+
+       @Override
+       public List<LdapName> getReferences(String attributeId) {
+               Attribute memberAttribute = getAttributes().get(attributeId);
+               if (memberAttribute == null)
+                       return new ArrayList<LdapName>();
+               try {
+                       List<LdapName> roles = new ArrayList<LdapName>();
+                       NamingEnumeration<?> values = memberAttribute.getAll();
+                       while (values.hasMore()) {
+                               LdapName dn = new LdapName(values.next().toString());
+                               roles.add(dn);
+                       }
+                       return roles;
+               } catch (NamingException e) {
+                       throw new IllegalStateException("Cannot get members", e);
+               }
+
+       }
+
+       /** Should only be called from working copy thread. */
+       protected synchronized Attributes getModifiedAttributes() {
+               assert getWc() != null;
+               return getWc().getModifiedData().get(getDn());
+       }
+
+       protected synchronized boolean isEditing() {
+               return getWc() != null && getModifiedAttributes() != null;
+       }
+
+       private synchronized LdapEntryWorkingCopy getWc() {
+               return directory.getWorkingCopy();
+       }
+
+       protected synchronized void startEditing() {
+//             if (frozen)
+//                     throw new IllegalStateException("Cannot edit frozen view");
+               if (directory.isReadOnly())
+                       throw new IllegalStateException("User directory is read-only");
+               assert getModifiedAttributes() == null;
+               getWc().startEditing(this);
+               // modifiedAttributes = (Attributes) publishedAttributes.clone();
+       }
+
+       public synchronized void publishAttributes(Attributes modifiedAttributes) {
+               publishedAttributes = modifiedAttributes;
+       }
+       
+       /*
+        * PROPERTIES
+        */
+       @Override
+       public Dictionary<String, Object> getProperties() {
+               return properties;
+       }
+
+       /*
+        * CREDENTIALS
+        */
+       @Override
+       public boolean hasCredential(String key, Object value) {
+               if (key == null) {
+                       // TODO check other sources (like PKCS12)
+                       // String pwd = new String((char[]) value);
+                       // authPassword (RFC 312 https://tools.ietf.org/html/rfc3112)
+                       char[] password = DirectoryDigestUtils.bytesToChars(value);
+
+                       if (getDirectory().getForcedPassword() != null
+                                       && getDirectory().getForcedPassword().equals(new String(password)))
+                               return true;
+
+                       AuthPassword authPassword = AuthPassword.matchAuthValue(getAttributes(), password);
+                       if (authPassword != null) {
+                               if (authPassword.getAuthScheme().equals(SharedSecret.X_SHARED_SECRET)) {
+                                       SharedSecret onceToken = new SharedSecret(authPassword);
+                                       if (onceToken.isExpired()) {
+                                               // AuthPassword.remove(getAttributes(), onceToken);
+                                               return false;
+                                       } else {
+                                               // boolean wasRemoved = AuthPassword.remove(getAttributes(), onceToken);
+                                               return true;
+                                       }
+                                       // TODO delete expired tokens?
+                               } else {
+                                       // TODO implement SHA
+                                       throw new UnsupportedOperationException(
+                                                       "Unsupported authPassword scheme " + authPassword.getAuthScheme());
+                               }
+                       }
+
+                       // Regular password
+//                     byte[] hashedPassword = hash(password, DigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256);
+                       if (hasCredential(LdapAttrs.userPassword.name(), DirectoryDigestUtils.charsToBytes(password)))
+                               return true;
+                       return false;
+               }
+
+               Object storedValue = credentials.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[]) {
+                       String storedBase64 = new String((byte[]) storedValue, US_ASCII);
+                       String passwordScheme = null;
+                       if (storedBase64.charAt(0) == '{') {
+                               int index = storedBase64.indexOf('}');
+                               if (index > 0) {
+                                       passwordScheme = storedBase64.substring(1, index);
+                                       String storedValueBase64 = storedBase64.substring(index + 1);
+                                       byte[] storedValueBytes = Base64.getDecoder().decode(storedValueBase64);
+                                       char[] passwordValue = DirectoryDigestUtils.bytesToChars((byte[]) value);
+                                       byte[] valueBytes;
+                                       if (DirectoryDigestUtils.PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
+                                               valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, null, null,
+                                                               null);
+                                       } else if (DirectoryDigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
+                                               // see https://www.thesubtlety.com/post/a-389-ds-pbkdf2-password-checker/
+                                               byte[] iterationsArr = Arrays.copyOfRange(storedValueBytes, 0, 4);
+                                               BigInteger iterations = new BigInteger(iterationsArr);
+                                               byte[] salt = Arrays.copyOfRange(storedValueBytes, iterationsArr.length,
+                                                               iterationsArr.length + 64);
+                                               byte[] keyArr = Arrays.copyOfRange(storedValueBytes, iterationsArr.length + salt.length,
+                                                               storedValueBytes.length);
+                                               int keyLengthBits = keyArr.length * 8;
+                                               valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, salt,
+                                                               iterations.intValue(), keyLengthBits);
+                                       } else {
+                                               throw new UnsupportedOperationException("Unknown password scheme " + passwordScheme);
+                                       }
+                                       return Arrays.equals(storedValueBytes, valueBytes);
+                               }
+                       }
+               }
+//             if (storedValue instanceof byte[] && value instanceof byte[]) {
+//                     return Arrays.equals((byte[]) storedValue, (byte[]) value);
+//             }
+               return false;
+       }
+
+       /** Hash the password */
+       private static byte[] sha1hash(char[] password) {
+               byte[] hashedPassword = ("{SHA}" + Base64.getEncoder()
+                               .encodeToString(DirectoryDigestUtils.sha1(DirectoryDigestUtils.charsToBytes(password))))
+                               .getBytes(StandardCharsets.UTF_8);
+               return hashedPassword;
+       }
+
+       public AbstractLdapDirectory getDirectory() {
+               return directory;
+       }
+
+       public LdapDirectoryDao getDirectoryDao() {
+               return directory.getDirectoryDao();
+       }
+
+       @Override
+       public int hashCode() {
+               return dn.hashCode();
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj instanceof LdapEntry) {
+                       LdapEntry that = (LdapEntry) obj;
+                       return this.dn.equals(that.getDn());
+               }
+               return false;
+       }
+
+       @Override
+       public String toString() {
+               return dn.toString();
+       }
+
+       private static boolean isAsciiPrintable(String str) {
+               if (str == null) {
+                       return false;
+               }
+               int sz = str.length();
+               for (int i = 0; i < sz; i++) {
+                       if (isAsciiPrintable(str.charAt(i)) == false) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       private static boolean isAsciiPrintable(char ch) {
+               return ch >= 32 && ch < 127;
+       }
+
+       protected class AttributeDictionary extends Dictionary<String, Object> {
+               private final List<String> effectiveKeys = new ArrayList<String>();
+               private final List<String> attrFilter;
+               private final Boolean includeFilter;
+
+               public AttributeDictionary(Boolean credentials) {
+                       this.attrFilter = getDirectory().getCredentialAttributeIds();
+                       this.includeFilter = credentials;
+                       try {
+                               NamingEnumeration<String> ids = getAttributes().getIDs();
+                               while (ids.hasMore()) {
+                                       String id = ids.next();
+                                       if (credentials && attrFilter.contains(id))
+                                               effectiveKeys.add(id);
+                                       else if (!credentials && !attrFilter.contains(id))
+                                               effectiveKeys.add(id);
+                               }
+                       } catch (NamingException e) {
+                               throw new IllegalStateException("Cannot initialise attribute dictionary", e);
+                       }
+                       if (!credentials)
+                               effectiveKeys.add(LdapAttrs.objectClasses.name());
+               }
+
+               @Override
+               public int size() {
+                       return effectiveKeys.size();
+               }
+
+               @Override
+               public boolean isEmpty() {
+                       return effectiveKeys.size() == 0;
+               }
+
+               @Override
+               public Enumeration<String> keys() {
+                       return Collections.enumeration(effectiveKeys);
+               }
+
+               @Override
+               public Enumeration<Object> elements() {
+                       final Iterator<String> it = effectiveKeys.iterator();
+                       return new Enumeration<Object>() {
+
+                               @Override
+                               public boolean hasMoreElements() {
+                                       return it.hasNext();
+                               }
+
+                               @Override
+                               public Object nextElement() {
+                                       String key = it.next();
+                                       return get(key);
+                               }
+
+                       };
+               }
+
+               @Override
+               public Object get(Object key) {
+                       try {
+                               Attribute attr = !key.equals(LdapAttrs.objectClasses.name()) ? getAttributes().get(key.toString())
+                                               : getAttributes().get(LdapAttrs.objectClass.name());
+                               if (attr == null)
+                                       return null;
+                               Object value = attr.get();
+                               if (value instanceof byte[]) {
+                                       if (key.equals(LdapAttrs.userPassword.name()))
+                                               // TODO other cases (certificates, images)
+                                               return value;
+                                       value = new String((byte[]) value, StandardCharsets.UTF_8);
+                               }
+                               if (attr.size() == 1)
+                                       return value;
+                               // special case for object class
+                               if (key.equals(LdapAttrs.objectClass.name())) {
+                                       // TODO support multiple object classes
+                                       NamingEnumeration<?> en = attr.getAll();
+                                       String first = null;
+                                       attrs: while (en.hasMore()) {
+                                               String v = en.next().toString();
+                                               if (v.equalsIgnoreCase(LdapObjs.top.name()))
+                                                       continue attrs;
+                                               if (first == null)
+                                                       first = v;
+                                               if (v.equalsIgnoreCase(getDirectory().getUserObjectClass()))
+                                                       return getDirectory().getUserObjectClass();
+                                               else if (v.equalsIgnoreCase(getDirectory().getGroupObjectClass()))
+                                                       return getDirectory().getGroupObjectClass();
+                                       }
+                                       if (first != null)
+                                               return first;
+                                       throw new IllegalStateException("Cannot find objectClass in " + value);
+                               } else {
+                                       NamingEnumeration<?> en = attr.getAll();
+                                       StringJoiner values = new StringJoiner("\n");
+                                       while (en.hasMore()) {
+                                               String v = en.next().toString();
+                                               values.add(v);
+                                       }
+                                       return values.toString();
+                               }
+//                             else
+//                                     return value;
+                       } catch (NamingException e) {
+                               throw new IllegalStateException("Cannot get value for attribute " + key, e);
+                       }
+               }
+
+               @Override
+               public Object put(String key, Object value) {
+                       if (key == null) {
+                               // TODO persist to other sources (like PKCS12)
+                               char[] password = DirectoryDigestUtils.bytesToChars(value);
+                               byte[] hashedPassword = sha1hash(password);
+                               return put(LdapAttrs.userPassword.name(), hashedPassword);
+                       }
+                       if (key.startsWith("X-")) {
+                               return put(LdapAttrs.authPassword.name(), value);
+                       }
+
+                       getDirectory().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 = getModifiedAttributes().get(key.toString());
+                               // if (attribute == null) // block unit tests
+                               attribute = new BasicAttribute(key.toString());
+                               if (value instanceof String && !isAsciiPrintable(((String) value)))
+                                       attribute.add(((String) value).getBytes(StandardCharsets.UTF_8));
+                               else
+                                       attribute.add(value);
+                               Attribute previousAttribute = getModifiedAttributes().put(attribute);
+                               if (previousAttribute != null)
+                                       return previousAttribute.get();
+                               else
+                                       return null;
+                       } catch (NamingException e) {
+                               throw new IllegalStateException("Cannot get value for attribute " + key, e);
+                       }
+               }
+
+               @Override
+               public Object remove(Object key) {
+                       getDirectory().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 = getModifiedAttributes().remove(key.toString());
+                               if (attr != null)
+                                       return attr.get();
+                               else
+                                       return null;
+                       } catch (NamingException e) {
+                               throw new IllegalStateException("Cannot remove attribute " + key, e);
+                       }
+               }
+
+       }
+
+}
index a2d9e7fc3bbc0c33fbb4cadaff5cbcbdd06349d7..8e26cb44f14125206446e23eb0cf0849f26ebe50 100644 (file)
@@ -35,7 +35,7 @@ public class LdapDao extends AbstractLdapDirectoryDao {
 
        @Override
        public void init() {
-               ldapConnection = new LdapConnection(getDirectory().getUri().toString(), getDirectory().getProperties());
+               ldapConnection = new LdapConnection(getDirectory().getUri().toString(), getDirectory().cloneConfigProperties());
        }
 
        public void destroy() {
@@ -66,26 +66,34 @@ public class LdapDao extends AbstractLdapDirectoryDao {
 //     }
 
        @Override
-       public Boolean daoHasEntry(LdapName dn) {
+       public Boolean entryExists(LdapName dn) {
                try {
-                       return daoGetEntry(dn) != null;
+                       return doGetEntry(dn) != null;
                } catch (NameNotFoundException e) {
                        return false;
                }
        }
 
        @Override
-       public LdapEntry daoGetEntry(LdapName name) throws NameNotFoundException {
+       public LdapEntry doGetEntry(LdapName name) throws NameNotFoundException {
                try {
                        Attributes attrs = ldapConnection.getAttributes(name);
                        if (attrs.size() == 0)
                                return null;
 //                     int roleType = roleType(name);
                        LdapEntry res;
-                       if (isGroup(name))
+                       Rdn technicalRdn = LdapNameUtils.getParentRdn(name);
+                       if (getDirectory().getGroupBaseRdn().equals(technicalRdn)
+                                       || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
                                res = newGroup(name, attrs);
-                       else
+                       else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
                                res = newUser(name, attrs);
+                       else
+                               res = new DefaultLdapEntry(getDirectory(), name, attrs);
+//                     if (isGroup(name))
+//                             res = newGroup(name, attrs);
+//                     else
+//                             res = newUser(name, attrs);
 //                     else
 //                             throw new IllegalArgumentException("Unsupported LDAP type for " + name);
                        return res;
@@ -96,17 +104,17 @@ public class LdapDao extends AbstractLdapDirectoryDao {
                }
        }
 
-       protected boolean isGroup(LdapName dn) {
-               Rdn technicalRdn = LdapNameUtils.getParentRdn(dn);
-               if (getDirectory().getGroupBaseRdn().equals(technicalRdn)
-                               || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
-                       return true;
-               else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
-                       return false;
-               else
-                       throw new IllegalArgumentException(
-                                       "Cannot dind role type, " + technicalRdn + " is not a technical RDN for " + dn);
-       }
+//     protected boolean isGroup(LdapName dn) {
+//             Rdn technicalRdn = LdapNameUtils.getParentRdn(dn);
+//             if (getDirectory().getGroupBaseRdn().equals(technicalRdn)
+//                             || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
+//                     return true;
+//             else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
+//                     return false;
+//             else
+//                     throw new IllegalArgumentException(
+//                                     "Cannot find role type, " + technicalRdn + " is not a technical RDN for " + dn);
+//     }
 
        @Override
        public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
@@ -237,6 +245,8 @@ public class LdapDao extends AbstractLdapDirectoryDao {
        @Override
        public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
                try {
+                       if (getDirectory().getBaseDn().equals(dn))
+                               return null;
                        Attributes attrs = ldapConnection.getAttributes(dn);
                        return new LdapHierarchyUnit(getDirectory(), dn, attrs);
                } catch (NamingException e) {
index 3a0f4e6e019987c517250f86913b02daf938c5cc..2739932767419d1d5825d658209cbe4e1be0ceda 100644 (file)
@@ -10,9 +10,9 @@ import org.argeo.util.directory.HierarchyUnit;
 import org.argeo.util.transaction.WorkingCopyProcessor;
 
 public interface LdapDirectoryDao extends WorkingCopyProcessor<LdapEntryWorkingCopy> {
-       Boolean daoHasEntry(LdapName dn);
+       Boolean entryExists(LdapName dn);
 
-       LdapEntry daoGetEntry(LdapName name) throws NameNotFoundException;
+       LdapEntry doGetEntry(LdapName name) throws NameNotFoundException;
 
        List<LdapEntry> doGetEntries(LdapName searchBase, String filter, boolean deep);
 
@@ -25,8 +25,8 @@ public interface LdapDirectoryDao extends WorkingCopyProcessor<LdapEntryWorkingC
        LdapEntry newUser(LdapName name, Attributes attrs);
 
        LdapEntry newGroup(LdapName name, Attributes attrs);
-       
+
        void init();
-       
+
        void destroy();
 }
index 3fa23e5f1bd32a5851892bd7e0b29df1f52d0fd3..45788b93576ac0757643252aef9cd3080ca295a0 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.util.directory.ldap;
 
+import java.util.Dictionary;
 import java.util.List;
 
 import javax.naming.directory.Attributes;
@@ -13,4 +14,9 @@ public interface LdapEntry {
        void publishAttributes(Attributes modifiedAttributes);
 
        public List<LdapName> getReferences(String attributeId);
+       
+       public Dictionary<String, Object> getProperties();
+
+       public boolean hasCredential(String key, Object value) ;
+
 }
index 5cfca3192b0ce985f8724dac573380e551dbf454..a9043cc38cb13c941982b345a39aeb1f5ce2e129 100644 (file)
@@ -7,7 +7,7 @@ import javax.naming.ldap.Rdn;
 import org.argeo.util.directory.HierarchyUnit;
 
 /** LDIF/LDAP based implementation of {@link HierarchyUnit}. */
-public class LdapHierarchyUnit extends AbstractLdapEntry implements HierarchyUnit {
+public class LdapHierarchyUnit extends DefaultLdapEntry implements HierarchyUnit {
        private final boolean functional;
 
        public LdapHierarchyUnit(AbstractLdapDirectory directory, LdapName dn, Attributes attributes) {
index c805d12725856fce3fb6edd853a833472965c141..5826d86ac1d29324d50f31badf63afcc5bb6a98d 100644 (file)
@@ -217,7 +217,7 @@ public class LdifDao extends AbstractLdapDirectoryDao {
         */
 
        @Override
-       public LdapEntry daoGetEntry(LdapName key) throws NameNotFoundException {
+       public LdapEntry doGetEntry(LdapName key) throws NameNotFoundException {
 //             if (groups.containsKey(key))
 //                     return groups.get(key);
 //             if (users.containsKey(key))
@@ -228,7 +228,7 @@ public class LdifDao extends AbstractLdapDirectoryDao {
        }
 
        @Override
-       public Boolean daoHasEntry(LdapName dn) {
+       public Boolean entryExists(LdapName dn) {
                return entries.containsKey(dn);// || groups.containsKey(dn);
        }
 
@@ -281,7 +281,7 @@ public class LdifDao extends AbstractLdapDirectoryDao {
                entries: for (LdapName name : entries.keySet()) {
                        LdapEntry group;
                        try {
-                               LdapEntry entry = daoGetEntry(name);
+                               LdapEntry entry = doGetEntry(name);
                                if (AbstractLdapDirectory.hasObjectClass(entry.getAttributes(), getDirectory().getGroupObjectClass())) {
                                        group = entry;
                                } else {
@@ -329,7 +329,7 @@ public class LdifDao extends AbstractLdapDirectoryDao {
                        Attributes modifiedAttrs = wc.getModifiedData().get(dn);
                        LdapEntry user;
                        try {
-                               user = daoGetEntry(dn);
+                               user = doGetEntry(dn);
                        } catch (NameNotFoundException e) {
                                throw new IllegalStateException("User to modify no found " + dn, e);
                        }