]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
c5ca49300425ad2910d361b2253c9e5728d7de35
1 package org
.argeo
.osgi
.useradmin
;
4 import java
.io
.FileOutputStream
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
7 import java
.io
.OutputStream
;
9 import java
.net
.URISyntaxException
;
10 import java
.util
.ArrayList
;
11 import java
.util
.Dictionary
;
12 import java
.util
.LinkedHashMap
;
13 import java
.util
.List
;
15 import java
.util
.SortedMap
;
16 import java
.util
.TreeMap
;
18 import javax
.naming
.InvalidNameException
;
19 import javax
.naming
.NamingEnumeration
;
20 import javax
.naming
.directory
.Attributes
;
21 import javax
.naming
.directory
.BasicAttributes
;
22 import javax
.naming
.ldap
.LdapName
;
23 import javax
.naming
.ldap
.Rdn
;
25 import org
.apache
.commons
.io
.IOUtils
;
26 import org
.osgi
.framework
.Filter
;
27 import org
.osgi
.framework
.FrameworkUtil
;
28 import org
.osgi
.framework
.InvalidSyntaxException
;
29 import org
.osgi
.service
.useradmin
.Authorization
;
30 import org
.osgi
.service
.useradmin
.Role
;
31 import org
.osgi
.service
.useradmin
.User
;
33 /** User admin implementation using LDIF file(s) as backend. */
34 public class LdifUserAdmin
extends AbstractLdapUserAdmin
{
35 SortedMap
<LdapName
, LdifUser
> users
= new TreeMap
<LdapName
, LdifUser
>();
36 SortedMap
<LdapName
, LdifGroup
> groups
= new TreeMap
<LdapName
, LdifGroup
>();
38 private Map
<String
, Map
<String
, LdifUser
>> userIndexes
= new LinkedHashMap
<String
, Map
<String
, LdifUser
>>();
40 // private Map<LdapName, List<LdifGroup>> directMemberOf = new
41 // TreeMap<LdapName, List<LdifGroup>>();
43 public LdifUserAdmin(String uri
) {
47 public LdifUserAdmin(String uri
, boolean isReadOnly
) {
48 setReadOnly(isReadOnly
);
51 } catch (URISyntaxException e
) {
52 throw new ArgeoUserAdminException("Invalid URI " + uri
, e
);
55 if (!isReadOnly
&& !getUri().getScheme().equals("file:"))
56 throw new UnsupportedOperationException(getUri().getScheme()
57 + "not supported read-write.");
61 public LdifUserAdmin(InputStream in
) {
69 load(getUri().toURL().openStream());
70 } catch (Exception e
) {
71 throw new ArgeoUserAdminException("Cannot open URL " + getUri(), e
);
76 if (getUri() == null || isReadOnly())
77 throw new ArgeoUserAdminException("Cannot save LDIF user admin");
78 try (FileOutputStream out
= new FileOutputStream(new File(getUri()))) {
80 } catch (IOException e
) {
81 throw new ArgeoUserAdminException("Cannot save user admin to "
86 public void save(OutputStream out
) throws IOException
{
88 LdifWriter ldifWriter
= new LdifWriter(out
);
89 for (LdapName name
: groups
.keySet())
90 ldifWriter
.writeEntry(name
, groups
.get(name
).getAttributes());
91 for (LdapName name
: users
.keySet())
92 ldifWriter
.writeEntry(name
, users
.get(name
).getAttributes());
94 IOUtils
.closeQuietly(out
);
98 protected void load(InputStream in
) {
100 LdifParser ldifParser
= new LdifParser();
101 SortedMap
<LdapName
, Attributes
> allEntries
= ldifParser
.read(in
);
102 for (LdapName key
: allEntries
.keySet()) {
103 Attributes attributes
= allEntries
.get(key
);
104 NamingEnumeration
<?
> objectClasses
= attributes
.get(
105 "objectClass").getAll();
106 objectClasses
: while (objectClasses
.hasMore()) {
107 String objectClass
= objectClasses
.next().toString();
108 if (objectClass
.equals("inetOrgPerson")) {
109 users
.put(key
, new LdifUser(key
, attributes
));
111 } else if (objectClass
.equals("groupOfNames")) {
112 groups
.put(key
, new LdifGroup(this, key
, attributes
));
119 // for (LdifGroup group : groups.values())
120 // loadMembers(group);
123 for (String attr
: getIndexedUserProperties())
124 userIndexes
.put(attr
, new TreeMap
<String
, LdifUser
>());
126 for (LdifUser user
: users
.values()) {
127 Dictionary
<String
, Object
> properties
= user
.getProperties();
128 for (String attr
: getIndexedUserProperties()) {
129 Object value
= properties
.get(attr
);
131 LdifUser otherUser
= userIndexes
.get(attr
).put(
132 value
.toString(), user
);
133 if (otherUser
!= null)
134 throw new ArgeoUserAdminException("User " + user
135 + " and user " + otherUser
136 + " both have property " + attr
137 + " set to " + value
);
141 } catch (Exception e
) {
142 throw new ArgeoUserAdminException(
143 "Cannot load user admin service from LDIF", e
);
147 public void destroy() {
155 public Role
getRole(String name
) {
158 key
= new LdapName(name
);
159 } catch (InvalidNameException e
) {
160 // TODO implements default base DN
161 throw new IllegalArgumentException("Badly formatted role name: "
165 if (groups
.containsKey(key
))
166 return groups
.get(key
);
167 if (users
.containsKey(key
))
168 return users
.get(key
);
173 public Authorization
getAuthorization(User user
) {
174 return new LdifAuthorization((LdifUser
) user
,
175 getAllRoles((LdifUser
) user
));
179 public Role
createRole(String name
, int type
) {
181 LdapName dn
= new LdapName(name
);
182 if (users
.containsKey(dn
) || groups
.containsKey(dn
))
183 throw new ArgeoUserAdminException("Already a role " + name
);
185 BasicAttributes attrs
= new BasicAttributes();
186 attrs
.put("dn", dn
.toString());
187 Rdn nameRdn
= dn
.getRdn(dn
.size() - 1);
188 // TODO deal with multiple attr RDN
189 attrs
.put(nameRdn
.getType(), nameRdn
.getValue());
191 if (type
== Role
.USER
) {
192 newRole
= new LdifUser(dn
, attrs
);
193 users
.put(dn
, newRole
);
194 } else if (type
== Role
.GROUP
) {
195 newRole
= new LdifGroup(this, dn
, attrs
);
196 groups
.put(dn
, (LdifGroup
) newRole
);
198 throw new ArgeoUserAdminException("Unsupported type " + type
);
200 } catch (InvalidNameException e
) {
201 throw new ArgeoUserAdminException("Cannot create role " + name
, e
);
206 public boolean removeRole(String name
) {
208 LdapName dn
= new LdapName(name
);
209 LdifUser role
= null;
210 if (users
.containsKey(dn
))
211 role
= users
.remove(dn
);
212 else if (groups
.containsKey(dn
))
213 role
= groups
.remove(dn
);
215 throw new ArgeoUserAdminException("There is no role " + name
);
218 for (LdifGroup group
: getDirectGroups(role
)) {
219 // group.directMembers.remove(role);
220 group
.getAttributes().get(group
.getMemberAttrName())
221 .remove(dn
.toString());
223 if (role
instanceof LdifGroup
) {
224 LdifGroup group
= (LdifGroup
) role
;
225 // for (Role user : group.directMembers) {
226 // if (user instanceof LdifUser)
227 // directMemberOf.get(((LdifUser) user).getDn()).remove(
232 } catch (InvalidNameException e
) {
233 throw new ArgeoUserAdminException("Cannot create role " + name
, e
);
238 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
239 ArrayList
<Role
> res
= new ArrayList
<Role
>();
240 if (filter
== null) {
241 res
.addAll(users
.values());
242 res
.addAll(groups
.values());
244 Filter f
= FrameworkUtil
.createFilter(filter
);
245 for (LdifUser user
: users
.values())
246 if (f
.match(user
.getProperties()))
248 for (LdifUser group
: groups
.values())
249 if (f
.match(group
.getProperties()))
252 return res
.toArray(new Role
[res
.size()]);
256 public User
getUser(String key
, String value
) {
257 // TODO check value null or empty
259 if (!userIndexes
.containsKey(key
))
261 return userIndexes
.get(key
).get(value
);
265 List
<LdifUser
> collectedUsers
= new ArrayList
<LdifUser
>(
266 getIndexedUserProperties().size());
268 LdifUser user
= null;
270 user
= (LdifUser
) getRole(value
);
272 collectedUsers
.add(user
);
273 } catch (Exception e
) {
276 for (String attr
: userIndexes
.keySet()) {
277 user
= userIndexes
.get(attr
).get(value
);
279 collectedUsers
.add(user
);
282 if (collectedUsers
.size() == 1)
283 return collectedUsers
.get(0);
285 // throw new UnsupportedOperationException();
288 // protected void loadMembers(LdifGroup group) {
289 // group.directMembers = new ArrayList<Role>();
290 // for (LdapName ldapName : group.getMemberNames()) {
291 // LdifUser role = null;
292 // if (groups.containsKey(ldapName))
293 // role = groups.get(ldapName);
294 // else if (users.containsKey(ldapName))
295 // role = users.get(ldapName);
297 // if (getExternalRoles() != null)
298 // role = (LdifUser) getExternalRoles().getRole(
299 // ldapName.toString());
301 // throw new ArgeoUserAdminException("No role found for "
304 // // role.directMemberOf.add(group);
305 // // if (!directMemberOf.containsKey(role.getDn()))
306 // // directMemberOf.put(role.getDn(), new ArrayList<LdifGroup>());
307 // // directMemberOf.get(role.getDn()).add(group);
308 // group.directMembers.add(role);
313 protected List
<LdifGroup
> getDirectGroups(User user
) {
315 if (user
instanceof LdifUser
)
316 dn
= ((LdifUser
) user
).getDn();
319 dn
= new LdapName(user
.getName());
320 } catch (InvalidNameException e
) {
321 throw new ArgeoUserAdminException("Badly formatted user name "
322 + user
.getName(), e
);
325 List
<LdifGroup
> directGroups
= new ArrayList
<LdifGroup
>();
326 for (LdapName name
: groups
.keySet()) {
327 LdifGroup group
= groups
.get(name
);
328 if (group
.getMemberNames().contains(dn
))
329 directGroups
.add(group
);
332 // if (directMemberOf.containsKey(dn))
333 // return Collections.unmodifiableList(directMemberOf.get(dn));
335 // return Collections.EMPTY_LIST;