]> git.argeo.org Git - lgpl/argeo-commons.git/blob - osgi/useradmin/AggregatingUserAdmin.java
Prepare next development cycle
[lgpl/argeo-commons.git] / osgi / useradmin / AggregatingUserAdmin.java
1 package org.argeo.osgi.useradmin;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import javax.naming.InvalidNameException;
12 import javax.naming.ldap.LdapName;
13
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;
20
21 /**
22 * Aggregates multiple {@link UserDirectory} and integrates them with system
23 * roles.
24 */
25 public class AggregatingUserAdmin implements UserAdmin {
26 private final LdapName systemRolesBaseDn;
27 private final LdapName tokensBaseDn;
28
29 // DAOs
30 private AbstractUserDirectory systemRoles = null;
31 private AbstractUserDirectory tokens = null;
32 private Map<LdapName, AbstractUserDirectory> businessRoles = new HashMap<LdapName, AbstractUserDirectory>();
33
34 // TODO rather use an empty constructor and an init method
35 public AggregatingUserAdmin(String systemRolesBaseDn, String tokensBaseDn) {
36 try {
37 this.systemRolesBaseDn = new LdapName(systemRolesBaseDn);
38 if (tokensBaseDn != null)
39 this.tokensBaseDn = new LdapName(tokensBaseDn);
40 else
41 this.tokensBaseDn = null;
42 } catch (InvalidNameException e) {
43 throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin.class, e);
44 }
45 }
46
47 @Override
48 public Role createRole(String name, int type) {
49 return findUserAdmin(name).createRole(name, type);
50 }
51
52 @Override
53 public boolean removeRole(String name) {
54 boolean actuallyDeleted = findUserAdmin(name).removeRole(name);
55 systemRoles.removeRole(name);
56 return actuallyDeleted;
57 }
58
59 @Override
60 public Role getRole(String name) {
61 return findUserAdmin(name).getRole(name);
62 }
63
64 @Override
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)));
69 }
70 res.addAll(Arrays.asList(systemRoles.getRoles(filter)));
71 return res.toArray(new Role[res.size()]);
72 }
73
74 @Override
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);
79 if (u != null)
80 res.add(u);
81 }
82 // Note: node roles cannot contain users, so it is not searched
83 return res.size() == 1 ? res.get(0) : null;
84 }
85
86 @Override
87 public Authorization getAuthorization(User user) {
88 if (user == null) {// anonymous
89 return systemRoles.getAuthorization(null);
90 }
91 AbstractUserDirectory userReferentialOfThisUser = findUserAdmin(user.getName());
92 Authorization rawAuthorization = userReferentialOfThisUser.getAuthorization(user);
93 String usernameToUse;
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);
103 } else {
104 usernameToUse = rawAuthorization.getName();
105 displayNameToUse = rawAuthorization.toString();
106 }
107 } else {// regular users
108 usernameToUse = rawAuthorization.getName();
109 displayNameToUse = rawAuthorization.toString();
110 }
111
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);
118 } else {
119 throw new IllegalArgumentException("Unsupported user type " + user.getClass());
120 }
121
122 try {
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);
131 }
132 // sysRoles.addAll(Arrays.asList(auth.getRoles()));
133 }
134 addAbstractSystemRoles(rawAuthorization, sysRoles);
135 Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles,
136 rawAuthorization.getRoles());
137 return authorization;
138 } finally {
139 if (userAdminToUse != null && userAdminToUse.isScoped()) {
140 userAdminToUse.destroy();
141 }
142 }
143 }
144
145 /**
146 * Enrich with application-specific roles which are strictly programmatic, such
147 * as anonymous/user semantics.
148 */
149 protected void addAbstractSystemRoles(Authorization rawAuthorization, Set<String> sysRoles) {
150
151 }
152
153 //
154 // USER ADMIN AGGREGATOR
155 //
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);
164 } else {
165 if (businessRoles.containsKey(baseDn))
166 throw new UserDirectoryException("There is already a user admin for " + baseDn);
167 businessRoles.put(baseDn, userDirectory);
168 }
169 userDirectory.init();
170 postAdd(userDirectory);
171 }
172
173 /** Called after a new user directory has been added */
174 protected void postAdd(AbstractUserDirectory userDirectory) {
175 }
176
177 // private UserAdmin findUserAdmin(User user) {
178 // if (user == null)
179 // throw new IllegalArgumentException("User should not be null");
180 // AbstractUserDirectory userAdmin = findUserAdmin(user.getName());
181 // if (user instanceof DirectoryUser) {
182 // return userAdmin;
183 // } else {
184 // return userAdmin.scope(user);
185 // }
186 // }
187
188 private AbstractUserDirectory findUserAdmin(String name) {
189 try {
190 return findUserAdmin(new LdapName(name));
191 } catch (InvalidNameException e) {
192 throw new UserDirectoryException("Badly formatted name " + name, e);
193 }
194 }
195
196 private AbstractUserDirectory findUserAdmin(LdapName name) {
197 if (name.startsWith(systemRolesBaseDn))
198 return systemRoles;
199 if (tokensBaseDn != null && name.startsWith(tokensBaseDn))
200 return tokens;
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);
209 // } else {
210 // for (AbstractUserDirectory ud : res) {
211 // LdapName bd = ud.getBaseDn();
212 // if (userDirectory.getBaseDn().startsWith(bd)) {
213 // // child user directory
214 // }
215 // }
216 // }
217 }
218 }
219 if (res.size() == 0)
220 throw new UserDirectoryException("Cannot find user admin for " + name);
221 if (res.size() > 1)
222 throw new UserDirectoryException("Multiple user admin found for " + name);
223 return res.get(0);
224 }
225
226 protected boolean isSystemRolesBaseDn(LdapName baseDn) {
227 return baseDn.equals(systemRolesBaseDn);
228 }
229
230 protected boolean isTokensBaseDn(LdapName baseDn) {
231 return tokensBaseDn != null && baseDn.equals(tokensBaseDn);
232 }
233
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();
240 // res.put(uri, "");
241 // }
242 // return res;
243 // }
244
245 public void destroy() {
246 for (LdapName name : businessRoles.keySet()) {
247 AbstractUserDirectory userDirectory = businessRoles.get(name);
248 destroy(userDirectory);
249 }
250 businessRoles.clear();
251 businessRoles = null;
252 destroy(systemRoles);
253 systemRoles = null;
254 }
255
256 private void destroy(AbstractUserDirectory userDirectory) {
257 preDestroy(userDirectory);
258 userDirectory.destroy();
259 }
260
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);
268 }
269
270 /**
271 * Called before each user directory is destroyed, so that additional actions
272 * can be performed.
273 */
274 protected void preDestroy(AbstractUserDirectory userDirectory) {
275 }
276
277 }