1 package org
.argeo
.cms
.internal
.kernel
;
4 import java
.io
.IOException
;
6 import java
.util
.ArrayList
;
7 import java
.util
.Arrays
;
8 import java
.util
.Dictionary
;
9 import java
.util
.HashMap
;
10 import java
.util
.HashSet
;
11 import java
.util
.Hashtable
;
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
.LdapUserAdmin
;
26 import org
.argeo
.osgi
.useradmin
.LdifUserAdmin
;
27 import org
.argeo
.osgi
.useradmin
.UserAdminConf
;
28 import org
.argeo
.osgi
.useradmin
.UserDirectory
;
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_URIS
);
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
.getPath() == null)
78 throw new CmsException("URI " + uri
79 + " must have a path in order to determine base DN");
80 if (u
.getScheme() == null) {
81 if (uri
.startsWith("/") || uri
.startsWith("./")
82 || uri
.startsWith("../"))
83 u
= new File(uri
).getCanonicalFile().toURI();
84 else if (!uri
.contains("/"))
85 u
= new File(nodeBaseDir
, uri
).getCanonicalFile()
88 throw new CmsException("Cannot interpret " + uri
90 } else if (u
.getScheme().equals("file")) {
91 u
= new File(u
).getCanonicalFile().toURI();
93 } catch (Exception e
) {
94 throw new CmsException(
95 "Cannot interpret " + uri
+ " as an uri", e
);
97 Dictionary
<String
, ?
> properties
= UserAdminConf
.uriAsProperties(u
99 UserDirectory businessRoles
;
100 if (u
.getScheme().startsWith("ldap")) {
101 businessRoles
= new LdapUserAdmin(properties
);
103 businessRoles
= new LdifUserAdmin(properties
);
105 businessRoles
.init();
106 addUserAdmin(businessRoles
.getBaseDn(), (UserAdmin
) businessRoles
);
107 if (log
.isDebugEnabled())
108 log
.debug("User directory " + businessRoles
.getBaseDn() + " ["
109 + u
.getScheme() + "] enabled.");
113 String nodeRolesUri
= KernelUtils
114 .getFrameworkProp(KernelConstants
.ROLES_URI
);
115 String baseNodeRoleDn
= KernelHeader
.ROLES_BASEDN
;
116 if (nodeRolesUri
== null) {
117 File nodeRolesFile
= new File(nodeBaseDir
, baseNodeRoleDn
+ ".ldif");
118 if (!nodeRolesFile
.exists())
120 FileUtils
.copyInputStreamToFile(getClass()
121 .getResourceAsStream("demo.ldif"), nodeRolesFile
);
122 } catch (IOException e
) {
123 throw new CmsException("Cannot copy demo resource", e
);
125 nodeRolesUri
= nodeRolesFile
.toURI().toString();
128 Dictionary
<String
, ?
> nodeRolesProperties
= UserAdminConf
129 .uriAsProperties(nodeRolesUri
);
130 if (!nodeRolesProperties
.get(UserAdminConf
.baseDn
.property()).equals(
132 throw new CmsException("Invalid base dn for node roles");
133 // TODO deal with "mounted" roles with a different baseDN
135 UserDirectory nodeRoles
;
136 if (nodeRolesUri
.startsWith("ldap")) {
137 nodeRoles
= new LdapUserAdmin(nodeRolesProperties
);
139 nodeRoles
= new LdifUserAdmin(nodeRolesProperties
);
141 nodeRoles
.setExternalRoles(this);
143 addUserAdmin(baseNodeRoleDn
, (UserAdmin
) nodeRoles
);
144 if (log
.isTraceEnabled())
145 log
.trace("Node roles enabled.");
148 Dictionary
<String
, ?
> currentState() {
149 Dictionary
<String
, Object
> res
= new Hashtable
<String
, Object
>();
150 for (LdapName name
: userAdmins
.keySet()) {
151 StringBuilder buf
= new StringBuilder();
152 if (userAdmins
.get(name
) instanceof UserDirectory
) {
153 UserDirectory userDirectory
= (UserDirectory
) userAdmins
155 String uri
= UserAdminConf
.propertiesAsUri(
156 userDirectory
.getProperties()).toString();
159 buf
.append('/').append(name
.toString())
160 .append("?readOnly=true");
166 public void destroy() {
167 for (LdapName name
: userAdmins
.keySet()) {
168 if (userAdmins
.get(name
) instanceof UserDirectory
) {
169 UserDirectory userDirectory
= (UserDirectory
) userAdmins
171 userDirectory
.destroy();
177 public Role
createRole(String name
, int type
) {
178 return findUserAdmin(name
).createRole(name
, type
);
182 public boolean removeRole(String name
) {
183 boolean actuallyDeleted
= findUserAdmin(name
).removeRole(name
);
184 nodeRoles
.removeRole(name
);
185 return actuallyDeleted
;
189 public Role
getRole(String name
) {
190 return findUserAdmin(name
).getRole(name
);
194 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
195 List
<Role
> res
= new ArrayList
<Role
>();
196 for (UserAdmin userAdmin
: userAdmins
.values()) {
197 res
.addAll(Arrays
.asList(userAdmin
.getRoles(filter
)));
199 res
.addAll(Arrays
.asList(nodeRoles
.getRoles(filter
)));
200 return res
.toArray(new Role
[res
.size()]);
204 public User
getUser(String key
, String value
) {
205 List
<User
> res
= new ArrayList
<User
>();
206 for (UserAdmin userAdmin
: userAdmins
.values()) {
207 User u
= userAdmin
.getUser(key
, value
);
211 // Note: node roles cannot contain users, so it is not searched
212 return res
.size() == 1 ? res
.get(0) : null;
216 public Authorization
getAuthorization(User user
) {
218 return nodeRoles
.getAuthorization(null);
220 UserAdmin userAdmin
= findUserAdmin(user
.getName());
221 Authorization rawAuthorization
= userAdmin
.getAuthorization(user
);
222 // gather system roles
223 Set
<String
> systemRoles
= new HashSet
<String
>();
224 for (String role
: rawAuthorization
.getRoles()) {
225 Authorization auth
= nodeRoles
.getAuthorization((User
) userAdmin
227 systemRoles
.addAll(Arrays
.asList(auth
.getRoles()));
229 return new NodeAuthorization(rawAuthorization
.getName(),
230 rawAuthorization
.toString(), systemRoles
,
231 rawAuthorization
.getRoles());
235 // USER ADMIN AGGREGATOR
237 public synchronized void addUserAdmin(String baseDn
, UserAdmin userAdmin
) {
238 if (baseDn
.equals(KernelHeader
.ROLES_BASEDN
)) {
239 nodeRoles
= userAdmin
;
243 if (userAdmins
.containsKey(baseDn
))
244 throw new UserDirectoryException(
245 "There is already a user admin for " + baseDn
);
247 userAdmins
.put(new LdapName(baseDn
), userAdmin
);
248 } catch (InvalidNameException e
) {
249 throw new UserDirectoryException("Badly formatted base DN "
254 public synchronized void removeUserAdmin(String baseDn
) {
255 if (baseDn
.equals(KernelHeader
.ROLES_BASEDN
))
256 throw new UserDirectoryException("Node roles cannot be removed.");
259 base
= new LdapName(baseDn
);
260 } catch (InvalidNameException e
) {
261 throw new UserDirectoryException("Badly formatted base DN "
264 if (!userAdmins
.containsKey(base
))
265 throw new UserDirectoryException("There is no user admin for "
267 userAdmins
.remove(base
);
270 private UserAdmin
findUserAdmin(String name
) {
272 return findUserAdmin(new LdapName(name
));
273 } catch (InvalidNameException e
) {
274 throw new UserDirectoryException("Badly formatted name " + name
, e
);
278 private UserAdmin
findUserAdmin(LdapName name
) {
279 if (name
.startsWith(ROLES_BASE
))
281 List
<UserAdmin
> res
= new ArrayList
<UserAdmin
>(1);
282 for (LdapName baseDn
: userAdmins
.keySet()) {
283 if (name
.startsWith(baseDn
))
284 res
.add(userAdmins
.get(baseDn
));
287 throw new UserDirectoryException("Cannot find user admin for "
290 throw new UserDirectoryException("Multiple user admin found for "
295 public void setTransactionManager(TransactionManager transactionManager
) {
296 if (nodeRoles
instanceof UserDirectory
)
297 ((UserDirectory
) nodeRoles
)
298 .setTransactionManager(transactionManager
);
299 for (UserAdmin userAdmin
: userAdmins
.values()) {
300 if (userAdmin
instanceof UserDirectory
)
301 ((UserDirectory
) userAdmin
)
302 .setTransactionManager(transactionManager
);