]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifUserAdmin.java
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
.ldap
.LdapName
;
23 import org
.apache
.commons
.io
.IOUtils
;
24 import org
.osgi
.framework
.Filter
;
25 import org
.osgi
.service
.useradmin
.Role
;
26 import org
.osgi
.service
.useradmin
.User
;
28 /** User admin implementation using LDIF file(s) as backend. */
29 public class LdifUserAdmin
extends AbstractUserDirectory
{
30 SortedMap
<LdapName
, DirectoryUser
> users
= new TreeMap
<LdapName
, DirectoryUser
>();
31 SortedMap
<LdapName
, DirectoryGroup
> groups
= new TreeMap
<LdapName
, DirectoryGroup
>();
33 private Map
<String
, Map
<String
, DirectoryUser
>> userIndexes
= new LinkedHashMap
<String
, Map
<String
, DirectoryUser
>>();
35 // private Map<LdapName, List<LdifGroup>> directMemberOf = new
36 // TreeMap<LdapName, List<LdifGroup>>();
38 public LdifUserAdmin(String uri
) {
39 this(uri
, readOnlyDefault(uri
));
42 public LdifUserAdmin(String uri
, boolean isReadOnly
) {
43 setReadOnly(isReadOnly
);
46 } catch (URISyntaxException e
) {
47 throw new UserDirectoryException("Invalid URI " + uri
, e
);
50 if (!isReadOnly
&& !getUri().getScheme().equals("file"))
51 throw new UnsupportedOperationException(getUri().getScheme()
52 + " not supported read-write.");
56 public LdifUserAdmin(URI uri
, boolean isReadOnly
) {
57 setReadOnly(isReadOnly
);
59 if (!isReadOnly
&& !getUri().getScheme().equals("file"))
60 throw new UnsupportedOperationException(getUri().getScheme()
61 + " not supported read-write.");
65 public LdifUserAdmin(InputStream in
) {
71 private static boolean readOnlyDefault(String uriStr
) {
74 uri
= new URI(uriStr
);
75 } catch (Exception e
) {
76 throw new UserDirectoryException("Invalid URI " + uriStr
, e
);
78 if (uri
.getScheme().equals("file")) {
79 File file
= new File(uri
);
80 return !file
.canWrite();
87 load(getUri().toURL().openStream());
88 } catch (Exception e
) {
89 throw new UserDirectoryException("Cannot open URL " + getUri(), e
);
94 if (getUri() == null || isReadOnly())
95 throw new UserDirectoryException("Cannot save LDIF user admin");
96 try (FileOutputStream out
= new FileOutputStream(new File(getUri()))) {
98 } catch (IOException e
) {
99 throw new UserDirectoryException("Cannot save user admin to "
104 public void save(OutputStream out
) throws IOException
{
106 LdifWriter ldifWriter
= new LdifWriter(out
);
107 for (LdapName name
: groups
.keySet())
108 ldifWriter
.writeEntry(name
, groups
.get(name
).getAttributes());
109 for (LdapName name
: users
.keySet())
110 ldifWriter
.writeEntry(name
, users
.get(name
).getAttributes());
112 IOUtils
.closeQuietly(out
);
116 protected void load(InputStream in
) {
121 LdifParser ldifParser
= new LdifParser();
122 SortedMap
<LdapName
, Attributes
> allEntries
= ldifParser
.read(in
);
123 for (LdapName key
: allEntries
.keySet()) {
124 Attributes attributes
= allEntries
.get(key
);
125 NamingEnumeration
<?
> objectClasses
= attributes
.get(
126 "objectClass").getAll();
127 objectClasses
: while (objectClasses
.hasMore()) {
128 String objectClass
= objectClasses
.next().toString();
129 if (objectClass
.equals("inetOrgPerson")) {
130 users
.put(key
, new LdifUser(this, key
, attributes
));
132 } else if (objectClass
.equals("groupOfNames")) {
133 groups
.put(key
, new LdifGroup(this, key
, attributes
));
140 // for (LdifGroup group : groups.values())
141 // loadMembers(group);
144 for (String attr
: getIndexedUserProperties())
145 userIndexes
.put(attr
, new TreeMap
<String
, DirectoryUser
>());
147 for (DirectoryUser user
: users
.values()) {
148 Dictionary
<String
, Object
> properties
= user
.getProperties();
149 for (String attr
: getIndexedUserProperties()) {
150 Object value
= properties
.get(attr
);
152 DirectoryUser otherUser
= userIndexes
.get(attr
).put(
153 value
.toString(), user
);
154 if (otherUser
!= null)
155 throw new UserDirectoryException("User " + user
156 + " and user " + otherUser
157 + " both have property " + attr
158 + " set to " + value
);
162 } catch (Exception e
) {
163 throw new UserDirectoryException(
164 "Cannot load user admin service from LDIF", e
);
168 public void destroy() {
175 protected DirectoryUser
daoGetRole(LdapName key
) {
176 if (groups
.containsKey(key
))
177 return groups
.get(key
);
178 if (users
.containsKey(key
))
179 return users
.get(key
);
183 protected Boolean
daoHasRole(LdapName dn
) {
184 return users
.containsKey(dn
) || groups
.containsKey(dn
);
188 // public boolean removeRole(String name) {
189 // LdapName dn = toDn(name);
190 // LdifUser role = null;
191 // if (users.containsKey(dn))
192 // role = users.remove(dn);
193 // else if (groups.containsKey(dn))
194 // role = groups.remove(dn);
196 // throw new UserDirectoryException("There is no role " + name);
199 // for (LdifGroup group : getDirectGroups(role)) {
200 // group.getAttributes().get(getMemberAttributeId())
201 // .remove(dn.toString());
206 protected List
<DirectoryUser
> doGetRoles(Filter f
) {
207 ArrayList
<DirectoryUser
> res
= new ArrayList
<DirectoryUser
>();
209 res
.addAll(users
.values());
210 res
.addAll(groups
.values());
212 // Filter f = FrameworkUtil.createFilter(filter);
213 for (DirectoryUser user
: users
.values())
214 if (f
.match(user
.getProperties()))
216 for (DirectoryUser group
: groups
.values())
217 if (f
.match(group
.getProperties()))
223 protected void doGetUser(String key
, String value
,
224 List
<DirectoryUser
> collectedUsers
) {
226 DirectoryUser user
= userIndexes
.get(key
).get(value
);
228 collectedUsers
.add(user
);
232 protected List
<DirectoryGroup
> getDirectGroups(User user
) {
234 if (user
instanceof LdifUser
)
235 dn
= ((LdifUser
) user
).getDn();
238 dn
= new LdapName(user
.getName());
239 } catch (InvalidNameException e
) {
240 throw new UserDirectoryException("Badly formatted user name "
241 + user
.getName(), e
);
244 List
<DirectoryGroup
> directGroups
= new ArrayList
<DirectoryGroup
>();
245 for (LdapName name
: groups
.keySet()) {
246 DirectoryGroup group
= groups
.get(name
);
247 if (group
.getMemberNames().contains(dn
))
248 directGroups
.add(group
);
254 protected void prepare(WorkingCopy wc
) {
256 for (LdapName dn
: wc
.getDeletedUsers().keySet()) {
257 if (users
.containsKey(dn
))
259 else if (groups
.containsKey(dn
))
262 throw new UserDirectoryException("User to delete no found "
266 for (LdapName dn
: wc
.getNewUsers().keySet()) {
267 DirectoryUser user
= wc
.getNewUsers().get(dn
);
268 if (Role
.USER
== user
.getType())
270 else if (Role
.GROUP
== user
.getType())
271 groups
.put(dn
, (DirectoryGroup
) user
);
273 throw new UserDirectoryException("Unsupported role type "
274 + user
.getType() + " for new user " + dn
);
277 for (LdapName dn
: wc
.getModifiedUsers().keySet()) {
278 Attributes modifiedAttrs
= wc
.getModifiedUsers().get(dn
);
280 if (users
.containsKey(dn
))
281 user
= users
.get(dn
);
282 else if (groups
.containsKey(dn
))
283 user
= groups
.get(dn
);
285 throw new UserDirectoryException("User to modify no found "
287 user
.publishAttributes(modifiedAttrs
);
292 protected void commit(WorkingCopy wc
) {
297 protected void rollback(WorkingCopy wc
) {