5e6666b7be9027520440e390c8fd6d4c9ab5d90d
[utils] / security / impl / src / main / java / org / wamblee / security / authentication / 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.security.authentication;
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.Column;
24 import javax.persistence.Entity;
25 import javax.persistence.FetchType;
26 import javax.persistence.GeneratedValue;
27 import javax.persistence.GenerationType;
28 import javax.persistence.Id;
29 import javax.persistence.JoinColumn;
30 import javax.persistence.JoinTable;
31 import javax.persistence.ManyToMany;
32 import javax.persistence.NamedQueries;
33 import javax.persistence.NamedQuery;
34 import javax.persistence.Table;
35 import javax.persistence.Transient;
36 import javax.persistence.Version;
37
38 import org.wamblee.security.authentication.UserMgtException.Reason;
39 import org.wamblee.security.encryption.MessageDigester;
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.security.authentication.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 id;
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     @JoinTable(name = "SEC_USER_GROUP", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "GROUP_ID") })
84     private Set<Group> groups;
85
86     /**
87      * Password validator.
88      */
89     @Transient
90     private NameValidator passwordValidator;
91
92     /**
93      * Password encoder.
94      */
95     @Transient
96     private MessageDigester passwordEncoder;
97
98     /**
99      * Constructs the user.
100      * 
101      * @param aName
102      *            User name.
103      * @param aPassword
104      *            Password.
105      */
106     User(String aName, String aPassword, NameValidator aPasswordValidator,
107         MessageDigester aPasswordEncoder) {
108         super();
109         name = aName;
110         aPasswordValidator.validate(aPassword);
111         password = aPasswordEncoder.hash(aPassword);
112         groups = new TreeSet<Group>();
113         passwordValidator = aPasswordValidator;
114         passwordEncoder = aPasswordEncoder;
115     }
116
117     /**
118      * Creates a new User object.
119      * 
120      */
121     public User(User aUser) {
122         id = aUser.id;
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      * @return True iff the password is correct.
183      */
184     public boolean checkPassword(String aPassword) {
185         String encoded = passwordEncoder.hash(aPassword);
186
187         return password.equals(encoded);
188     }
189
190     /**
191      * Changes the password.
192      * 
193      * @param aOldPassword
194      *            Old password.
195      * @param aNewPassword
196      *            New password.
197      * 
198      * @return True iff the password was changed successfully.
199      */
200     public boolean changePassword(String aOldPassword, String aNewPassword) {
201         if (!checkPassword(aOldPassword)) {
202             return false;
203         }
204         passwordValidator.validate(aNewPassword);
205         setPassword(aNewPassword);
206         return true;
207     }
208
209     /**
210      * 
211      * @param aPassword
212      *            The password to set.
213      * 
214      */
215     public void setPassword(String aPassword) {
216         passwordValidator.validate(aPassword);
217         password = passwordEncoder.hash(aPassword);
218     }
219
220     /**
221      * For OR mapping.
222      * 
223      * @return Password.
224      */
225     protected String getPasswordString() {
226         return password;
227     }
228
229     /**
230      * For OR mapping.
231      * 
232      * @param aPassword
233      *            Password.
234      */
235     protected void setPasswordString(String aPassword) {
236         password = aPassword;
237     }
238
239     /**
240      * 
241      * @return Returns the _user.
242      */
243     public String getName() {
244         return name;
245     }
246
247     /**
248      * 
249      * @param aName
250      *            The username to set.
251      */
252     void setName(String aName) {
253         name = aName;
254     }
255
256     /**
257      * Gets the groups the user belongs to.
258      * 
259      * @return Groups.
260      */
261     public Set<Group> getGroups() {
262         Set<Group> result = new TreeSet<Group>();
263         result.addAll(groups);
264
265         return result;
266     }
267
268     /**
269      * Checks whether the user belongs to the given group.
270      * 
271      * @param aGroup
272      *            Group.
273      * 
274      * @return True if the user belongs to the group.
275      */
276     public boolean isInGroup(Group aGroup) {
277         return groups.contains(aGroup);
278     }
279
280     /**
281      * Checks whether the user belongs to the given group.
282      * 
283      * @param aGroup
284      *            Group.
285      * 
286      * @return True if the user belongs to the group.
287      */
288     public boolean isInGroup(String aGroup) {
289         return groups.contains(new Group(aGroup));
290     }
291
292     /**
293      * Gets the group set. For OR mapping.
294      * 
295      * @return set of groups.
296      */
297     Set<Group> getGroupSet() {
298         return groups;
299     }
300
301     /**
302      * Sets the groups the user belongs to, for OR mapping.
303      * 
304      * @param aGroups
305      *            Groups.
306      */
307     void setGroupSet(Set<Group> aGroups) {
308         groups = aGroups;
309     }
310
311     /**
312      * Adds the user to a group.
313      * 
314      * @param aGroup
315      *            Group to add the user to.
316      * 
317      * @throws UserMgtException
318      *             In case the user already belongs to the group.
319      */
320     void addGroup(Group aGroup) throws UserMgtException {
321         if (groups.contains(aGroup)) {
322             throw new UserMgtException(Reason.USER_ALREADY_IN_GROUP, aGroup);
323         }
324
325         groups.add(aGroup);
326     }
327
328     /**
329      * Removes the user from a group.
330      * 
331      * @param aGroup
332      *            Group.
333      * 
334      * @throws UserMgtException
335      *             In case the user does not belong to the group.
336      */
337     void removeGroup(Group aGroup) {
338         if (!groups.contains(aGroup)) {
339             throw new UserMgtException(Reason.USER_NOT_IN_GROUP, this, aGroup);
340         }
341
342         groups.remove(aGroup);
343     }
344
345     /*
346      * (non-Javadoc)
347      * 
348      * @see java.lang.Object#equals(java.lang.Object)
349      */
350     @Override
351     public boolean equals(Object aUser) {
352         if (aUser == null) {
353             return false;
354         }
355         if (!(aUser instanceof User)) {
356             return false;
357         }
358
359         User user = (User) aUser;
360
361         return name.equals(user.name);
362     }
363
364     /*
365      * (non-Javadoc)
366      * 
367      * @see java.lang.Object#hashCode()
368      */
369     @Override
370     public int hashCode() {
371         return name.hashCode();
372     }
373
374     /*
375      * (non-Javadoc)
376      * 
377      * @see java.lang.Object#toString()
378      */
379     @Override
380     public String toString() {
381         String result = "User(name=" + name + ", password=" + password;
382
383         for (Group group : groups) {
384             result += (", group=" + group);
385         }
386
387         return result + ")";
388     }
389
390     /*
391      * (non-Javadoc)
392      * 
393      * @see java.lang.Comparable#compareTo(T)
394      */
395     public int compareTo(Object aUser) {
396         return name.compareTo(((User) aUser).name);
397     }
398
399     public Long getPrimaryKey() {
400         return id;
401     }
402 }