(no commit message)
[utils] / security / impl / src / main / java / org / wamblee / usermgt / User.java
1 /*
2  * Copyright 2005-2010 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 package org.wamblee.usermgt;
17
18 import org.wamblee.security.AbstractPersistent;
19 import org.wamblee.security.encryption.MessageDigester;
20
21 import org.wamblee.usermgt.UserMgtException.Reason;
22
23 import java.io.Serializable;
24
25 import java.util.Set;
26 import java.util.TreeSet;
27
28 import javax.persistence.CascadeType;
29 import javax.persistence.Entity;
30 import javax.persistence.FetchType;
31 import javax.persistence.GeneratedValue;
32 import javax.persistence.GenerationType;
33 import javax.persistence.Id;
34 import javax.persistence.ManyToMany;
35 import javax.persistence.NamedQueries;
36 import javax.persistence.NamedQuery;
37 import javax.persistence.Table;
38 import javax.persistence.Transient;
39 import javax.persistence.Version;
40
41 /**
42  * Represents a user. The methods for managing the groups of the user have
43  * package scope. Managing the groups of the user should be done through the
44  * {@link org.wamblee.usermgt.UserAdministration} interface.
45  */
46 @Entity
47 @Table(name = "SEC_USER")
48 @NamedQueries( {
49     @NamedQuery(name = User.QUERY_FIND_BY_NAME, query = "select u from User u where u.name = :" +
50         User.NAME_PARAM),
51     @NamedQuery(name = User.QUERY_FIND_BY_GROUP_NAME, query = "select user from User user join user.groups grp where grp.name = :name"),
52     @NamedQuery(name = User.QUERY_COUNT_USERS, query = "select count(u) from User u"),
53     @NamedQuery(name = User.QUERY_ALL_USERS, query = "select u from User u")})
54 public class User implements Serializable, Comparable {
55
56     public static final String QUERY_FIND_BY_NAME = "User.findByName";
57     public static final String QUERY_FIND_BY_GROUP_NAME = "User.findByGroupName";
58     public static final String QUERY_COUNT_USERS = "User.count";
59     public static final String QUERY_ALL_USERS = "User.all";
60     public static final String NAME_PARAM = "name";
61
62     @Id
63     @GeneratedValue(strategy = GenerationType.AUTO)
64     private Long primaryKey;
65
66     @Version
67     private int version;
68
69     /**
70      * User name.
71      */
72     private String name;
73
74     /**
75      * Password.
76      */
77     private String password;
78
79     /**
80      * Groups the user belongs to.
81      */
82     @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
83     private Set<Group> groups;
84
85     /**
86      * Password validator.
87      */
88     @Transient
89     private NameValidator passwordValidator;
90
91     /**
92      * Password encoder.
93      */
94     @Transient
95     private MessageDigester passwordEncoder;
96
97     /**
98      * Constructs the user.
99      * 
100      * @param aName
101      *            User name.
102      * @param aPassword
103      *            Password.
104      * @param aGroup
105      *            Group the user belongs to.
106      */
107     User(String aName, String aPassword, Group aGroup,
108         NameValidator aPasswordValidator, MessageDigester aPasswordEncoder)
109         throws UserMgtException {
110         super();
111         name = aName;
112         aPasswordValidator.validate(aPassword);
113         password = aPasswordEncoder.hash(aPassword);
114         groups = new TreeSet<Group>();
115         groups.add(aGroup);
116         passwordValidator = aPasswordValidator;
117         passwordEncoder = aPasswordEncoder;
118     }
119
120     /**
121      * Creates a new User object.
122      * 
123      */
124     public User(User aUser) {
125         primaryKey  = aUser.primaryKey;
126         version = aUser.version;
127         name = aUser.name;
128         password = aUser.password;
129         groups = new TreeSet<Group>();
130
131         for (Group group : aUser.groups) {
132             groups.add(new Group(group));
133         }
134
135         passwordValidator = aUser.passwordValidator;
136         passwordEncoder = aUser.passwordEncoder;
137     }
138
139     /**
140      * Creates a new User object.
141      */
142     User() {
143         super();
144         name = null;
145         password = null;
146         groups = null;
147         passwordValidator = null;
148         passwordEncoder = null;
149     }
150
151     /**
152      * Sets the password validator.
153      * 
154      * @param aPasswordValidator
155      *            Validator.
156      */
157     public void setPasswordValidator(NameValidator aPasswordValidator) {
158         passwordValidator = aPasswordValidator;
159     }
160
161     /**
162      * Sets the password encoder.
163      * 
164      * @param aPasswordEncoder
165      *            Encoder.
166      */
167     public void setPasswordEncoder(MessageDigester aPasswordEncoder) {
168         passwordEncoder = aPasswordEncoder;
169     }
170
171     /**
172      * 
173      * @return Returns the password.
174      */
175     String getPassword() {
176         return password;
177     }
178
179     /**
180      * Checks the password.
181      * 
182      * @param aPassword
183      *            Password to check.
184      * 
185      * @throws UserMgtException
186      *             In case the password is incorrect.
187      */
188     public void checkPassword(String aPassword) throws UserMgtException {
189         String encoded = passwordEncoder.hash(aPassword);
190
191         if (!password.equals(encoded)) {
192             throw new UserMgtException(Reason.INVALID_PASSWORD, this);
193         }
194     }
195
196     /**
197      * Changes the password.
198      * 
199      * @param aOldPassword
200      *            Old password.
201      * @param aNewPassword
202      *            New password.
203      * 
204      * @throws UserMgtException
205      *             In case the old password is incorrect.
206      */
207     public void changePassword(String aOldPassword, String aNewPassword)
208         throws UserMgtException {
209         checkPassword(aOldPassword);
210         passwordValidator.validate(aNewPassword);
211         setPassword(aNewPassword);
212     }
213
214     /**
215      * 
216      * @param aPassword
217      *            The password to set.
218      * 
219      */
220     public void setPassword(String aPassword) throws UserMgtException {
221         passwordValidator.validate(aPassword);
222         password = passwordEncoder.hash(aPassword);
223     }
224
225     /**
226      * For OR mapping.
227      * 
228      * @return Password.
229      */
230     protected String getPasswordString() {
231         return password;
232     }
233
234     /**
235      * For OR mapping.
236      * 
237      * @param aPassword
238      *            Password.
239      */
240     protected void setPasswordString(String aPassword) {
241         password = aPassword;
242     }
243
244     /**
245      * 
246      * @return Returns the _user.
247      */
248     public String getName() {
249         return name;
250     }
251
252     /**
253      * 
254      * @param aName
255      *            The username to set.
256      */
257     void setName(String aName) {
258         name = aName;
259     }
260
261     /**
262      * Gets the groups the user belongs to.
263      * 
264      * @return Groups.
265      */
266     public Set<Group> getGroups() {
267         Set<Group> result = new TreeSet<Group>();
268         result.addAll(groups);
269
270         return result;
271     }
272
273     /**
274      * Checks whether the user belongs to the given group.
275      * 
276      * @param aGroup
277      *            Group.
278      * 
279      * @return True if the user belongs to the group.
280      */
281     public boolean isInGroup(Group aGroup) {
282         return groups.contains(aGroup);
283     }
284
285     /**
286      * Checks whether the user belongs to the given group.
287      * 
288      * @param aGroup
289      *            Group.
290      * 
291      * @return True if the user belongs to the group.
292      */
293     public boolean isInGroup(String aGroup) {
294         return groups.contains(new Group(aGroup));
295     }
296
297     /**
298      * Gets the group set. For OR mapping.
299      * 
300      * @return set of groups.
301      */
302     Set<Group> getGroupSet() {
303         return groups;
304     }
305
306     /**
307      * Sets the groups the user belongs to, for OR mapping.
308      * 
309      * @param aGroups
310      *            Groups.
311      */
312     void setGroupSet(Set<Group> aGroups) {
313         groups = aGroups;
314     }
315
316     /**
317      * Adds the user to a group.
318      * 
319      * @param aGroup
320      *            Group to add the user to.
321      * 
322      * @throws UserMgtException
323      *             In case the user already belongs to the group.
324      */
325     void addGroup(Group aGroup) throws UserMgtException {
326         if (groups.contains(aGroup)) {
327             throw new UserMgtException(Reason.USER_ALREADY_IN_GROUP, aGroup);
328         }
329
330         groups.add(aGroup);
331     }
332
333     /**
334      * Removes the user from a group.
335      * 
336      * @param aGroup
337      *            Group.
338      * 
339      * @throws UserMgtException
340      *             In case the user does not belong to the group.
341      */
342     void removeGroup(Group aGroup) throws UserMgtException {
343         if (!groups.contains(aGroup)) {
344             throw new UserMgtException(Reason.USER_NOT_IN_GROUP, this, aGroup);
345         }
346
347         if (groups.size() == 1) {
348             throw new UserMgtException(Reason.USER_MUST_BE_IN_A_GROUP, this,
349                 aGroup);
350         }
351
352         groups.remove(aGroup);
353     }
354
355     /*
356      * (non-Javadoc)
357      * 
358      * @see java.lang.Object#equals(java.lang.Object)
359      */
360     @Override
361     public boolean equals(Object aUser) {
362         if (!(aUser instanceof User)) {
363             return false;
364         }
365
366         User user = (User) aUser;
367
368         return name.equals(user.name);
369     }
370
371     /*
372      * (non-Javadoc)
373      * 
374      * @see java.lang.Object#hashCode()
375      */
376     @Override
377     public int hashCode() {
378         return name.hashCode();
379     }
380
381     /*
382      * (non-Javadoc)
383      * 
384      * @see java.lang.Object#toString()
385      */
386     @Override
387     public String toString() {
388         String result = "User(name=" + name + ", password=" + password;
389
390         for (Group group : groups) {
391             result += (", group=" + group);
392         }
393
394         return result + ")";
395     }
396
397     /*
398      * (non-Javadoc)
399      * 
400      * @see java.lang.Comparable#compareTo(T)
401      */
402     public int compareTo(Object aUser) {
403         return name.compareTo(((User) aUser).name);
404     }
405
406     public Long getPrimaryKey() {
407         return primaryKey;
408     }
409 }