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
.List
;
16 import javax
.naming
.InvalidNameException
;
17 import javax
.naming
.ldap
.LdapName
;
18 import javax
.transaction
.TransactionManager
;
20 import org
.apache
.commons
.io
.FileUtils
;
21 import org
.apache
.commons
.logging
.Log
;
22 import org
.apache
.commons
.logging
.LogFactory
;
23 import org
.argeo
.cms
.CmsException
;
24 import org
.argeo
.cms
.KernelHeader
;
25 import org
.argeo
.osgi
.useradmin
.AbstractUserDirectory
;
26 import org
.argeo
.osgi
.useradmin
.LdapProperties
;
27 import org
.argeo
.osgi
.useradmin
.LdapUserAdmin
;
28 import org
.argeo
.osgi
.useradmin
.LdifUserAdmin
;
29 import org
.argeo
.osgi
.useradmin
.UserDirectoryException
;
30 import org
.osgi
.framework
.InvalidSyntaxException
;
31 import org
.osgi
.service
.useradmin
.Authorization
;
32 import org
.osgi
.service
.useradmin
.Role
;
33 import org
.osgi
.service
.useradmin
.User
;
34 import org
.osgi
.service
.useradmin
.UserAdmin
;
36 public class NodeUserAdmin
implements UserAdmin
{
37 private final static Log log
= LogFactory
.getLog(NodeUserAdmin
.class);
38 final static LdapName ROLES_BASE
;
41 ROLES_BASE
= new LdapName(KernelHeader
.ROLES_BASEDN
);
42 } catch (InvalidNameException e
) {
43 throw new UserDirectoryException("Cannot initialize "
44 + NodeUserAdmin
.class, e
);
48 private UserAdmin nodeRoles
= null;
49 private Map
<LdapName
, UserAdmin
> userAdmins
= new HashMap
<LdapName
, UserAdmin
>();
51 public NodeUserAdmin() {
52 File osgiInstanceDir
= KernelUtils
.getOsgiInstanceDir();
53 File nodeBaseDir
= new File(osgiInstanceDir
, "node");
56 String userAdminUri
= KernelUtils
57 .getFrameworkProp(KernelConstants
.USERADMIN_URI
);
58 if (userAdminUri
== null) {
59 String demoBaseDn
= "dc=example,dc=com";
60 File businessRolesFile
= new File(nodeBaseDir
, demoBaseDn
+ ".ldif");
61 if (!businessRolesFile
.exists())
63 FileUtils
.copyInputStreamToFile(getClass()
64 .getResourceAsStream(demoBaseDn
+ ".ldif"),
66 } catch (IOException e
) {
67 throw new CmsException("Cannot copy demo resource", e
);
69 userAdminUri
= businessRolesFile
.toURI().toString();
72 String
[] uris
= userAdminUri
.split(" ");
73 for (String uri
: uris
) {
77 if (u
.getScheme() == null) {
78 if (uri
.startsWith("/"))
79 u
= new File(uri
).getAbsoluteFile().toURI();
80 else if (!uri
.contains("/"))
81 u
= new File(nodeBaseDir
, uri
).getAbsoluteFile()
84 throw new CmsException("Cannot interpret " + uri
87 } catch (URISyntaxException e
) {
88 throw new CmsException(
89 "Cannot interpret " + uri
+ " as an uri", e
);
91 Dictionary
<String
, ?
> properties
= LdapProperties
.uriAsProperties(u
93 AbstractUserDirectory businessRoles
;
94 if (u
.getScheme().startsWith("ldap")) {
95 businessRoles
= new LdapUserAdmin(properties
);
97 businessRoles
= new LdifUserAdmin(properties
);
100 addUserAdmin(businessRoles
.getBaseDn(), businessRoles
);
101 if (log
.isDebugEnabled())
102 log
.debug("User directory " + businessRoles
.getBaseDn() + " ["
103 + u
.getScheme() + "] enabled.");
107 String nodeRolesUri
= KernelUtils
108 .getFrameworkProp(KernelConstants
.ROLES_URI
);
109 String baseNodeRoleDn
= KernelHeader
.ROLES_BASEDN
;
110 if (nodeRolesUri
== null) {
111 File nodeRolesFile
= new File(nodeBaseDir
, baseNodeRoleDn
+ ".ldif");
112 if (!nodeRolesFile
.exists())
114 FileUtils
.copyInputStreamToFile(getClass()
115 .getResourceAsStream("demo.ldif"), nodeRolesFile
);
116 } catch (IOException e
) {
117 throw new CmsException("Cannot copy demo resource", e
);
119 nodeRolesUri
= nodeRolesFile
.toURI().toString();
122 Dictionary
<String
, ?
> nodeRolesProperties
= LdapProperties
123 .uriAsProperties(nodeRolesUri
);
124 if (!nodeRolesProperties
.get(LdapProperties
.baseDn
.getFullName())
125 .equals(baseNodeRoleDn
)) {
126 throw new CmsException("Invalid base dn for node roles");
127 // TODO deal with "mounted" roles with a different baseDN
129 AbstractUserDirectory nodeRoles
;
130 if (nodeRolesUri
.startsWith("ldap")) {
131 nodeRoles
= new LdapUserAdmin(nodeRolesProperties
);
133 nodeRoles
= new LdifUserAdmin(nodeRolesProperties
);
135 nodeRoles
.setExternalRoles(this);
137 addUserAdmin(baseNodeRoleDn
, nodeRoles
);
138 if (log
.isTraceEnabled())
139 log
.trace("Node roles enabled.");
142 String
asConfigUris() {
143 StringBuilder buf
= new StringBuilder();
144 for (LdapName name
: userAdmins
.keySet()) {
145 buf
.append('/').append(name
.toString());
146 if (userAdmins
.get(name
) instanceof AbstractUserDirectory
) {
147 AbstractUserDirectory userDirectory
= (AbstractUserDirectory
) userAdmins
149 if (userDirectory
.isReadOnly())
150 buf
.append('?').append(LdapProperties
.readOnly
.name())
155 return buf
.toString();
158 public void destroy() {
159 for (LdapName name
: userAdmins
.keySet()) {
160 if (userAdmins
.get(name
) instanceof AbstractUserDirectory
) {
161 AbstractUserDirectory userDirectory
= (AbstractUserDirectory
) userAdmins
163 userDirectory
.destroy();
169 public Role
createRole(String name
, int type
) {
170 return findUserAdmin(name
).createRole(name
, type
);
174 public boolean removeRole(String name
) {
175 return findUserAdmin(name
).removeRole(name
);
179 public Role
getRole(String name
) {
180 return findUserAdmin(name
).getRole(name
);
184 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
185 List
<Role
> res
= new ArrayList
<Role
>();
186 for (UserAdmin userAdmin
: userAdmins
.values()) {
187 res
.addAll(Arrays
.asList(userAdmin
.getRoles(filter
)));
189 res
.addAll(Arrays
.asList(nodeRoles
.getRoles(filter
)));
190 return res
.toArray(new Role
[res
.size()]);
194 public User
getUser(String key
, String value
) {
195 List
<User
> res
= new ArrayList
<User
>();
196 for (UserAdmin userAdmin
: userAdmins
.values()) {
197 User u
= userAdmin
.getUser(key
, value
);
201 // Note: node roles cannot contain users, so it is not searched
202 return res
.size() == 1 ? res
.get(0) : null;
206 public Authorization
getAuthorization(User user
) {
208 return nodeRoles
.getAuthorization(null);
210 UserAdmin userAdmin
= findUserAdmin(user
.getName());
211 Authorization rawAuthorization
= userAdmin
.getAuthorization(user
);
212 // gather system roles
213 Set
<String
> systemRoles
= new HashSet
<String
>();
214 for (String role
: rawAuthorization
.getRoles()) {
215 Authorization auth
= nodeRoles
.getAuthorization((User
) userAdmin
217 systemRoles
.addAll(Arrays
.asList(auth
.getRoles()));
219 return new NodeAuthorization(rawAuthorization
.getName(),
220 rawAuthorization
.toString(), systemRoles
,
221 rawAuthorization
.getRoles());
225 // USER ADMIN AGGREGATOR
227 public synchronized void addUserAdmin(String baseDn
, UserAdmin userAdmin
) {
228 if (baseDn
.equals(KernelHeader
.ROLES_BASEDN
)) {
229 nodeRoles
= userAdmin
;
233 if (userAdmins
.containsKey(baseDn
))
234 throw new UserDirectoryException(
235 "There is already a user admin for " + baseDn
);
237 userAdmins
.put(new LdapName(baseDn
), userAdmin
);
238 } catch (InvalidNameException e
) {
239 throw new UserDirectoryException("Badly formatted base DN "
244 public synchronized void removeUserAdmin(String baseDn
) {
245 if (baseDn
.equals(KernelHeader
.ROLES_BASEDN
))
246 throw new UserDirectoryException("Node roles cannot be removed.");
249 base
= new LdapName(baseDn
);
250 } catch (InvalidNameException e
) {
251 throw new UserDirectoryException("Badly formatted base DN "
254 if (!userAdmins
.containsKey(base
))
255 throw new UserDirectoryException("There is no user admin for "
257 userAdmins
.remove(base
);
260 private UserAdmin
findUserAdmin(String name
) {
262 return findUserAdmin(new LdapName(name
));
263 } catch (InvalidNameException e
) {
264 throw new UserDirectoryException("Badly formatted name " + name
, e
);
268 private UserAdmin
findUserAdmin(LdapName name
) {
269 if (name
.startsWith(ROLES_BASE
))
271 List
<UserAdmin
> res
= new ArrayList
<UserAdmin
>(1);
272 for (LdapName baseDn
: userAdmins
.keySet()) {
273 if (name
.startsWith(baseDn
))
274 res
.add(userAdmins
.get(baseDn
));
277 throw new UserDirectoryException("Cannot find user admin for "
280 throw new UserDirectoryException("Multiple user admin found for "
285 public void setTransactionManager(TransactionManager transactionManager
) {
286 if (nodeRoles
instanceof AbstractUserDirectory
)
287 ((AbstractUserDirectory
) nodeRoles
)
288 .setTransactionManager(transactionManager
);
289 for (UserAdmin userAdmin
: userAdmins
.values()) {
290 if (userAdmin
instanceof AbstractUserDirectory
)
291 ((AbstractUserDirectory
) userAdmin
)
292 .setTransactionManager(transactionManager
);