Introduce LDIF persistence
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 5 Sep 2015 08:19:02 +0000 (08:19 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 5 Sep 2015 08:19:02 +0000 (08:19 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8367 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifWriter.java [new file with mode: 0644]

index 52682bf03ba85ce71b63d1f027178c49ab6e5309..05167741781ef21b490ae5e3412ea8f40912a972 100644 (file)
@@ -1,5 +1,7 @@
 package org.argeo.osgi.useradmin;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.util.Arrays;
 import java.util.List;
 
@@ -7,6 +9,7 @@ import junit.framework.TestCase;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.IOUtils;
 import org.osgi.service.useradmin.Authorization;
 import org.osgi.service.useradmin.Group;
 import org.osgi.service.useradmin.Role;
@@ -15,8 +18,19 @@ import org.osgi.service.useradmin.User;
 public class LdifUserAdminTest extends TestCase implements BasicTestConstants {
 
        public void testBasicUserAdmin() throws Exception {
-               LdifUserAdmin userAdmin = new LdifUserAdmin(getClass()
+               // read
+               LdifUserAdmin initialUserAdmin = new LdifUserAdmin(getClass()
                                .getResourceAsStream("basic.ldif"));
+               // write
+               ByteArrayOutputStream out = new ByteArrayOutputStream();
+               initialUserAdmin.save(out);
+               byte[] arr = out.toByteArray();
+               initialUserAdmin.destroy();
+               IOUtils.closeQuietly(out);
+               String written = new String(arr);
+               System.out.print(written);
+               ByteArrayInputStream in = new ByteArrayInputStream(arr);
+               LdifUserAdmin userAdmin = new LdifUserAdmin(in);
 
                // users
                User rootUser = (User) userAdmin.getRole(ROOT_USER_DN);
@@ -54,7 +68,7 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants {
                                .getBytes();
                assertTrue(rootUser.hasCredential("userpassword", hashedPassword));
                assertTrue(demoUser.hasCredential("userpassword", hashedPassword));
-               
+
                // search
                Role[] search = userAdmin.getRoles(null);
                assertEquals(4, search.length);
index dacae7964f1ee74a24415529655fbd7940133a44..c96f2de6625e4af88f0bdae5d32c8f2e9768c7c8 100644 (file)
@@ -1,6 +1,10 @@
 package org.argeo.osgi.useradmin;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
@@ -18,6 +22,7 @@ import javax.naming.directory.BasicAttributes;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 
+import org.apache.commons.io.IOUtils;
 import org.osgi.framework.Filter;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
@@ -64,6 +69,29 @@ public class LdifUserAdmin extends AbstractLdapUserAdmin {
                }
        }
 
+       public void save() {
+               if (getUri() == null || isReadOnly())
+                       throw new ArgeoUserAdminException("Cannot save LDIF user admin");
+               try (FileOutputStream out = new FileOutputStream(new File(getUri()))) {
+                       save(out);
+               } catch (IOException e) {
+                       throw new ArgeoUserAdminException("Cannot save user admin to "
+                                       + getUri(), e);
+               }
+       }
+
+       public void save(OutputStream out) throws IOException {
+               try {
+                       LdifWriter ldifWriter = new LdifWriter(out);
+                       for (LdapName name : groups.keySet())
+                               ldifWriter.writeEntry(name, groups.get(name).getAttributes());
+                       for (LdapName name : users.keySet())
+                               ldifWriter.writeEntry(name, users.get(name).getAttributes());
+               } finally {
+                       IOUtils.closeQuietly(out);
+               }
+       }
+
        protected void load(InputStream in) {
                try {
                        LdifParser ldifParser = new LdifParser();
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifWriter.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifWriter.java
new file mode 100644 (file)
index 0000000..25793c9
--- /dev/null
@@ -0,0 +1,61 @@
+package org.argeo.osgi.useradmin;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.apache.commons.codec.binary.Base64;
+
+/** Basic LDIF writer */
+public class LdifWriter {
+       private final Writer writer;
+
+       public LdifWriter(OutputStream out) {
+               this.writer = new OutputStreamWriter(out);
+       }
+
+       void writeEntry(LdapName name, Attributes attributes) throws IOException {
+               try {
+                       // TODO check consistency of DN with attributes
+                       writer.append("dn:").append(name.toString()).append('\n');
+                       Attribute objectClassAttr = attributes.get("objectClass");
+                       if (objectClassAttr != null)
+                               writeAttribute(objectClassAttr);
+                       for (NamingEnumeration<? extends Attribute> attrs = attributes
+                                       .getAll(); attrs.hasMore();) {
+                               Attribute attribute = attrs.next();
+                               if (attribute.getID().equals("dn")
+                                               || attribute.getID().equals("objectClass"))
+                                       continue;// skip DN attribute
+                               writeAttribute(attribute);
+                       }
+                       writer.append('\n');
+                       writer.flush();
+               } catch (NamingException e) {
+                       throw new ArgeoUserAdminException("Cannot write LDIF", e);
+               }
+       }
+
+       private void writeAttribute(Attribute attribute) throws NamingException,
+                       IOException {
+               for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues
+                               .hasMore();) {
+                       Object value = attrValues.next();
+                       if (value instanceof byte[]) {
+                               String encoded = Base64.encodeBase64String((byte[]) value);
+                               writer.append(attribute.getID()).append("::").append(encoded)
+                                               .append('\n');
+                       } else {
+                               writer.append(attribute.getID()).append(':')
+                                               .append(value.toString()).append('\n');
+                       }
+               }
+       }
+}