From a93bccc486bc6334586d9afaabdc5ddfc9211647 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 5 Sep 2015 08:19:02 +0000 Subject: [PATCH] Introduce LDIF persistence git-svn-id: https://svn.argeo.org/commons/trunk@8367 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../osgi/useradmin/LdifUserAdminTest.java | 18 +++++- .../argeo/osgi/useradmin/LdifUserAdmin.java | 28 +++++++++ .../org/argeo/osgi/useradmin/LdifWriter.java | 61 +++++++++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifWriter.java diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java index 52682bf03..051677417 100644 --- a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java +++ b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java @@ -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); diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java index dacae7964..c96f2de66 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java @@ -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 index 000000000..25793c923 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifWriter.java @@ -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 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'); + } + } + } +} -- 2.39.2