]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
Fix URI when using default LDIF
[lgpl/argeo-commons.git] / org.argeo.security.core / src / org / argeo / osgi / useradmin / LdifUserAdmin.java
1 package org.argeo.osgi.useradmin;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.util.ArrayList;
9 import java.util.Dictionary;
10 import java.util.Hashtable;
11 import java.util.List;
12 import java.util.SortedMap;
13 import java.util.TreeMap;
14
15 import javax.naming.NamingEnumeration;
16 import javax.naming.directory.Attributes;
17 import javax.naming.ldap.LdapName;
18 import javax.transaction.TransactionManager;
19
20 import org.apache.commons.io.IOUtils;
21 import org.osgi.framework.Filter;
22 import org.osgi.service.useradmin.Role;
23
24 /**
25 * A user admin based on a LDIF files. Requires a {@link TransactionManager} and
26 * an open transaction for write access.
27 */
28 public class LdifUserAdmin extends AbstractUserDirectory {
29 private SortedMap<LdapName, DirectoryUser> users = new TreeMap<LdapName, DirectoryUser>();
30 private SortedMap<LdapName, DirectoryGroup> groups = new TreeMap<LdapName, DirectoryGroup>();
31
32 public LdifUserAdmin(String uri, String baseDn) {
33 this(fromUri(uri, baseDn));
34 }
35
36 public LdifUserAdmin(Dictionary<String, ?> properties) {
37 super(properties);
38 }
39
40 public LdifUserAdmin(InputStream in) {
41 super(new Hashtable<String, Object>());
42 load(in);
43 }
44
45 private static Dictionary<String, Object> fromUri(String uri, String baseDn) {
46 Hashtable<String, Object> res = new Hashtable<String, Object>();
47 res.put(UserAdminConf.uri.property(), uri);
48 res.put(UserAdminConf.baseDn.property(), baseDn);
49 return res;
50 }
51
52 public void init() {
53 try {
54 if (getUri().getScheme().equals("file")) {
55 File file = new File(getUri());
56 if (!file.exists())
57 return;
58 }
59 load(getUri().toURL().openStream());
60 } catch (Exception e) {
61 throw new UserDirectoryException("Cannot open URL " + getUri(), e);
62 }
63 }
64
65 public void save() {
66 if (getUri() == null)
67 throw new UserDirectoryException(
68 "Cannot save LDIF user admin: no URI is set");
69 if (isReadOnly())
70 throw new UserDirectoryException("Cannot save LDIF user admin: "
71 + getUri() + " is read-only");
72 try (FileOutputStream out = new FileOutputStream(new File(getUri()))) {
73 save(out);
74 } catch (IOException e) {
75 throw new UserDirectoryException("Cannot save user admin to "
76 + getUri(), e);
77 }
78 }
79
80 public void save(OutputStream out) throws IOException {
81 try {
82 LdifWriter ldifWriter = new LdifWriter(out);
83 for (LdapName name : groups.keySet())
84 ldifWriter.writeEntry(name, groups.get(name).getAttributes());
85 for (LdapName name : users.keySet())
86 ldifWriter.writeEntry(name, users.get(name).getAttributes());
87 } finally {
88 IOUtils.closeQuietly(out);
89 }
90 }
91
92 protected void load(InputStream in) {
93 try {
94 users.clear();
95 groups.clear();
96
97 LdifParser ldifParser = new LdifParser();
98 SortedMap<LdapName, Attributes> allEntries = ldifParser.read(in);
99 for (LdapName key : allEntries.keySet()) {
100 Attributes attributes = allEntries.get(key);
101 NamingEnumeration<?> objectClasses = attributes.get(
102 "objectClass").getAll();
103 objectClasses: while (objectClasses.hasMore()) {
104 String objectClass = objectClasses.next().toString();
105 if (objectClass.equals("inetOrgPerson")) {
106 users.put(key, new LdifUser(this, key, attributes));
107 break objectClasses;
108 } else if (objectClass.equals("groupOfNames")) {
109 groups.put(key, new LdifGroup(this, key, attributes));
110 break objectClasses;
111 }
112 }
113 }
114 } catch (Exception e) {
115 throw new UserDirectoryException(
116 "Cannot load user admin service from LDIF", e);
117 }
118 }
119
120 public void destroy() {
121 users.clear();
122 users = null;
123 groups.clear();
124 groups = null;
125 }
126
127 protected DirectoryUser daoGetRole(LdapName key) {
128 if (groups.containsKey(key))
129 return groups.get(key);
130 if (users.containsKey(key))
131 return users.get(key);
132 return null;
133 }
134
135 protected Boolean daoHasRole(LdapName dn) {
136 return users.containsKey(dn) || groups.containsKey(dn);
137 }
138
139 @SuppressWarnings("unchecked")
140 protected List<DirectoryUser> doGetRoles(Filter f) {
141 ArrayList<DirectoryUser> res = new ArrayList<DirectoryUser>();
142 if (f == null) {
143 res.addAll(users.values());
144 res.addAll(groups.values());
145 } else {
146 // Filter f = FrameworkUtil.createFilter(filter);
147 for (DirectoryUser user : users.values())
148 if (f.match(user.getProperties()))
149 res.add(user);
150 for (DirectoryUser group : groups.values())
151 if (f.match(group.getProperties()))
152 res.add(group);
153 }
154 return res;
155 }
156
157 @Override
158 protected List<LdapName> getDirectGroups(LdapName dn) {
159 List<LdapName> directGroups = new ArrayList<LdapName>();
160 for (LdapName name : groups.keySet()) {
161 DirectoryGroup group = groups.get(name);
162 if (group.getMemberNames().contains(dn))
163 directGroups.add(group.getDn());
164 }
165 return directGroups;
166 }
167
168 @Override
169 protected void prepare(UserDirectoryWorkingCopy wc) {
170 // delete
171 for (LdapName dn : wc.getDeletedUsers().keySet()) {
172 if (users.containsKey(dn))
173 users.remove(dn);
174 else if (groups.containsKey(dn))
175 groups.remove(dn);
176 else
177 throw new UserDirectoryException("User to delete no found "
178 + dn);
179 }
180 // add
181 for (LdapName dn : wc.getNewUsers().keySet()) {
182 DirectoryUser user = wc.getNewUsers().get(dn);
183 if (Role.USER == user.getType())
184 users.put(dn, user);
185 else if (Role.GROUP == user.getType())
186 groups.put(dn, (DirectoryGroup) user);
187 else
188 throw new UserDirectoryException("Unsupported role type "
189 + user.getType() + " for new user " + dn);
190 }
191 // modify
192 for (LdapName dn : wc.getModifiedUsers().keySet()) {
193 Attributes modifiedAttrs = wc.getModifiedUsers().get(dn);
194 DirectoryUser user;
195 if (users.containsKey(dn))
196 user = users.get(dn);
197 else if (groups.containsKey(dn))
198 user = groups.get(dn);
199 else
200 throw new UserDirectoryException("User to modify no found "
201 + dn);
202 user.publishAttributes(modifiedAttrs);
203 }
204 }
205
206 @Override
207 protected void commit(UserDirectoryWorkingCopy wc) {
208 save();
209 }
210
211 @Override
212 protected void rollback(UserDirectoryWorkingCopy wc) {
213 init();
214 }
215
216 }