1 package org
.argeo
.cms
.internal
.kernel
;
4 import java
.io
.IOException
;
6 import java
.net
.URISyntaxException
;
7 import java
.util
.ArrayList
;
8 import java
.util
.Arrays
;
9 import java
.util
.Dictionary
;
10 import java
.util
.HashMap
;
11 import java
.util
.HashSet
;
12 import java
.util
.Hashtable
;
13 import java
.util
.List
;
17 import javax
.naming
.InvalidNameException
;
18 import javax
.naming
.ldap
.LdapName
;
19 import javax
.transaction
.TransactionManager
;
21 import org
.apache
.commons
.io
.FileUtils
;
22 import org
.apache
.commons
.logging
.Log
;
23 import org
.apache
.commons
.logging
.LogFactory
;
24 import org
.argeo
.cms
.CmsException
;
25 import org
.argeo
.cms
.KernelHeader
;
26 import org
.argeo
.osgi
.useradmin
.UserDirectory
;
27 import org
.argeo
.osgi
.useradmin
.UserAdminConf
;
28 import org
.argeo
.osgi
.useradmin
.LdapUserAdmin
;
29 import org
.argeo
.osgi
.useradmin
.LdifUserAdmin
;
30 import org
.argeo
.osgi
.useradmin
.UserDirectoryException
;
31 import org
.osgi
.framework
.InvalidSyntaxException
;
32 import org
.osgi
.service
.useradmin
.Authorization
;
33 import org
.osgi
.service
.useradmin
.Role
;
34 import org
.osgi
.service
.useradmin
.User
;
35 import org
.osgi
.service
.useradmin
.UserAdmin
;
37 public class NodeUserAdmin
implements UserAdmin
{
38 private final static Log log
= LogFactory
.getLog(NodeUserAdmin
.class);
39 final static LdapName ROLES_BASE
;
42 ROLES_BASE
= new LdapName(KernelHeader
.ROLES_BASEDN
);
43 } catch (InvalidNameException e
) {
44 throw new UserDirectoryException("Cannot initialize "
45 + NodeUserAdmin
.class, e
);
49 private UserAdmin nodeRoles
= null;
50 private Map
<LdapName
, UserAdmin
> userAdmins
= new HashMap
<LdapName
, UserAdmin
>();
52 public NodeUserAdmin() {
53 File osgiInstanceDir
= KernelUtils
.getOsgiInstanceDir();
54 File nodeBaseDir
= new File(osgiInstanceDir
, "node");
57 String userAdminUri
= KernelUtils
58 .getFrameworkProp(KernelConstants
.USERADMIN_URIS
);
59 if (userAdminUri
== null) {
60 String demoBaseDn
= "dc=example,dc=com";
61 File businessRolesFile
= new File(nodeBaseDir
, demoBaseDn
+ ".ldif");
62 if (!businessRolesFile
.exists())
64 FileUtils
.copyInputStreamToFile(getClass()
65 .getResourceAsStream(demoBaseDn
+ ".ldif"),
67 } catch (IOException e
) {
68 throw new CmsException("Cannot copy demo resource", e
);
70 userAdminUri
= businessRolesFile
.toURI().toString();
73 String
[] uris
= userAdminUri
.split(" ");
74 for (String uri
: uris
) {
78 if (u
.getScheme() == null) {
79 if (uri
.startsWith("/"))
80 u
= new File(uri
).getAbsoluteFile().toURI();
81 else if (!uri
.contains("/"))
82 u
= new File(nodeBaseDir
, uri
).getAbsoluteFile()
85 throw new CmsException("Cannot interpret " + uri
88 } catch (URISyntaxException e
) {
89 throw new CmsException(
90 "Cannot interpret " + uri
+ " as an uri", e
);
92 Dictionary
<String
, ?
> properties
= UserAdminConf
.uriAsProperties(u
94 UserDirectory businessRoles
;
95 if (u
.getScheme().startsWith("ldap")) {
96 businessRoles
= new LdapUserAdmin(properties
);
98 businessRoles
= new LdifUserAdmin(properties
);
100 businessRoles
.init();
101 addUserAdmin(businessRoles
.getBaseDn(), (UserAdmin
) businessRoles
);
102 if (log
.isDebugEnabled())
103 log
.debug("User directory " + businessRoles
.getBaseDn() + " ["
104 + u
.getScheme() + "] enabled.");
108 String nodeRolesUri
= KernelUtils
109 .getFrameworkProp(KernelConstants
.ROLES_URI
);
110 String baseNodeRoleDn
= KernelHeader
.ROLES_BASEDN
;
111 if (nodeRolesUri
== null) {
112 File nodeRolesFile
= new File(nodeBaseDir
, baseNodeRoleDn
+ ".ldif");
113 if (!nodeRolesFile
.exists())
115 FileUtils
.copyInputStreamToFile(getClass()
116 .getResourceAsStream("demo.ldif"), nodeRolesFile
);
117 } catch (IOException e
) {
118 throw new CmsException("Cannot copy demo resource", e
);
120 nodeRolesUri
= nodeRolesFile
.toURI().toString();
123 Dictionary
<String
, ?
> nodeRolesProperties
= UserAdminConf
124 .uriAsProperties(nodeRolesUri
);
125 if (!nodeRolesProperties
.get(UserAdminConf
.baseDn
.property())
126 .equals(baseNodeRoleDn
)) {
127 throw new CmsException("Invalid base dn for node roles");
128 // TODO deal with "mounted" roles with a different baseDN
130 UserDirectory nodeRoles
;
131 if (nodeRolesUri
.startsWith("ldap")) {
132 nodeRoles
= new LdapUserAdmin(nodeRolesProperties
);
134 nodeRoles
= new LdifUserAdmin(nodeRolesProperties
);
136 nodeRoles
.setExternalRoles(this);
138 addUserAdmin(baseNodeRoleDn
, (UserAdmin
)nodeRoles
);
139 if (log
.isTraceEnabled())
140 log
.trace("Node roles enabled.");
143 Dictionary
<String
, ?
> currentState() {
144 Dictionary
<String
, Object
> res
= new Hashtable
<String
, Object
>();
145 for (LdapName name
: userAdmins
.keySet()) {
146 StringBuilder buf
= new StringBuilder();
147 if (userAdmins
.get(name
) instanceof UserDirectory
) {
148 UserDirectory userDirectory
= (UserDirectory
) userAdmins
150 String uri
= UserAdminConf
.propertiesAsUri(
151 userDirectory
.getProperties()).toString();
154 buf
.append('/').append(name
.toString())
155 .append("?readOnly=true");
161 public void destroy() {
162 for (LdapName name
: userAdmins
.keySet()) {
163 if (userAdmins
.get(name
) instanceof UserDirectory
) {
164 UserDirectory userDirectory
= (UserDirectory
) userAdmins
166 userDirectory
.destroy();
172 public Role
createRole(String name
, int type
) {
173 return findUserAdmin(name
).createRole(name
, type
);
177 public boolean removeRole(String name
) {
178 return findUserAdmin(name
).removeRole(name
);
182 public Role
getRole(String name
) {
183 return findUserAdmin(name
).getRole(name
);
187 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
188 List
<Role
> res
= new ArrayList
<Role
>();
189 for (UserAdmin userAdmin
: userAdmins
.values()) {
190 res
.addAll(Arrays
.asList(userAdmin
.getRoles(filter
)));
192 res
.addAll(Arrays
.asList(nodeRoles
.getRoles(filter
)));
193 return res
.toArray(new Role
[res
.size()]);
197 public User
getUser(String key
, String value
) {
198 List
<User
> res
= new ArrayList
<User
>();
199 for (UserAdmin userAdmin
: userAdmins
.values()) {
200 User u
= userAdmin
.getUser(key
, value
);
204 // Note: node roles cannot contain users, so it is not searched
205 return res
.size() == 1 ? res
.get(0) : null;
209 public Authorization
getAuthorization(User user
) {
211 return nodeRoles
.getAuthorization(null);
213 UserAdmin userAdmin
= findUserAdmin(user
.getName());
214 Authorization rawAuthorization
= userAdmin
.getAuthorization(user
);
215 // gather system roles
216 Set
<String
> systemRoles
= new HashSet
<String
>();
217 for (String role
: rawAuthorization
.getRoles()) {
218 Authorization auth
= nodeRoles
.getAuthorization((User
) userAdmin
220 systemRoles
.addAll(Arrays
.asList(auth
.getRoles()));
222 return new NodeAuthorization(rawAuthorization
.getName(),
223 rawAuthorization
.toString(), systemRoles
,
224 rawAuthorization
.getRoles());
228 // USER ADMIN AGGREGATOR
230 public synchronized void addUserAdmin(String baseDn
, UserAdmin userAdmin
) {
231 if (baseDn
.equals(KernelHeader
.ROLES_BASEDN
)) {
232 nodeRoles
= userAdmin
;
236 if (userAdmins
.containsKey(baseDn
))
237 throw new UserDirectoryException(
238 "There is already a user admin for " + baseDn
);
240 userAdmins
.put(new LdapName(baseDn
), userAdmin
);
241 } catch (InvalidNameException e
) {
242 throw new UserDirectoryException("Badly formatted base DN "
247 public synchronized void removeUserAdmin(String baseDn
) {
248 if (baseDn
.equals(KernelHeader
.ROLES_BASEDN
))
249 throw new UserDirectoryException("Node roles cannot be removed.");
252 base
= new LdapName(baseDn
);
253 } catch (InvalidNameException e
) {
254 throw new UserDirectoryException("Badly formatted base DN "
257 if (!userAdmins
.containsKey(base
))
258 throw new UserDirectoryException("There is no user admin for "
260 userAdmins
.remove(base
);
263 private UserAdmin
findUserAdmin(String name
) {
265 return findUserAdmin(new LdapName(name
));
266 } catch (InvalidNameException e
) {
267 throw new UserDirectoryException("Badly formatted name " + name
, e
);
271 private UserAdmin
findUserAdmin(LdapName name
) {
272 if (name
.startsWith(ROLES_BASE
))
274 List
<UserAdmin
> res
= new ArrayList
<UserAdmin
>(1);
275 for (LdapName baseDn
: userAdmins
.keySet()) {
276 if (name
.startsWith(baseDn
))
277 res
.add(userAdmins
.get(baseDn
));
280 throw new UserDirectoryException("Cannot find user admin for "
283 throw new UserDirectoryException("Multiple user admin found for "
288 public void setTransactionManager(TransactionManager transactionManager
) {
289 if (nodeRoles
instanceof UserDirectory
)
290 ((UserDirectory
) nodeRoles
)
291 .setTransactionManager(transactionManager
);
292 for (UserAdmin userAdmin
: userAdmins
.values()) {
293 if (userAdmin
instanceof UserDirectory
)
294 ((UserDirectory
) userAdmin
)
295 .setTransactionManager(transactionManager
);