]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
Work on userAdmin UI:
[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.InputStream;
4 import java.net.URI;
5 import java.net.URISyntaxException;
6 import java.util.ArrayList;
7 import java.util.Dictionary;
8 import java.util.LinkedHashMap;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.SortedMap;
12 import java.util.TreeMap;
13
14 import javax.naming.InvalidNameException;
15 import javax.naming.NamingEnumeration;
16 import javax.naming.directory.Attributes;
17 import javax.naming.directory.BasicAttributes;
18 import javax.naming.ldap.LdapName;
19 import javax.naming.ldap.Rdn;
20
21 import org.osgi.framework.Filter;
22 import org.osgi.framework.FrameworkUtil;
23 import org.osgi.framework.InvalidSyntaxException;
24 import org.osgi.service.useradmin.Authorization;
25 import org.osgi.service.useradmin.Role;
26 import org.osgi.service.useradmin.User;
27
28 /** User admin implementation using LDIF file(s) as backend. */
29 public class LdifUserAdmin extends AbstractLdapUserAdmin {
30 SortedMap<LdapName, LdifUser> users = new TreeMap<LdapName, LdifUser>();
31 SortedMap<LdapName, LdifGroup> groups = new TreeMap<LdapName, LdifGroup>();
32
33 private Map<String, Map<String, LdifUser>> userIndexes = new LinkedHashMap<String, Map<String, LdifUser>>();
34
35 public LdifUserAdmin(String uri) {
36 this(uri, true);
37 }
38
39 public LdifUserAdmin(String uri, boolean isReadOnly) {
40 setReadOnly(isReadOnly);
41 try {
42 setUri(new URI(uri));
43 } catch (URISyntaxException e) {
44 throw new ArgeoUserAdminException("Invalid URI " + uri, e);
45 }
46
47 if (!isReadOnly && !getUri().getScheme().equals("file:"))
48 throw new UnsupportedOperationException(getUri().getScheme()
49 + "not supported read-write.");
50
51 }
52
53 public LdifUserAdmin(InputStream in) {
54 load(in);
55 setReadOnly(true);
56 setUri(null);
57 }
58
59 public void init() {
60 try {
61 load(getUri().toURL().openStream());
62 } catch (Exception e) {
63 throw new ArgeoUserAdminException("Cannot open URL " + getUri(), e);
64 }
65 }
66
67 protected void load(InputStream in) {
68 try {
69 LdifParser ldifParser = new LdifParser();
70 SortedMap<LdapName, Attributes> allEntries = ldifParser.read(in);
71 for (LdapName key : allEntries.keySet()) {
72 Attributes attributes = allEntries.get(key);
73 NamingEnumeration<?> objectClasses = attributes.get(
74 "objectClass").getAll();
75 objectClasses: while (objectClasses.hasMore()) {
76 String objectClass = objectClasses.next().toString();
77 if (objectClass.equals("inetOrgPerson")) {
78 users.put(key, new LdifUser(key, attributes));
79 break objectClasses;
80 } else if (objectClass.equals("groupOfNames")) {
81 groups.put(key, new LdifGroup(key, attributes));
82 break objectClasses;
83 }
84 }
85 }
86
87 // optimise
88 for (LdifGroup group : groups.values())
89 loadMembers(group);
90
91 // indexes
92 for (String attr : getIndexedUserProperties())
93 userIndexes.put(attr, new TreeMap<String, LdifUser>());
94
95 for (LdifUser user : users.values()) {
96 Dictionary<String, Object> properties = user.getProperties();
97 for (String attr : getIndexedUserProperties()) {
98 Object value = properties.get(attr);
99 if (value != null) {
100 LdifUser otherUser = userIndexes.get(attr).put(
101 value.toString(), user);
102 if (otherUser != null)
103 throw new ArgeoUserAdminException("User " + user
104 + " and user " + otherUser
105 + " both have property " + attr
106 + " set to " + value);
107 }
108 }
109 }
110 } catch (Exception e) {
111 throw new ArgeoUserAdminException(
112 "Cannot load user admin service from LDIF", e);
113 }
114 }
115
116 public void destroy() {
117 users.clear();
118 users = null;
119 groups.clear();
120 groups = null;
121 }
122
123 @Override
124 public Role getRole(String name) {
125 LdapName key;
126 try {
127 key = new LdapName(name);
128 } catch (InvalidNameException e) {
129 // TODO implements default base DN
130 throw new IllegalArgumentException("Badly formatted role name: "
131 + name, e);
132 }
133
134 if (groups.containsKey(key))
135 return groups.get(key);
136 if (users.containsKey(key))
137 return users.get(key);
138 return null;
139 }
140
141 @Override
142 public Authorization getAuthorization(User user) {
143 return new LdifAuthorization((LdifUser) user);
144 }
145
146 @Override
147 public Role createRole(String name, int type) {
148 try {
149 LdapName dn = new LdapName(name);
150 if (users.containsKey(dn) || groups.containsKey(dn))
151 throw new ArgeoUserAdminException("Already a role " + name);
152
153 BasicAttributes attrs = new BasicAttributes();
154 attrs.put("dn", dn.toString());
155 Rdn nameRdn = dn.getRdn(dn.size() - 1);
156 // TODO deal with multiple attr RDN
157 attrs.put(nameRdn.getType(), nameRdn.getValue());
158 LdifUser newRole;
159 if (type == Role.USER) {
160 newRole = new LdifUser(dn, attrs);
161 users.put(dn, newRole);
162 } else if (type == Role.GROUP) {
163 newRole = new LdifGroup(dn, attrs);
164 groups.put(dn, (LdifGroup) newRole);
165 } else
166 throw new ArgeoUserAdminException("Unsupported type " + type);
167 return newRole;
168 } catch (InvalidNameException e) {
169 throw new ArgeoUserAdminException("Cannot create role " + name, e);
170 }
171 }
172
173 @Override
174 public boolean removeRole(String name) {
175 try {
176 LdapName dn = new LdapName(name);
177 LdifUser role = null;
178 if (users.containsKey(dn))
179 role = users.remove(dn);
180 else if (groups.containsKey(dn))
181 role = groups.remove(dn);
182 else
183 throw new ArgeoUserAdminException("There is no role " + name);
184 if (role == null)
185 return false;
186 for (LdifGroup group : role.directMemberOf) {
187 group.directMembers.remove(role);
188 group.getAttributes().get(group.getMemberAttrName())
189 .remove(dn.toString());
190 }
191 if (role instanceof LdifGroup) {
192 LdifGroup group = (LdifGroup) role;
193 for (Role user : group.directMembers) {
194 if (user instanceof LdifUser)
195 ((LdifUser) user).directMemberOf.remove(group);
196 }
197 }
198 return true;
199 } catch (InvalidNameException e) {
200 throw new ArgeoUserAdminException("Cannot create role " + name, e);
201 }
202 }
203
204 @Override
205 public Role[] getRoles(String filter) throws InvalidSyntaxException {
206 ArrayList<Role> res = new ArrayList<Role>();
207 if (filter == null) {
208 res.addAll(users.values());
209 res.addAll(groups.values());
210 } else {
211 Filter f = FrameworkUtil.createFilter(filter);
212 for (LdifUser user : users.values())
213 if (f.match(user.getProperties()))
214 res.add(user);
215 for (LdifUser group : groups.values())
216 if (f.match(group.getProperties()))
217 res.add(group);
218 }
219 return res.toArray(new Role[res.size()]);
220 }
221
222 @Override
223 public User getUser(String key, String value) {
224 // TODO check value null or empty
225 if (key != null) {
226 if (!userIndexes.containsKey(key))
227 return null;
228 return userIndexes.get(key).get(value);
229 }
230
231 // Try all indexes
232 List<LdifUser> collectedUsers = new ArrayList<LdifUser>(
233 getIndexedUserProperties().size());
234 // try dn
235 LdifUser user = null;
236 try {
237 user = (LdifUser) getRole(value);
238 if (user != null)
239 collectedUsers.add(user);
240 } catch (Exception e) {
241 // silent
242 }
243 for (String attr : userIndexes.keySet()) {
244 user = userIndexes.get(attr).get(value);
245 if (user != null)
246 collectedUsers.add(user);
247 }
248
249 if (collectedUsers.size() == 1)
250 return collectedUsers.get(0);
251 return null;
252 // throw new UnsupportedOperationException();
253 }
254
255 protected void loadMembers(LdifGroup group) {
256 group.directMembers = new ArrayList<Role>();
257 for (LdapName ldapName : group.getMemberNames()) {
258 LdifUser role = null;
259 if (groups.containsKey(ldapName))
260 role = groups.get(ldapName);
261 else if (users.containsKey(ldapName))
262 role = users.get(ldapName);
263 else {
264 if (getExternalRoles() != null)
265 role = (LdifUser) getExternalRoles().getRole(
266 ldapName.toString());
267 if (role == null)
268 throw new ArgeoUserAdminException("No role found for "
269 + ldapName);
270 }
271 role.directMemberOf.add(group);
272 group.directMembers.add(role);
273 }
274 }
275
276 }