]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java
[maven-release-plugin] prepare release v2.3.4
[lgpl/argeo-commons.git] / org.argeo.enterprise / src / org / argeo / 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 public AggregatingUserAdmin(String systemRolesBaseDn, String tokensBaseDn) {
35 try {
36 this.systemRolesBaseDn = new LdapName(systemRolesBaseDn);
37 if (tokensBaseDn != null)
38 this.tokensBaseDn = new LdapName(tokensBaseDn);
39 else
40 this.tokensBaseDn = null;
41 } catch (InvalidNameException e) {
42 throw new UserDirectoryException("Cannot initialize " + AggregatingUserAdmin.class, e);
43 }
44 }
45
46 @Override
47 public Role createRole(String name, int type) {
48 return findUserAdmin(name).createRole(name, type);
49 }
50
51 @Override
52 public boolean removeRole(String name) {
53 boolean actuallyDeleted = findUserAdmin(name).removeRole(name);
54 systemRoles.removeRole(name);
55 return actuallyDeleted;
56 }
57
58 @Override
59 public Role getRole(String name) {
60 return findUserAdmin(name).getRole(name);
61 }
62
63 @Override
64 public Role[] getRoles(String filter) throws InvalidSyntaxException {
65 List<Role> res = new ArrayList<Role>();
66 for (UserAdmin userAdmin : businessRoles.values()) {
67 res.addAll(Arrays.asList(userAdmin.getRoles(filter)));
68 }
69 res.addAll(Arrays.asList(systemRoles.getRoles(filter)));
70 return res.toArray(new Role[res.size()]);
71 }
72
73 @Override
74 public User getUser(String key, String value) {
75 List<User> res = new ArrayList<User>();
76 for (UserAdmin userAdmin : businessRoles.values()) {
77 User u = userAdmin.getUser(key, value);
78 if (u != null)
79 res.add(u);
80 }
81 // Note: node roles cannot contain users, so it is not searched
82 return res.size() == 1 ? res.get(0) : null;
83 }
84
85 @Override
86 public Authorization getAuthorization(User user) {
87 if (user == null) {// anonymous
88 return systemRoles.getAuthorization(null);
89 }
90 AbstractUserDirectory userReferentialOfThisUser = findUserAdmin(user.getName());
91 Authorization rawAuthorization = userReferentialOfThisUser.getAuthorization(user);
92 String usernameToUse;
93 String displayNameToUse;
94 if (user instanceof Group) {
95 // TODO check whether this is still working
96 String ownerDn = TokenUtils.userDn((Group) user);
97 if (ownerDn != null) {// tokens
98 UserAdmin ownerUserAdmin = findUserAdmin(ownerDn);
99 User ownerUser = (User) ownerUserAdmin.getRole(ownerDn);
100 usernameToUse = ownerDn;
101 displayNameToUse = LdifAuthorization.extractDisplayName(ownerUser);
102 } else {
103 usernameToUse = rawAuthorization.getName();
104 displayNameToUse = rawAuthorization.toString();
105 }
106 } else {// regular users
107 usernameToUse = rawAuthorization.getName();
108 displayNameToUse = rawAuthorization.toString();
109 }
110
111 // gather roles from other referentials
112 final AbstractUserDirectory userAdminToUse;// possibly scoped when authenticating
113 if (user instanceof DirectoryUser) {
114 userAdminToUse = userReferentialOfThisUser;
115 } else if (user instanceof AuthenticatingUser) {
116 userAdminToUse = userReferentialOfThisUser.scope(user);
117 } else {
118 throw new IllegalArgumentException("Unsupported user type " + user.getClass());
119 }
120
121 try {
122 Set<String> sysRoles = new HashSet<String>();
123 for (String role : rawAuthorization.getRoles()) {
124 User userOrGroup = (User) userAdminToUse.getRole(role);
125 Authorization auth = systemRoles.getAuthorization(userOrGroup);
126 systemRoles: for (String systemRole : auth.getRoles()) {
127 if (role.equals(systemRole))
128 continue systemRoles;
129 sysRoles.add(systemRole);
130 }
131 // sysRoles.addAll(Arrays.asList(auth.getRoles()));
132 }
133 addAbstractSystemRoles(rawAuthorization, sysRoles);
134 Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles,
135 rawAuthorization.getRoles());
136 return authorization;
137 } finally {
138 if (userAdminToUse != null && userAdminToUse.isScoped()) {
139 userAdminToUse.destroy();
140 }
141 }
142 }
143
144 /**
145 * Enrich with application-specific roles which are strictly programmatic, such
146 * as anonymous/user semantics.
147 */
148 protected void addAbstractSystemRoles(Authorization rawAuthorization, Set<String> sysRoles) {
149
150 }
151
152 //
153 // USER ADMIN AGGREGATOR
154 //
155 protected void addUserDirectory(AbstractUserDirectory userDirectory) {
156 LdapName baseDn = userDirectory.getBaseDn();
157 if (isSystemRolesBaseDn(baseDn)) {
158 this.systemRoles = userDirectory;
159 systemRoles.setExternalRoles(this);
160 } else if (isTokensBaseDn(baseDn)) {
161 this.tokens = userDirectory;
162 tokens.setExternalRoles(this);
163 } else {
164 if (businessRoles.containsKey(baseDn))
165 throw new UserDirectoryException("There is already a user admin for " + baseDn);
166 businessRoles.put(baseDn, userDirectory);
167 }
168 userDirectory.init();
169 postAdd(userDirectory);
170 }
171
172 /** Called after a new user directory has been added */
173 protected void postAdd(AbstractUserDirectory userDirectory) {
174 }
175
176 // private UserAdmin findUserAdmin(User user) {
177 // if (user == null)
178 // throw new IllegalArgumentException("User should not be null");
179 // AbstractUserDirectory userAdmin = findUserAdmin(user.getName());
180 // if (user instanceof DirectoryUser) {
181 // return userAdmin;
182 // } else {
183 // return userAdmin.scope(user);
184 // }
185 // }
186
187 private AbstractUserDirectory findUserAdmin(String name) {
188 try {
189 return findUserAdmin(new LdapName(name));
190 } catch (InvalidNameException e) {
191 throw new UserDirectoryException("Badly formatted name " + name, e);
192 }
193 }
194
195 private AbstractUserDirectory findUserAdmin(LdapName name) {
196 if (name.startsWith(systemRolesBaseDn))
197 return systemRoles;
198 if (tokensBaseDn != null && name.startsWith(tokensBaseDn))
199 return tokens;
200 List<AbstractUserDirectory> res = new ArrayList<>(1);
201 userDirectories: for (LdapName baseDn : businessRoles.keySet()) {
202 AbstractUserDirectory userDirectory = businessRoles.get(baseDn);
203 if (name.startsWith(baseDn)) {
204 if (userDirectory.isDisabled())
205 continue userDirectories;
206 // if (res.isEmpty()) {
207 res.add(userDirectory);
208 // } else {
209 // for (AbstractUserDirectory ud : res) {
210 // LdapName bd = ud.getBaseDn();
211 // if (userDirectory.getBaseDn().startsWith(bd)) {
212 // // child user directory
213 // }
214 // }
215 // }
216 }
217 }
218 if (res.size() == 0)
219 throw new UserDirectoryException("Cannot find user admin for " + name);
220 if (res.size() > 1)
221 throw new UserDirectoryException("Multiple user admin found for " + name);
222 return res.get(0);
223 }
224
225 protected boolean isSystemRolesBaseDn(LdapName baseDn) {
226 return baseDn.equals(systemRolesBaseDn);
227 }
228
229 protected boolean isTokensBaseDn(LdapName baseDn) {
230 return tokensBaseDn != null && baseDn.equals(tokensBaseDn);
231 }
232
233 // protected Dictionary<String, Object> currentState() {
234 // Dictionary<String, Object> res = new Hashtable<String, Object>();
235 // // res.put(NodeConstants.CN, NodeConstants.DEFAULT);
236 // for (LdapName name : businessRoles.keySet()) {
237 // AbstractUserDirectory userDirectory = businessRoles.get(name);
238 // String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString();
239 // res.put(uri, "");
240 // }
241 // return res;
242 // }
243
244 public void destroy() {
245 for (LdapName name : businessRoles.keySet()) {
246 AbstractUserDirectory userDirectory = businessRoles.get(name);
247 destroy(userDirectory);
248 }
249 businessRoles.clear();
250 businessRoles = null;
251 destroy(systemRoles);
252 systemRoles = null;
253 }
254
255 private void destroy(AbstractUserDirectory userDirectory) {
256 preDestroy(userDirectory);
257 userDirectory.destroy();
258 }
259
260 protected void removeUserDirectory(LdapName baseDn) {
261 if (isSystemRolesBaseDn(baseDn))
262 throw new UserDirectoryException("System roles cannot be removed ");
263 if (!businessRoles.containsKey(baseDn))
264 throw new UserDirectoryException("No user directory registered for " + baseDn);
265 AbstractUserDirectory userDirectory = businessRoles.remove(baseDn);
266 destroy(userDirectory);
267 }
268
269 /**
270 * Called before each user directory is destroyed, so that additional actions
271 * can be performed.
272 */
273 protected void preDestroy(AbstractUserDirectory userDirectory) {
274 }
275
276 }