1 package org
.argeo
.osgi
.useradmin
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Arrays
;
5 import java
.util
.HashMap
;
6 import java
.util
.HashSet
;
11 import javax
.naming
.InvalidNameException
;
12 import javax
.naming
.ldap
.LdapName
;
14 import org
.osgi
.framework
.InvalidSyntaxException
;
15 import org
.osgi
.service
.useradmin
.Authorization
;
16 import org
.osgi
.service
.useradmin
.Group
;
17 import org
.osgi
.service
.useradmin
.Role
;
18 import org
.osgi
.service
.useradmin
.User
;
19 import org
.osgi
.service
.useradmin
.UserAdmin
;
22 * Aggregates multiple {@link UserDirectory} and integrates them with system
25 public class AggregatingUserAdmin
implements UserAdmin
{
26 private final LdapName systemRolesBaseDn
;
27 private final LdapName tokensBaseDn
;
30 private AbstractUserDirectory systemRoles
= null;
31 private AbstractUserDirectory tokens
= null;
32 private Map
<LdapName
, AbstractUserDirectory
> businessRoles
= new HashMap
<LdapName
, AbstractUserDirectory
>();
34 // TODO rather use an empty constructor and an init method
35 public AggregatingUserAdmin(String systemRolesBaseDn
, String tokensBaseDn
) {
37 this.systemRolesBaseDn
= new LdapName(systemRolesBaseDn
);
38 if (tokensBaseDn
!= null)
39 this.tokensBaseDn
= new LdapName(tokensBaseDn
);
41 this.tokensBaseDn
= null;
42 } catch (InvalidNameException e
) {
43 throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin
.class, e
);
48 public Role
createRole(String name
, int type
) {
49 return findUserAdmin(name
).createRole(name
, type
);
53 public boolean removeRole(String name
) {
54 boolean actuallyDeleted
= findUserAdmin(name
).removeRole(name
);
55 systemRoles
.removeRole(name
);
56 return actuallyDeleted
;
60 public Role
getRole(String name
) {
61 return findUserAdmin(name
).getRole(name
);
65 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
66 List
<Role
> res
= new ArrayList
<Role
>();
67 for (UserAdmin userAdmin
: businessRoles
.values()) {
68 res
.addAll(Arrays
.asList(userAdmin
.getRoles(filter
)));
70 res
.addAll(Arrays
.asList(systemRoles
.getRoles(filter
)));
71 return res
.toArray(new Role
[res
.size()]);
75 public User
getUser(String key
, String value
) {
76 List
<User
> res
= new ArrayList
<User
>();
77 for (UserAdmin userAdmin
: businessRoles
.values()) {
78 User u
= userAdmin
.getUser(key
, value
);
82 // Note: node roles cannot contain users, so it is not searched
83 return res
.size() == 1 ? res
.get(0) : null;
87 public Authorization
getAuthorization(User user
) {
88 if (user
== null) {// anonymous
89 return systemRoles
.getAuthorization(null);
91 AbstractUserDirectory userReferentialOfThisUser
= findUserAdmin(user
.getName());
92 Authorization rawAuthorization
= userReferentialOfThisUser
.getAuthorization(user
);
94 String displayNameToUse
;
95 if (user
instanceof Group
) {
96 // TODO check whether this is still working
97 String ownerDn
= TokenUtils
.userDn((Group
) user
);
98 if (ownerDn
!= null) {// tokens
99 UserAdmin ownerUserAdmin
= findUserAdmin(ownerDn
);
100 User ownerUser
= (User
) ownerUserAdmin
.getRole(ownerDn
);
101 usernameToUse
= ownerDn
;
102 displayNameToUse
= LdifAuthorization
.extractDisplayName(ownerUser
);
104 usernameToUse
= rawAuthorization
.getName();
105 displayNameToUse
= rawAuthorization
.toString();
107 } else {// regular users
108 usernameToUse
= rawAuthorization
.getName();
109 displayNameToUse
= rawAuthorization
.toString();
112 // gather roles from other referentials
113 final AbstractUserDirectory userAdminToUse
;// possibly scoped when authenticating
114 if (user
instanceof DirectoryUser
) {
115 userAdminToUse
= userReferentialOfThisUser
;
116 } else if (user
instanceof AuthenticatingUser
) {
117 userAdminToUse
= userReferentialOfThisUser
.scope(user
);
119 throw new IllegalArgumentException("Unsupported user type " + user
.getClass());
123 Set
<String
> sysRoles
= new HashSet
<String
>();
124 for (String role
: rawAuthorization
.getRoles()) {
125 User userOrGroup
= (User
) userAdminToUse
.getRole(role
);
126 Authorization auth
= systemRoles
.getAuthorization(userOrGroup
);
127 systemRoles
: for (String systemRole
: auth
.getRoles()) {
128 if (role
.equals(systemRole
))
129 continue systemRoles
;
130 sysRoles
.add(systemRole
);
132 // sysRoles.addAll(Arrays.asList(auth.getRoles()));
134 addAbstractSystemRoles(rawAuthorization
, sysRoles
);
135 Authorization authorization
= new AggregatingAuthorization(usernameToUse
, displayNameToUse
, sysRoles
,
136 rawAuthorization
.getRoles());
137 return authorization
;
139 if (userAdminToUse
!= null && userAdminToUse
.isScoped()) {
140 userAdminToUse
.destroy();
146 * Enrich with application-specific roles which are strictly programmatic, such
147 * as anonymous/user semantics.
149 protected void addAbstractSystemRoles(Authorization rawAuthorization
, Set
<String
> sysRoles
) {
154 // USER ADMIN AGGREGATOR
156 protected void addUserDirectory(AbstractUserDirectory userDirectory
) {
157 LdapName baseDn
= userDirectory
.getBaseDn();
158 if (isSystemRolesBaseDn(baseDn
)) {
159 this.systemRoles
= userDirectory
;
160 systemRoles
.setExternalRoles(this);
161 } else if (isTokensBaseDn(baseDn
)) {
162 this.tokens
= userDirectory
;
163 tokens
.setExternalRoles(this);
165 if (businessRoles
.containsKey(baseDn
))
166 throw new UserDirectoryException("There is already a user admin for " + baseDn
);
167 businessRoles
.put(baseDn
, userDirectory
);
169 userDirectory
.init();
170 postAdd(userDirectory
);
173 /** Called after a new user directory has been added */
174 protected void postAdd(AbstractUserDirectory userDirectory
) {
177 // private UserAdmin findUserAdmin(User user) {
179 // throw new IllegalArgumentException("User should not be null");
180 // AbstractUserDirectory userAdmin = findUserAdmin(user.getName());
181 // if (user instanceof DirectoryUser) {
184 // return userAdmin.scope(user);
188 private AbstractUserDirectory
findUserAdmin(String name
) {
190 return findUserAdmin(new LdapName(name
));
191 } catch (InvalidNameException e
) {
192 throw new UserDirectoryException("Badly formatted name " + name
, e
);
196 private AbstractUserDirectory
findUserAdmin(LdapName name
) {
197 if (name
.startsWith(systemRolesBaseDn
))
199 if (tokensBaseDn
!= null && name
.startsWith(tokensBaseDn
))
201 List
<AbstractUserDirectory
> res
= new ArrayList
<>(1);
202 userDirectories
: for (LdapName baseDn
: businessRoles
.keySet()) {
203 AbstractUserDirectory userDirectory
= businessRoles
.get(baseDn
);
204 if (name
.startsWith(baseDn
)) {
205 if (userDirectory
.isDisabled())
206 continue userDirectories
;
207 // if (res.isEmpty()) {
208 res
.add(userDirectory
);
210 // for (AbstractUserDirectory ud : res) {
211 // LdapName bd = ud.getBaseDn();
212 // if (userDirectory.getBaseDn().startsWith(bd)) {
213 // // child user directory
220 throw new UserDirectoryException("Cannot find user admin for " + name
);
222 throw new UserDirectoryException("Multiple user admin found for " + name
);
226 protected boolean isSystemRolesBaseDn(LdapName baseDn
) {
227 return baseDn
.equals(systemRolesBaseDn
);
230 protected boolean isTokensBaseDn(LdapName baseDn
) {
231 return tokensBaseDn
!= null && baseDn
.equals(tokensBaseDn
);
234 // protected Dictionary<String, Object> currentState() {
235 // Dictionary<String, Object> res = new Hashtable<String, Object>();
236 // // res.put(NodeConstants.CN, NodeConstants.DEFAULT);
237 // for (LdapName name : businessRoles.keySet()) {
238 // AbstractUserDirectory userDirectory = businessRoles.get(name);
239 // String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString();
245 public void destroy() {
246 for (LdapName name
: businessRoles
.keySet()) {
247 AbstractUserDirectory userDirectory
= businessRoles
.get(name
);
248 destroy(userDirectory
);
250 businessRoles
.clear();
251 businessRoles
= null;
252 destroy(systemRoles
);
256 private void destroy(AbstractUserDirectory userDirectory
) {
257 preDestroy(userDirectory
);
258 userDirectory
.destroy();
261 protected void removeUserDirectory(LdapName baseDn
) {
262 if (isSystemRolesBaseDn(baseDn
))
263 throw new UserDirectoryException("System roles cannot be removed ");
264 if (!businessRoles
.containsKey(baseDn
))
265 throw new UserDirectoryException("No user directory registered for " + baseDn
);
266 AbstractUserDirectory userDirectory
= businessRoles
.remove(baseDn
);
267 destroy(userDirectory
);
271 * Called before each user directory is destroyed, so that additional actions
274 protected void preDestroy(AbstractUserDirectory userDirectory
) {