1 package org
.argeo
.osgi
.useradmin
;
3 import static org
.argeo
.osgi
.useradmin
.AbstractUserDirectory
.toLdapName
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Arrays
;
7 import java
.util
.HashMap
;
8 import java
.util
.HashSet
;
12 import java
.util
.TreeSet
;
14 import javax
.naming
.InvalidNameException
;
15 import javax
.naming
.ldap
.LdapName
;
17 import org
.osgi
.framework
.InvalidSyntaxException
;
18 import org
.osgi
.service
.useradmin
.Authorization
;
19 import org
.osgi
.service
.useradmin
.Group
;
20 import org
.osgi
.service
.useradmin
.Role
;
21 import org
.osgi
.service
.useradmin
.User
;
22 import org
.osgi
.service
.useradmin
.UserAdmin
;
25 * Aggregates multiple {@link UserDirectory} and integrates them with system
28 public class AggregatingUserAdmin
implements UserAdmin
{
29 private final LdapName systemRolesBaseDn
;
30 private final LdapName tokensBaseDn
;
33 private AbstractUserDirectory systemRoles
= null;
34 private AbstractUserDirectory tokens
= null;
35 private Map
<LdapName
, AbstractUserDirectory
> businessRoles
= new HashMap
<LdapName
, AbstractUserDirectory
>();
37 // TODO rather use an empty constructor and an init method
38 public AggregatingUserAdmin(String systemRolesBaseDn
, String tokensBaseDn
) {
40 this.systemRolesBaseDn
= new LdapName(systemRolesBaseDn
);
41 if (tokensBaseDn
!= null)
42 this.tokensBaseDn
= new LdapName(tokensBaseDn
);
44 this.tokensBaseDn
= null;
45 } catch (InvalidNameException e
) {
46 throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin
.class, e
);
51 public Role
createRole(String name
, int type
) {
52 return findUserAdmin(name
).createRole(name
, type
);
56 public boolean removeRole(String name
) {
57 boolean actuallyDeleted
= findUserAdmin(name
).removeRole(name
);
58 systemRoles
.removeRole(name
);
59 return actuallyDeleted
;
63 public Role
getRole(String name
) {
64 return findUserAdmin(name
).getRole(name
);
68 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
69 List
<Role
> res
= new ArrayList
<Role
>();
70 for (UserAdmin userAdmin
: businessRoles
.values()) {
71 res
.addAll(Arrays
.asList(userAdmin
.getRoles(filter
)));
73 res
.addAll(Arrays
.asList(systemRoles
.getRoles(filter
)));
74 return res
.toArray(new Role
[res
.size()]);
78 public User
getUser(String key
, String value
) {
79 List
<User
> res
= new ArrayList
<User
>();
80 for (UserAdmin userAdmin
: businessRoles
.values()) {
81 User u
= userAdmin
.getUser(key
, value
);
85 // Note: node roles cannot contain users, so it is not searched
86 return res
.size() == 1 ? res
.get(0) : null;
90 public Authorization
getAuthorization(User user
) {
91 if (user
== null) {// anonymous
92 return systemRoles
.getAuthorization(null);
94 AbstractUserDirectory userReferentialOfThisUser
= findUserAdmin(user
.getName());
95 Authorization rawAuthorization
= userReferentialOfThisUser
.getAuthorization(user
);
97 String displayNameToUse
;
98 if (user
instanceof Group
) {
99 // TODO check whether this is still working
100 String ownerDn
= TokenUtils
.userDn((Group
) user
);
101 if (ownerDn
!= null) {// tokens
102 UserAdmin ownerUserAdmin
= findUserAdmin(ownerDn
);
103 User ownerUser
= (User
) ownerUserAdmin
.getRole(ownerDn
);
104 usernameToUse
= ownerDn
;
105 displayNameToUse
= LdifAuthorization
.extractDisplayName(ownerUser
);
107 usernameToUse
= rawAuthorization
.getName();
108 displayNameToUse
= rawAuthorization
.toString();
110 } else {// regular users
111 usernameToUse
= rawAuthorization
.getName();
112 displayNameToUse
= rawAuthorization
.toString();
115 // gather roles from other referentials
116 final AbstractUserDirectory userAdminToUse
;// possibly scoped when authenticating
117 if (user
instanceof DirectoryUser
) {
118 userAdminToUse
= userReferentialOfThisUser
;
119 } else if (user
instanceof AuthenticatingUser
) {
120 userAdminToUse
= userReferentialOfThisUser
.scope(user
);
122 throw new IllegalArgumentException("Unsupported user type " + user
.getClass());
126 Set
<String
> sysRoles
= new HashSet
<String
>();
127 for (String role
: rawAuthorization
.getRoles()) {
128 User userOrGroup
= (User
) userAdminToUse
.getRole(role
);
129 Authorization auth
= systemRoles
.getAuthorization(userOrGroup
);
130 systemRoles
: for (String systemRole
: auth
.getRoles()) {
131 if (role
.equals(systemRole
))
132 continue systemRoles
;
133 sysRoles
.add(systemRole
);
135 // sysRoles.addAll(Arrays.asList(auth.getRoles()));
137 addAbstractSystemRoles(rawAuthorization
, sysRoles
);
138 Authorization authorization
= new AggregatingAuthorization(usernameToUse
, displayNameToUse
, sysRoles
,
139 rawAuthorization
.getRoles());
140 return authorization
;
142 if (userAdminToUse
!= null && userAdminToUse
.isScoped()) {
143 userAdminToUse
.destroy();
149 * Enrich with application-specific roles which are strictly programmatic, such
150 * as anonymous/user semantics.
152 protected void addAbstractSystemRoles(Authorization rawAuthorization
, Set
<String
> sysRoles
) {
157 // USER ADMIN AGGREGATOR
159 protected void addUserDirectory(UserDirectory ud
) {
160 if (!(ud
instanceof AbstractUserDirectory
))
161 throw new IllegalArgumentException("Only " + AbstractUserDirectory
.class.getName() + " is supported");
162 AbstractUserDirectory userDirectory
= (AbstractUserDirectory
) ud
;
163 String basePath
= userDirectory
.getGlobalId();
164 if (isSystemRolesBaseDn(basePath
)) {
165 this.systemRoles
= userDirectory
;
166 systemRoles
.setExternalRoles(this);
167 } else if (isTokensBaseDn(basePath
)) {
168 this.tokens
= userDirectory
;
169 tokens
.setExternalRoles(this);
171 LdapName baseDn
= toLdapName(basePath
);
172 if (businessRoles
.containsKey(baseDn
))
173 throw new UserDirectoryException("There is already a user admin for " + baseDn
);
174 businessRoles
.put(baseDn
, userDirectory
);
176 userDirectory
.init();
177 postAdd(userDirectory
);
180 /** Called after a new user directory has been added */
181 protected void postAdd(UserDirectory userDirectory
) {
184 private AbstractUserDirectory
findUserAdmin(String name
) {
186 return findUserAdmin(new LdapName(name
));
187 } catch (InvalidNameException e
) {
188 throw new UserDirectoryException("Badly formatted name " + name
, e
);
192 private AbstractUserDirectory
findUserAdmin(LdapName name
) {
193 if (name
.startsWith(systemRolesBaseDn
))
195 if (tokensBaseDn
!= null && name
.startsWith(tokensBaseDn
))
197 List
<AbstractUserDirectory
> res
= new ArrayList
<>(1);
198 userDirectories
: for (LdapName baseDn
: businessRoles
.keySet()) {
199 AbstractUserDirectory userDirectory
= businessRoles
.get(baseDn
);
200 if (name
.startsWith(baseDn
)) {
201 if (userDirectory
.isDisabled())
202 continue userDirectories
;
203 // if (res.isEmpty()) {
204 res
.add(userDirectory
);
206 // for (AbstractUserDirectory ud : res) {
207 // LdapName bd = ud.getBaseDn();
208 // if (userDirectory.getBaseDn().startsWith(bd)) {
209 // // child user directory
216 throw new UserDirectoryException("Cannot find user admin for " + name
);
218 throw new UserDirectoryException("Multiple user admin found for " + name
);
222 protected boolean isSystemRolesBaseDn(String basePath
) {
223 return toLdapName(basePath
).equals(systemRolesBaseDn
);
226 protected boolean isTokensBaseDn(String basePath
) {
227 return tokensBaseDn
!= null && toLdapName(basePath
).equals(tokensBaseDn
);
230 // protected Dictionary<String, Object> currentState() {
231 // Dictionary<String, Object> res = new Hashtable<String, Object>();
232 // // res.put(NodeConstants.CN, NodeConstants.DEFAULT);
233 // for (LdapName name : businessRoles.keySet()) {
234 // AbstractUserDirectory userDirectory = businessRoles.get(name);
235 // String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString();
241 public void destroy() {
242 for (LdapName name
: businessRoles
.keySet()) {
243 AbstractUserDirectory userDirectory
= businessRoles
.get(name
);
244 destroy(userDirectory
);
246 businessRoles
.clear();
247 businessRoles
= null;
248 destroy(systemRoles
);
252 private void destroy(AbstractUserDirectory userDirectory
) {
253 preDestroy(userDirectory
);
254 userDirectory
.destroy();
257 protected void removeUserDirectory(String basePath
) {
258 if (isSystemRolesBaseDn(basePath
))
259 throw new UserDirectoryException("System roles cannot be removed ");
260 LdapName baseDn
= toLdapName(basePath
);
261 if (!businessRoles
.containsKey(baseDn
))
262 throw new UserDirectoryException("No user directory registered for " + baseDn
);
263 AbstractUserDirectory userDirectory
= businessRoles
.remove(baseDn
);
264 destroy(userDirectory
);
268 * Called before each user directory is destroyed, so that additional actions
271 protected void preDestroy(UserDirectory userDirectory
) {
274 public Set
<UserDirectory
> getUserDirectories() {
275 TreeSet
<UserDirectory
> res
= new TreeSet
<>((o1
, o2
) -> o1
.getGlobalId().compareTo(o2
.getGlobalId()));
276 res
.addAll(businessRoles
.values());