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