Added author to all java files with class comments.
[utils] / security / src / test / java / org / wamblee / usermgt / UserAdministrationImplTest.java
1 /*
2  * Copyright 2005 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.wamblee.usermgt;
18
19 import java.util.Set;
20
21 import org.apache.log4j.Logger;
22 import org.wamblee.persistence.hibernate.HibernateMappingFiles;
23 import org.wamblee.security.encryption.Md5HexMessageDigester;
24 import org.wamblee.test.SpringConfigFiles;
25 import org.wamblee.test.SpringTestCase;
26 import org.wamblee.usermgt.UserMgtException.Reason;
27
28 /**
29  * Test of user administration implementation.
30  *
31  * @author Erik Brakkee
32  */
33 public class UserAdministrationImplTest extends SpringTestCase {
34
35     private static final Logger LOGGER = Logger
36             .getLogger(UserAdministrationImplTest.class);
37
38     private static final String USER1 = "piet";
39
40     private static final String PASS1 = "passpiet";
41
42     private static final String USER2 = "kees";
43
44     private static final String PASS2 = "passkees";
45
46     private static final String GROUP1 = "cyclists";
47
48     private static final String GROUP2 = "runners";
49
50     private UserAdministration _admin;
51
52     public UserAdministrationImplTest() {
53         super(SpringConfigFiles.class, HibernateMappingFiles.class);
54     }
55
56     public UserAdministrationImplTest(
57             Class<? extends SpringConfigFiles> aSprings,
58             Class<? extends HibernateMappingFiles> aMappings) {
59         super(aSprings, aMappings);
60     }
61
62     /*
63      * (non-Javadoc)
64      * 
65      * @see junit.framework.TestCase#setUp()
66      */
67     @Override
68     protected void setUp() throws Exception {
69         super.setUp();
70         _admin = createAdmin();
71     }
72
73     protected UserAdministration createAdmin() {
74         UserSet users = new InMemoryUserSet(   new RegexpNameValidator(RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, "Password must contain at least 6 characters"),
75                 new Md5HexMessageDigester());
76         GroupSet groups = new InMemoryGroupSet();
77         return new UserAdministrationImpl(users, groups,
78                 new RegexpNameValidator(RegexpNameValidator.ID_PATTERN,
79                         Reason.INVALID_USERNAME, "Invalid user"),
80                 new RegexpNameValidator(RegexpNameValidator.ID_PATTERN,
81                         Reason.INVALID_GROUPNAME, "Invalid group"));
82     }
83     
84     protected User createUser(String aName, String aPassword, Group aGroup) throws UserMgtException { 
85         return UsermgtTestUtils.createUser(aName, aPassword, aGroup);
86     }
87
88     /**
89      * Constructs the admin, verify it contains no users and no groups.
90      */
91     public void testConstruct() {
92         assertEquals(0, _admin.getUsers().size());
93         assertEquals(0, _admin.getGroups().size());
94         assertEquals(0, _admin.getUserCount());
95         assertEquals(0, _admin.getGroupCount());
96     }
97
98     /**
99      * Creates a new group. Verifies the group is created correctly and that the
100      * user is added.
101      * 
102      */
103     public void testCreateGroup() throws UserMgtException {
104         Group group = _admin.createGroup(GROUP1);
105         assertNotNull(group);
106         assertEquals(GROUP1, group.getName());
107
108         Set<Group> groups = _admin.getGroups();
109         assertEquals(1, groups.size());
110         assertEquals(1, _admin.getGroupCount());
111         assertTrue(groups.contains(group));
112     }
113
114     private void createInvalidGroup(String aUsername) {
115         try {
116             _admin.createGroup(aUsername);
117             fail();
118         } catch (UserMgtException e) {
119             assertEquals(UserMgtException.Reason.INVALID_GROUPNAME, e
120                     .getReason());
121             assertEquals(0, _admin.getGroupCount());
122         }
123     }
124
125     /**
126      * Creates a new group with an invalid name. Verifies that the appropriate
127      * exception is thrown.
128      * 
129      * @throws UserMgtException
130      */
131     public void testCreateInvalidGroupName() throws UserMgtException {
132         createInvalidGroup("");
133         createInvalidGroup("0abc"); // should not start with digits
134         createInvalidGroup("a b"); // should not contain spaces
135         createInvalidGroup(" aa");
136         createInvalidGroup("aa ");
137     }
138
139     /**
140      * Creates a new group which conflicts with an existing one. Verifies that
141      * the UserMgtException is thrown and that no group is added.
142      * 
143      */
144     public void testCreateDuplicateGroup() throws UserMgtException {
145         _admin.createGroup(GROUP1);
146         try {
147             _admin.createGroup(GROUP1);
148         } catch (UserMgtException e) {
149             assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason());
150             assertEquals(1, _admin.getGroupCount());
151             return;
152         }
153         fail();
154     }
155
156     /**
157      * Creates a new user. Verifies the user is created correctly and that the
158      * user is added.
159      * 
160      */
161     public void testCreateUser() throws UserMgtException {
162         Group group = _admin.createGroup(GROUP1);
163         User user = _admin.createUser(USER1, PASS1, group);
164         assertNotNull(user);
165         assertEquals(USER1, user.getName());
166         user.checkPassword(PASS1);
167
168         Set<User> users = _admin.getUsers();
169         assertEquals(1, users.size());
170         assertEquals(1, _admin.getUserCount());
171         assertTrue(users.contains(user));
172     }
173
174     private void createInvalidUser(String aUsername, Group aGroup) {
175         try {
176             _admin.createUser(aUsername, "pass", aGroup);
177             fail();
178         } catch (UserMgtException e) {
179             assertEquals(UserMgtException.Reason.INVALID_USERNAME, e
180                     .getReason());
181             assertEquals(0, _admin.getUserCount());
182         }
183     }
184
185     /**
186      * Constructs users with invalid names. Verifies that the appropriate
187      * exception is thrown.
188      * 
189      */
190     public void testCreateInvalidUserName() throws UserMgtException {
191         Group group = _admin.createGroup(GROUP1);
192         createInvalidUser("", group);
193         createInvalidUser("0abc", group); // should not start with digits
194         createInvalidUser("a b", group); // should not contain spaces
195         createInvalidUser(" aa", group);
196         createInvalidUser("aa ", group);
197     }
198
199     /**
200      * Creates a new user which conflicts with an existing one. Verifies that
201      * the UserMgtException is thrown and that no user is added.
202      * 
203      */
204     public void testCreateDuplicateUser() throws UserMgtException {
205         Group group = _admin.createGroup(GROUP1);
206         _admin.createUser(USER1, PASS1, group);
207         try {
208             _admin.createUser(USER1, PASS2, group);
209             fail();
210         } catch (UserMgtException e) {
211             assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason());
212             assertEquals(1, _admin.getUserCount());
213         }
214     }
215
216     /**
217      * Gets a known user by name. Verifies the correct user is obtained.
218      * Verifies that null is returned when trying to obtain an unknown user.
219      * 
220      */
221     public void testGetUser() throws UserMgtException {
222         Group group = _admin.createGroup(GROUP1);
223         User user = _admin.createUser(USER1, PASS1, group);
224         User user2 = _admin.getUser(USER1);
225         assertTrue(user.equals(user2));
226         assertNull(_admin.getUser(USER2));
227     }
228
229     /**
230      * Gets a known group by name. Verifies the correct group is obtained.
231      * Verifies that null is returned when the group is not known.
232      * 
233      */
234     public void testGetGroup() throws UserMgtException {
235         Group group = _admin.createGroup(GROUP1);
236         Group group2 = _admin.getGroup(GROUP1);
237         assertTrue(group.equals(group2));
238         assertNull(_admin.getGroup(GROUP2));
239     }
240
241     /**
242      * Adds a user to a group. Verifies that the user is added using several API
243      * calls. Verifies that an exception occurs if the user is not already part
244      * of the group.
245      * 
246      */
247     public void testAddUserToGroup() throws UserMgtException {
248
249         Group group = _admin.createGroup(GROUP1);
250         User user = _admin.createUser(USER1, PASS1, group);
251         Group group2 = _admin.createGroup(GROUP2);
252         assertTrue(user.isInGroup(group));
253         assertFalse(user.isInGroup(group2));
254         _admin.addUserToGroup(user, group2);
255         assertTrue(user.isInGroup(group));
256         assertTrue(user.isInGroup(group2));
257         Set<User> users = _admin.getUsers(group2);
258         assertNotNull(users);
259         assertEquals(1, users.size());
260         assertTrue(users.contains(user));
261
262         try {
263             _admin.addUserToGroup(user, group);
264         } catch (UserMgtException e) {
265             assertEquals(UserMgtException.Reason.USER_ALREADY_IN_GROUP, e
266                     .getReason());
267             return;
268         }
269         fail();
270     }
271
272     /**
273      * Adds a user to a group where the user does not exist. Verifies that an
274      * exception occurs.
275      * 
276      */
277     public void testAddUserToGroupUnknownUser() throws UserMgtException {
278         Group group = _admin.createGroup(GROUP1);
279         User user = createUser(USER1, PASS1, group);
280         try {
281             _admin.addUserToGroup(user, group);
282         } catch (UserMgtException e) {
283             assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason());
284             return;
285         }
286         fail();
287     }
288
289     /**
290      * Adds a user to a group where the user does not exist. Verifies that an
291      * exception occurs.
292      * 
293      */
294     public void testAddUserToGroupUnknownGroup() throws UserMgtException {
295         Group group = _admin.createGroup(GROUP1);
296         User user = _admin.createUser(USER1, PASS1, group);
297         Group group2 = new Group(GROUP2);
298         try {
299             _admin.addUserToGroup(user, group2);
300         } catch (UserMgtException e) {
301             assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason());
302             return;
303         }
304         fail();
305     }
306
307     /**
308      * Removes a user from a group. Verifies that the user is removed from the
309      * group using several API calls. Verifies that an exception occurs if the
310      * user not part of the group or if the user is only part of one group.
311      */
312     public void testRemoveUserFromGroup() throws UserMgtException {
313         Group group = _admin.createGroup(GROUP1);
314
315         User user = _admin.createUser(USER1, PASS1, group);
316         Group group2 = _admin.createGroup(GROUP2);
317         _admin.addUserToGroup(user, group2);
318         Set<Group> groups = user.getGroups();
319         assertEquals(2, groups.size());
320         assertTrue(groups.contains(group));
321         assertTrue(groups.contains(group2));
322
323         _admin.removeUserFromGroup(user, group);
324         groups = user.getGroups();
325         assertEquals(1, groups.size());
326         assertTrue(groups.contains(group2));
327         assertFalse(groups.contains(group));
328     }
329
330     /**
331      * Removes a user from a group where the user is not known. Verifies that an
332      * exception is thrown.
333      * 
334      */
335     public void testRemoveUserFromGroupUnknownUser() throws UserMgtException {
336         Group group = _admin.createGroup(GROUP1);
337         User user = createUser(USER1, GROUP1, group);
338         try {
339             _admin.removeUserFromGroup(user, group);
340         } catch (UserMgtException e) {
341             assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason());
342         }
343     }
344
345     /**
346      * Removes a user from a group where the group is not known. Verifies that
347      * an exception is thrown.
348      * 
349      */
350     public void testRemoveUserFromGroupUnknownGroup() throws UserMgtException {
351         Group group = _admin.createGroup(GROUP1);
352         User user = _admin.createUser(USER1, PASS1, group);
353         Group group2 = new Group(GROUP2);
354         try {
355             _admin.removeUserFromGroup(user, group2);
356         } catch (UserMgtException e) {
357             assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason());
358         }
359     }
360
361     /**
362      * Removes a user from a group where the user is only part of one group.
363      * Verifies that an exception is thrown.
364      */
365     public void testRemoveUserFromGroupOnlyGroup() throws UserMgtException {
366         Group group = _admin.createGroup(GROUP1);
367         User user = _admin.createUser(USER1, PASS1, group);
368         try {
369             _admin.removeUserFromGroup(user, group);
370         } catch (UserMgtException e) {
371             assertEquals(UserMgtException.Reason.USER_MUST_BE_IN_A_GROUP, e
372                     .getReason());
373         }
374     }
375
376     /**
377      * Gets the list of users and groups. Verifies that the correct suers and
378      * groups are returned. Verifies also that the relations from user to group
379      * are correct.
380      * 
381      */
382     public void testGetUsersAndGroups() throws UserMgtException {
383         Group group1 = _admin.createGroup(GROUP1);
384         Group group2 = _admin.createGroup(GROUP2);
385
386         User user1 = _admin.createUser(USER1, PASS1, group1);
387         _admin.addUserToGroup(user1, group2);
388         User user2 = _admin.createUser(USER2, PASS2, group2);
389
390         Set<User> users = _admin.getUsers();
391         assertEquals(2, users.size());
392         assertTrue(users.contains(user1));
393         assertTrue(users.contains(user2));
394
395         Set<Group> groups = _admin.getGroups();
396         assertEquals(2, groups.size());
397         assertTrue(groups.contains(group1));
398         assertTrue(groups.contains(group2));
399
400         assertTrue(user1.isInGroup(group1));
401         assertTrue(user1.isInGroup(group2));
402         assertFalse(user2.isInGroup(group1));
403         assertTrue(user2.isInGroup(group2));
404
405         Set<Group> groups1 = user1.getGroups();
406         assertEquals(2, groups1.size());
407
408         Set<Group> groups2 = user2.getGroups();
409         assertEquals(1, groups2.size());
410     }
411
412     /**
413      * Renames a user. Verifies that the user is renamed. Verifies that
414      * exceptions are thrown when an attempt is made to rename the user to
415      * itself or to another existing user, or when the group does not exist.
416      * 
417      */
418     public void testRenameUser() throws UserMgtException {
419         Group group = _admin.createGroup(GROUP1);
420         User user1 = _admin.createUser(USER1, PASS1, group);
421         _admin.renameUser(user1, USER2);
422         assertEquals(USER2, user1.getName());
423         assertEquals(user1, _admin.getUser(USER2));
424
425         _admin.createUser(USER1, PASS1, group);
426
427         try {
428             _admin.renameUser(user1, USER1);
429         } catch (UserMgtException e) {
430             assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason());
431
432             // do a trivial reanem
433             try {
434                 _admin.renameUser(user1, user1.getName());
435             } catch (UserMgtException e2) {
436                 assertEquals(UserMgtException.Reason.TRIVIAL_RENAME, e2
437                         .getReason());
438                 return;
439             }
440             fail();
441         }
442         fail();
443     }
444
445     /**
446      * Renames a user to a user with an invalid username. Verifies that the
447      * appropriate exception is thrown.
448      * 
449      */
450     public void testRenameUserInvalidUsername() throws UserMgtException {
451         Group group = _admin.createGroup(GROUP1);
452         User user1 = _admin.createUser(USER1, PASS1, group);
453         try {
454             _admin.renameUser(user1, USER2);
455         } catch (UserMgtException e) {
456             assertEquals(e.getReason(), Reason.INVALID_USERNAME);
457         }
458     }
459
460     /**
461      * Renames a group. Verifies that the group is renamed. Verifies that
462      * exceptions are thrown when an attempt is made to rename the group to
463      * itself or to another existing group or when the group does not exist.
464      * 
465      */
466     public void testRenameGroup() throws UserMgtException {
467         Group group = _admin.createGroup(GROUP1);
468         _admin.renameGroup(group, GROUP2);
469         assertEquals(GROUP2, group.getName());
470         assertEquals(group, _admin.getGroup(GROUP2));
471
472         _admin.createGroup(GROUP1);
473         try {
474             _admin.renameGroup(group, GROUP1);
475         } catch (UserMgtException e) {
476             assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason());
477
478             // do a trivial reanem
479             try {
480                 _admin.renameGroup(group, group.getName());
481             } catch (UserMgtException e2) {
482                 assertEquals(UserMgtException.Reason.TRIVIAL_RENAME, e2
483                         .getReason());
484                 return;
485             }
486             fail();
487             return;
488         }
489         fail();
490     }
491
492     /**
493      * Renames a group to a group with an invalid name. Verifies that the
494      * appropriate exception is thrown.
495      * 
496      */
497     public void testRenameGroupInvalidGroupname() throws UserMgtException {
498         Group group = _admin.createGroup(GROUP1);
499         try {
500             _admin.renameGroup(group, "a b");
501         } catch (UserMgtException e) {
502             assertEquals(e.getReason(), Reason.INVALID_GROUPNAME);
503         }
504     }
505
506     /**
507      * Removes a user. Verifies that the user is removed. Verifies that the an
508      * exception is thrown when the user does not exist.
509      * 
510      */
511     public void testRemoveUser() throws UserMgtException {
512         Group group = _admin.createGroup(GROUP1);
513         User user = _admin.createUser(USER1, PASS1, group);
514
515         assertEquals(1, _admin.getUserCount());
516         _admin.removeUser(user);
517         assertEquals(0, _admin.getUserCount());
518
519         _admin.createUser(USER1, PASS1, group);
520         assertEquals(1, _admin.getUserCount());
521
522         User user2 = createUser(USER2, PASS2, group);
523
524         try {
525             _admin.removeUser(user2);
526         } catch (UserMgtException e) {
527             assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason());
528         }
529     }
530
531     /**
532      * Removes a group. Verifies that the group is removed. Verifies that the an
533      * exception is thrown when the group does not exist or if there are still
534      * users in the group.
535      * 
536      */
537     public void testRemoveGroup() throws UserMgtException {
538         Group group1 = _admin.createGroup(GROUP1);
539         assertEquals(1, _admin.getGroupCount());
540         _admin.removeGroup(group1);
541         assertEquals(0, _admin.getGroupCount());
542         group1 = _admin.createGroup(GROUP1);
543
544         _admin.createUser(USER1, PASS1, group1);
545         try {
546             _admin.removeGroup(group1);
547         } catch (UserMgtException e) {
548             assertEquals(UserMgtException.Reason.GROUP_STILL_OCCUPIED, e
549                     .getReason());
550             return;
551         }
552         fail();
553     }
554
555     /**
556      * Tries to remove an unknown group. Verifies that an exception is thrown.
557      * 
558      */
559     public void testRemoveGroupUnknownGroup() throws UserMgtException {
560         Group group = _admin.createGroup(GROUP1);
561         Group group2 = new Group(GROUP2);
562         try {
563             _admin.removeGroup(group2);
564         } catch (UserMgtException e) {
565             assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason());
566         }
567     }
568
569     /**
570      * Changes the password, verifies that this succeeds.
571      * 
572      * @throws UserMgtException
573      */
574     public void testChangePassword() throws UserMgtException {
575         Group group = _admin.createGroup(GROUP1);
576         User user = _admin.createUser(USER1, PASS1, group);
577         user.changePassword(PASS1, PASS2);
578
579         // retrieve the user and verifies the password hasn't changed.
580         User user2 = _admin.getUser(USER1);
581         try {
582             user2.checkPassword(PASS2);
583             fail(); // password should not have changed already.
584         } catch (UserMgtException e) {
585             // ok.
586         }
587
588         // now notify the admin of the change in the user
589         _admin.userModified(user);
590
591         user2 = _admin.getUser(USER1);
592         user2.checkPassword(PASS2); // this time it should succeed.
593
594     }
595
596     /**
597      * Performance test. Finds a user by name.
598      * 
599      */
600     public void testPerformanceFindUserByName() throws UserMgtException {
601         Group group = _admin.createGroup(GROUP1);
602         _admin.createUser(USER1, PASS1, group);
603
604         int n = 1000;
605         long time = System.currentTimeMillis();
606         for (int i = 0; i < n; i++) {
607             _admin.getUser(USER1);
608         }
609         LOGGER.info("Looked up a user " + n + " times in "
610                 + (float) (System.currentTimeMillis() - time) / 1000.0);
611     }
612
613 }