Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DefaultUserManager |
|
| 1.9545454545454546;1,955 |
1 | package org.apache.turbine.services.security; | |
2 | ||
3 | ||
4 | /* | |
5 | * Licensed to the Apache Software Foundation (ASF) under one | |
6 | * or more contributor license agreements. See the NOTICE file | |
7 | * distributed with this work for additional information | |
8 | * regarding copyright ownership. The ASF licenses this file | |
9 | * to you under the Apache License, Version 2.0 (the | |
10 | * "License"); you may not use this file except in compliance | |
11 | * with the License. You may obtain a copy of the License at | |
12 | * | |
13 | * http://www.apache.org/licenses/LICENSE-2.0 | |
14 | * | |
15 | * Unless required by applicable law or agreed to in writing, | |
16 | * software distributed under the License is distributed on an | |
17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
18 | * KIND, either express or implied. See the License for the | |
19 | * specific language governing permissions and limitations | |
20 | * under the License. | |
21 | */ | |
22 | ||
23 | ||
24 | import java.util.ArrayList; | |
25 | import java.util.List; | |
26 | ||
27 | import org.apache.commons.configuration2.Configuration; | |
28 | import org.apache.fulcrum.factory.FactoryService; | |
29 | import org.apache.fulcrum.security.acl.AccessControlList; | |
30 | import org.apache.fulcrum.security.model.turbine.TurbineUserManager; | |
31 | import org.apache.fulcrum.security.model.turbine.entity.TurbineUser; | |
32 | import org.apache.fulcrum.security.util.DataBackendException; | |
33 | import org.apache.fulcrum.security.util.EntityExistsException; | |
34 | import org.apache.fulcrum.security.util.PasswordMismatchException; | |
35 | import org.apache.fulcrum.security.util.UnknownEntityException; | |
36 | import org.apache.fulcrum.security.util.UserSet; | |
37 | import org.apache.logging.log4j.LogManager; | |
38 | import org.apache.logging.log4j.Logger; | |
39 | import org.apache.turbine.om.security.TurbineUserDelegate; | |
40 | import org.apache.turbine.om.security.User; | |
41 | import org.apache.turbine.services.InitializationException; | |
42 | import org.apache.turbine.services.ServiceManager; | |
43 | import org.apache.turbine.services.TurbineServices; | |
44 | import org.apache.turbine.util.ObjectUtils; | |
45 | ||
46 | /** | |
47 | * Default user manager. | |
48 | * | |
49 | * The user manager wraps Fulcrum security user objects into | |
50 | * Turbine-specific ones. | |
51 | * | |
52 | * | |
53 | * <ol> | |
54 | * <li>either in a method with the same name (and very similar signature)</li> | |
55 | * <li>or mapped to method names as listed below: | |
56 | * | |
57 | * <ul> | |
58 | * <li>method(s) in this manager -> Fulcrum manager method(s) | |
59 | * <li>{@link #createAccount(User, String)}createAccount -> addUser(User, String) | |
60 | * <li>{@link #removeAccount(User)} -> removeUser(User) | |
61 | * <li>{@link #store(User)} -> saveUser(User) | |
62 | * <li>{@link #retrieve(String)} and {@link #retrieve(String, String)} -> getUser(String), getUser(String, String) | |
63 | * <li>{@link #retrieveList(Object)} -> getAllUsers() | |
64 | * <li>{@link #accountExists(String)}, {@link #accountExists(User)} -> checkExists(String), checkExists(User) | |
65 | * </ul> | |
66 | * | |
67 | * </li> | |
68 | * </ol> | |
69 | * | |
70 | * In this way all public methods of Fulcrum {@link TurbineUserManager} interface are used by reference of the Fulcrum delegate {@link #umDelegate} | |
71 | * and wrapped by this manager. | |
72 | * | |
73 | * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a> | |
74 | * @version $Id: PassiveUserManager.java 1096130 2011-04-23 10:37:19Z ludwig $ | |
75 | */ | |
76 | 15 | public class DefaultUserManager implements UserManager |
77 | { | |
78 | /** Fulcrum user manager instance to delegate to */ | |
79 | 15 | private TurbineUserManager umDelegate = null; |
80 | ||
81 | 15 | private FactoryService factoryService = null; |
82 | ||
83 | /** The user class, which the UserManager uses as wrapper for Fulcrum {@link TurbineUser} */ | |
84 | private String userWrapperClass; | |
85 | ||
86 | ||
87 | /** Logging */ | |
88 | 15 | private static final Logger log = LogManager.getLogger(DefaultUserManager.class); |
89 | ||
90 | /** | |
91 | * Wrap a Fulcrum user object into a Turbine user object | |
92 | * | |
93 | * @param <U> user class | |
94 | * @param user the user object to delegate to | |
95 | * | |
96 | * @return the wrapped object | |
97 | */ | |
98 | protected <U extends User> U wrap(TurbineUser user) | |
99 | { | |
100 | @SuppressWarnings("unchecked") | |
101 | 24 | U u = (U) getUserWrapper(user); |
102 | 24 | return u; |
103 | } | |
104 | ||
105 | /** | |
106 | * Exception could be ignored, as it is tested before in {@link #init(Configuration)}. | |
107 | * | |
108 | * @param <U> user class | |
109 | * @param user the user object to wrap | |
110 | * @return instance extending {@link User} | |
111 | */ | |
112 | @SuppressWarnings("unchecked") | |
113 | public <U extends User> U getUserWrapper(TurbineUser user) | |
114 | { | |
115 | try | |
116 | { | |
117 | 24 | Object params[] = new Object[] { user }; |
118 | 24 | String signature[] = new String[] { TurbineUser.class.getName() }; |
119 | 24 | return (U) factoryService.getInstance(getUserWrapperClass(), params, signature); |
120 | } | |
121 | 0 | catch (Exception e) |
122 | { | |
123 | 0 | log.error("after init/late instantiation exception", e); |
124 | 0 | return null; // (U)new DefaultUserImpl(user); |
125 | } | |
126 | } | |
127 | ||
128 | /** | |
129 | * Get the wrapper class for user objects | |
130 | * | |
131 | * @return the wrapper class name | |
132 | */ | |
133 | public String getUserWrapperClass() | |
134 | { | |
135 | 24 | return userWrapperClass; |
136 | } | |
137 | ||
138 | /** | |
139 | * Set the wrapper class for user objects | |
140 | * | |
141 | * @param userWrapperClass2 the wrapper class name | |
142 | */ | |
143 | public void setUserWrapperClass(String userWrapperClass2) | |
144 | { | |
145 | 15 | userWrapperClass = userWrapperClass2; |
146 | 15 | } |
147 | ||
148 | /** | |
149 | * Initializes the UserManager | |
150 | * | |
151 | * @param conf A Configuration object to init this Manager | |
152 | */ | |
153 | @Override | |
154 | public void init(Configuration conf) throws InitializationException | |
155 | { | |
156 | 15 | ServiceManager manager = TurbineServices.getInstance(); |
157 | 15 | this.umDelegate = (TurbineUserManager)manager.getService(TurbineUserManager.ROLE); |
158 | ||
159 | 15 | String userWrapperClass = conf.getString( |
160 | SecurityService.USER_WRAPPER_KEY, | |
161 | SecurityService.USER_WRAPPER_DEFAULT); | |
162 | ||
163 | try | |
164 | { | |
165 | 15 | factoryService = (FactoryService)manager.getService(FactoryService.ROLE); |
166 | ||
167 | // check instantiation | |
168 | // should provide default constructor | |
169 | 15 | TurbineUser turbineUser = umDelegate.getUserInstance(); |
170 | //(TurbineUser) factoryService.getInstance(userClass); | |
171 | 15 | Object params[] = new Object[] { turbineUser }; |
172 | 15 | String signature[] = new String[] { TurbineUser.class.getName() }; |
173 | ||
174 | // Just check if exceptions would occur | |
175 | 15 | factoryService.getInstance(userWrapperClass, params, signature); |
176 | ||
177 | 15 | this.setUserWrapperClass(userWrapperClass); |
178 | } | |
179 | 0 | catch (Exception e) |
180 | { | |
181 | 0 | throw new InitializationException("Failed to instantiate user wrapper class", e); |
182 | 15 | } |
183 | 15 | } |
184 | ||
185 | ||
186 | /** | |
187 | * Check whether a specified user's account exists. | |
188 | * | |
189 | * The login name is used for looking up the account. | |
190 | * | |
191 | * @param user The user to be checked. | |
192 | * @return true if the specified account exists | |
193 | * @throws DataBackendException if there was an error accessing the data backend. | |
194 | */ | |
195 | @Override | |
196 | public boolean accountExists(User user) | |
197 | throws DataBackendException | |
198 | { | |
199 | 6 | if (user == null) { |
200 | 0 | return false; |
201 | } | |
202 | 6 | return umDelegate.checkExists(user.getUserDelegate()); |
203 | } | |
204 | ||
205 | /** | |
206 | * Check whether a specified user's account exists. | |
207 | * | |
208 | * The login name is used for looking up the account. | |
209 | * | |
210 | * @param userName The name of the user to be checked. | |
211 | * @return true if the specified account exists | |
212 | * @throws DataBackendException if there was an error accessing the data backend. | |
213 | */ | |
214 | @Override | |
215 | public boolean accountExists(String userName) | |
216 | throws DataBackendException | |
217 | { | |
218 | 6 | return umDelegate.checkExists(userName); |
219 | } | |
220 | ||
221 | /** | |
222 | * Retrieve a user from persistent storage using username as the | |
223 | * key. | |
224 | * | |
225 | * @param username the name of the user. | |
226 | * @return an User object. | |
227 | * @throws UnknownEntityException if the user's record does not | |
228 | * exist in the database. | |
229 | * @throws DataBackendException if there is a problem accessing the | |
230 | * storage. | |
231 | */ | |
232 | @Override | |
233 | public <U extends User> U retrieve(String username) | |
234 | throws UnknownEntityException, DataBackendException | |
235 | { | |
236 | 3 | TurbineUser u = umDelegate.getUser(username); |
237 | 3 | return wrap(u); |
238 | } | |
239 | ||
240 | /** | |
241 | * Retrieve a set of users that meet the specified criteria. | |
242 | * | |
243 | * As the keys for the criteria, you should use the constants that | |
244 | * are defined in {@link User} interface, plus the names | |
245 | * of the custom attributes you added to your user representation | |
246 | * in the data storage. Use verbatim names of the attributes - | |
247 | * without table name prefix in case of DB implementation. | |
248 | * | |
249 | * @param criteria The criteria of selection. | |
250 | * @return a List of users meeting the criteria. | |
251 | * @throws DataBackendException if there is a problem accessing the | |
252 | * storage. | |
253 | */ | |
254 | @Override | |
255 | public List<? extends User> retrieveList(Object criteria) | |
256 | throws DataBackendException | |
257 | { | |
258 | 0 | UserSet<org.apache.fulcrum.security.entity.User> uset = umDelegate.getAllUsers(); |
259 | 0 | List<User> userList = new ArrayList<User>(); |
260 | ||
261 | 0 | for (org.apache.fulcrum.security.entity.User u : uset) |
262 | { | |
263 | 0 | TurbineUser tu = (TurbineUser)u; |
264 | 0 | userList.add(wrap(tu)); |
265 | 0 | } |
266 | ||
267 | 0 | return userList; |
268 | } | |
269 | ||
270 | /** | |
271 | * Retrieve a user from persistent storage using username as the | |
272 | * key, and authenticate the user. The implementation may chose | |
273 | * to authenticate to the server as the user whose data is being | |
274 | * retrieved. | |
275 | * | |
276 | * @param username the name of the user. | |
277 | * @param password the user supplied password. | |
278 | * @return an User object. | |
279 | * @throws PasswordMismatchException if the supplied password was | |
280 | * incorrect. | |
281 | * @throws UnknownEntityException if the user's record does not | |
282 | * exist in the database. | |
283 | * @throws DataBackendException if there is a problem accessing the | |
284 | * storage. | |
285 | */ | |
286 | @Override | |
287 | public <U extends User> U retrieve(String username, String password) | |
288 | throws PasswordMismatchException, UnknownEntityException, | |
289 | DataBackendException | |
290 | { | |
291 | 3 | TurbineUser u = umDelegate.getUser(username, password); |
292 | 3 | return wrap(u); |
293 | } | |
294 | ||
295 | /** | |
296 | * Save an User object to persistent storage. User's record is | |
297 | * required to exist in the storage. | |
298 | * | |
299 | * @param user an User object to store. | |
300 | * @throws UnknownEntityException if the user's record does not | |
301 | * exist in the database. | |
302 | * @throws DataBackendException if there is a problem accessing the | |
303 | * storage. | |
304 | */ | |
305 | @Override | |
306 | public void store(User user) | |
307 | throws UnknownEntityException, DataBackendException | |
308 | { | |
309 | 3 | if (user == null) { |
310 | 0 | throw new UnknownEntityException("user is null"); |
311 | } | |
312 | try | |
313 | { | |
314 | 3 | user.setObjectdata(ObjectUtils.serializeMap(user.getPermStorage())); |
315 | } | |
316 | 0 | catch (Exception e) |
317 | { | |
318 | 0 | throw new DataBackendException("Could not serialize permanent storage", e); |
319 | 3 | } |
320 | ||
321 | 3 | umDelegate.saveUser(((TurbineUserDelegate)user).getUserDelegate()); |
322 | 3 | } |
323 | ||
324 | /** | |
325 | * Saves User data when the session is unbound. The user account is required | |
326 | * to exist in the storage. | |
327 | * | |
328 | * LastLogin, AccessCounter, persistent pull tools, and any data stored | |
329 | * in the permData hashtable that is not mapped to a column will be saved. | |
330 | * | |
331 | * @throws UnknownEntityException if the user's account does not | |
332 | * exist in the database. | |
333 | * @throws DataBackendException if there is a problem accessing the | |
334 | * storage. | |
335 | */ | |
336 | @Override | |
337 | public void saveOnSessionUnbind(User user) | |
338 | throws UnknownEntityException, DataBackendException | |
339 | { | |
340 | 0 | store(user); |
341 | 0 | } |
342 | ||
343 | /** | |
344 | * Authenticate an User with the specified password. If authentication | |
345 | * is successful the method returns nothing. If there are any problems, | |
346 | * exception was thrown. | |
347 | * | |
348 | * @param user an User object to authenticate. | |
349 | * @param password the user supplied password. | |
350 | * @throws PasswordMismatchException if the supplied password was | |
351 | * incorrect. | |
352 | * @throws UnknownEntityException if the user's record does not | |
353 | * exist in the database. | |
354 | * @throws DataBackendException if there is a problem accessing the | |
355 | * storage. | |
356 | */ | |
357 | @Override | |
358 | public void authenticate(User user, String password) | |
359 | throws PasswordMismatchException, UnknownEntityException, | |
360 | DataBackendException | |
361 | { | |
362 | 0 | umDelegate.authenticate(user, password); |
363 | 0 | } |
364 | ||
365 | /** | |
366 | * Creates new user account with specified attributes. | |
367 | * | |
368 | * @param user the object describing account to be created. | |
369 | * @param initialPassword The password to use for the object creation | |
370 | * | |
371 | * @throws DataBackendException if there was an error accessing the data backend. | |
372 | * @throws EntityExistsException if the user account already exists. | |
373 | */ | |
374 | @Override | |
375 | public void createAccount(User user, String initialPassword) | |
376 | throws UnknownEntityException, EntityExistsException, DataBackendException | |
377 | { | |
378 | 9 | if (user == null) { |
379 | 0 | throw new UnknownEntityException("user is null"); |
380 | } | |
381 | 9 | umDelegate.addUser(user.getUserDelegate(), initialPassword); |
382 | 9 | } |
383 | ||
384 | /** | |
385 | * Removes an user account from the system. | |
386 | * | |
387 | * @param user the object describing the account to be removed. | |
388 | * @throws DataBackendException if there was an error accessing the data backend. | |
389 | * @throws UnknownEntityException if the user account is not present. | |
390 | */ | |
391 | @Override | |
392 | public void removeAccount(User user) | |
393 | throws UnknownEntityException, DataBackendException | |
394 | { | |
395 | 0 | if (user == null) { |
396 | 0 | throw new UnknownEntityException("user is null"); |
397 | } | |
398 | 0 | umDelegate.removeUser(user.getUserDelegate()); |
399 | 0 | } |
400 | ||
401 | /** | |
402 | * Change the password for an User. | |
403 | * | |
404 | * @param user an User to change password for. | |
405 | * @param oldPassword the current password supplied by the user. | |
406 | * @param newPassword the current password requested by the user. | |
407 | * @throws PasswordMismatchException if the supplied password was | |
408 | * incorrect. | |
409 | * @throws UnknownEntityException if the user's record does not | |
410 | * exist in the database. | |
411 | * @throws DataBackendException if there is a problem accessing the | |
412 | * storage. | |
413 | */ | |
414 | @Override | |
415 | public void changePassword(User user, String oldPassword, | |
416 | String newPassword) | |
417 | throws PasswordMismatchException, UnknownEntityException, | |
418 | DataBackendException | |
419 | { | |
420 | 0 | if (user == null) { |
421 | 0 | throw new UnknownEntityException("user is null"); |
422 | } | |
423 | 0 | umDelegate.changePassword( |
424 | 0 | ((TurbineUserDelegate)user).getUserDelegate(), |
425 | oldPassword, newPassword); | |
426 | 0 | } |
427 | ||
428 | /** | |
429 | * Forcibly sets new password for an User. | |
430 | * | |
431 | * This is supposed by the administrator to change the forgotten or | |
432 | * compromised passwords. Certain implementations of this feature | |
433 | * would require administrative level access to the authenticating | |
434 | * server / program. | |
435 | * | |
436 | * @param user an User to change password for. | |
437 | * @param password the new password. | |
438 | * @throws UnknownEntityException if the user's record does not | |
439 | * exist in the database. | |
440 | * @throws DataBackendException if there is a problem accessing the | |
441 | * storage. | |
442 | */ | |
443 | @Override | |
444 | public void forcePassword(User user, String password) | |
445 | throws UnknownEntityException, DataBackendException | |
446 | { | |
447 | 0 | if (user == null) { |
448 | 0 | throw new UnknownEntityException("user is null"); |
449 | } | |
450 | 0 | umDelegate.forcePassword(user.getUserDelegate(), password); |
451 | 0 | } |
452 | ||
453 | /** | |
454 | * Constructs an User object to represent an anonymous user of the | |
455 | * application. | |
456 | * | |
457 | * @return An anonymous Turbine User. | |
458 | * @throws UnknownEntityException | |
459 | * if the anonymous User object couldn't be constructed. | |
460 | */ | |
461 | @Override | |
462 | public <U extends User> U getAnonymousUser() throws UnknownEntityException | |
463 | { | |
464 | 12 | TurbineUser u = umDelegate.getAnonymousUser(); |
465 | 12 | return wrap(u); |
466 | } | |
467 | ||
468 | /** | |
469 | * Checks whether a passed user object matches the anonymous user pattern | |
470 | * according to the configured user manager | |
471 | * | |
472 | * @param u a user object | |
473 | * | |
474 | * @return True if this is an anonymous user | |
475 | * | |
476 | */ | |
477 | @Override | |
478 | public boolean isAnonymousUser(User u) | |
479 | { | |
480 | 12 | return umDelegate.isAnonymousUser(u); |
481 | } | |
482 | ||
483 | /** | |
484 | * Construct a blank User object. | |
485 | * | |
486 | * This method calls getUserClass, and then creates a new object using the | |
487 | * default constructor. | |
488 | * | |
489 | * @return an object implementing User interface. | |
490 | * @throws DataBackendException | |
491 | * if the object could not be instantiated. | |
492 | */ | |
493 | @Override | |
494 | public <U extends User> U getUserInstance() throws DataBackendException | |
495 | { | |
496 | 3 | TurbineUser u = umDelegate.getUserInstance(); |
497 | 3 | return wrap(u); |
498 | } | |
499 | ||
500 | /** | |
501 | * Construct a blank User object. | |
502 | * | |
503 | * This method calls getUserClass, and then creates a new object using the | |
504 | * default constructor. | |
505 | * | |
506 | * @param userName | |
507 | * The name of the user. | |
508 | * | |
509 | * @return an object implementing User interface. | |
510 | * @throws DataBackendException | |
511 | * if the object could not be instantiated. | |
512 | */ | |
513 | @Override | |
514 | public <U extends User> U getUserInstance(String userName) throws DataBackendException | |
515 | { | |
516 | 3 | TurbineUser u = umDelegate.getUserInstance(userName); |
517 | 3 | return wrap(u); |
518 | } | |
519 | ||
520 | /** | |
521 | * Return a Class object representing the system's chosen implementation of | |
522 | * of ACL interface. | |
523 | * | |
524 | * @return systems's chosen implementation of ACL interface. | |
525 | * @throws UnknownEntityException | |
526 | * if the implementation of ACL interface could not be | |
527 | * determined, or does not exist. | |
528 | */ | |
529 | @Override | |
530 | public <A extends AccessControlList> A getACL(User user) throws UnknownEntityException | |
531 | { | |
532 | 3 | if (user == null) { |
533 | 0 | throw new UnknownEntityException("user is null"); |
534 | } | |
535 | 3 | return umDelegate.getACL(user.getUserDelegate()); |
536 | } | |
537 | } |