001 // Copyright 2008 Thiago H. de Paula Figueiredo
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package br.com.arsmachina.authentication.entity;
016
017 import java.io.Serializable;
018 import java.util.ArrayList;
019 import java.util.Collections;
020 import java.util.HashSet;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Set;
024
025 import javax.persistence.CascadeType;
026 import javax.persistence.Column;
027 import javax.persistence.Entity;
028 import javax.persistence.GeneratedValue;
029 import javax.persistence.Id;
030 import javax.persistence.JoinColumn;
031 import javax.persistence.JoinTable;
032 import javax.persistence.ManyToMany;
033 import javax.persistence.OneToMany;
034 import javax.persistence.OrderBy;
035 import javax.persistence.Table;
036 import javax.persistence.Transient;
037
038 import org.hibernate.validator.Email;
039 import org.hibernate.validator.Length;
040 import org.hibernate.validator.NotNull;
041
042 /**
043 * Class that represents an application user. Each user can belong to any number of
044 * {@link Permission}s. When a given user belongs to a {@link Permission}, but cannot be granted
045 * some {@link Permission} in that group, this permission must be added to the list of removed
046 * permissions (<code>removedPermissions</code> property).
047 *
048 * @author Thiago H. de Paula Figueiredo
049 */
050 @Entity
051 @Table(name = "`user`")
052 final public class User implements Comparable<User>, Serializable {
053
054 private static final long serialVersionUID = 1L;
055
056 /**
057 * Minimum e-mail length.
058 */
059 public static final int MINIMUM_EMAIL_LENGTH = 3;
060
061 /**
062 * Minimum e-mail length.
063 */
064 public static final int MAXIMUM_EMAIL_LENGTH = 50;
065
066 /**
067 * Minimum login length.
068 */
069 public static final int MINIMUM_LOGIN_LENGTH = 2;
070
071 /**
072 * Maximum e-mail length.
073 */
074 public static final int MAXIMUM_LOGIN_LENGTH = 50;
075
076 /**
077 * Minimum name length.
078 */
079 public static final int MINIMUM_NAME_LENGTH = 2;
080
081 /**
082 * Maximum name length.
083 */
084 public static final int MAXIMUM_NAME_LENGTH = 50;
085
086 /**
087 * Minimum name length.
088 */
089 public static final int MINIMUM_PASSWORD_LENGTH = 6;
090
091 /**
092 * Maximum name length.
093 */
094 public static final int MAXIMUM_PASSWORD_LENGTH = 40;
095
096 private Integer id;
097
098 private String login;
099
100 private String name;
101
102 private String email;
103
104 private boolean credentialsExpired = false;
105
106 private boolean enabled = true;
107
108 private boolean expired = false;
109
110 private boolean locked = false;
111
112 private boolean loggedIn = false;
113
114 private String password;
115
116 private List<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>();
117
118 private List<Permission> removedPermissions = new ArrayList<Permission>();
119
120 private List<Role> roles = new ArrayList<Role>();
121
122 /**
123 * Adds a permission group to this user.
124 *
125 * @param permissionGroup a {@link PermissionGroup}.
126 */
127 public void add(PermissionGroup permissionGroup) {
128
129 if (permissionGroups.contains(permissionGroup) == false) {
130 permissionGroups.add(permissionGroup);
131 }
132
133 }
134
135 /**
136 * Adds a role to this user.
137 *
138 * @param role a {@link Role}.
139 */
140 public void add(Role role) {
141
142 if (roles.contains(role) == false) {
143 role.setUser(this);
144 roles.add(role);
145 }
146
147 }
148
149 /**
150 * Tells if this user has some a given role type.
151 *
152 * @param <R> a {@link Role} subclass.
153 * @param roleClass a {@link Class}.
154 * @return a <code>boolean</code>.
155 */
156 public <R extends Role> boolean hasRole(Class<R> roleClass) {
157 return getRole(roleClass) != null;
158 }
159
160 /**
161 * Adds a removed permission to this user.
162 *
163 * @param permission a {@link PermissionGroup}.
164 */
165 public void addRemovedPermission(Permission permission) {
166
167 if (removedPermissions.contains(permission) == false) {
168 removedPermissions.add(permission);
169 }
170
171 }
172
173 /**
174 * @see java.lang.Comparable#compareTo(java.lang.Object)
175 */
176 public int compareTo(User o) {
177 return getName().compareToIgnoreCase(o.getName());
178 }
179
180 /**
181 * @see java.lang.Object#equals(java.lang.Object)
182 */
183 @Override
184 public boolean equals(Object obj) {
185 if (this == obj) {
186 return true;
187 }
188 if (obj == null) {
189 return false;
190 }
191 if (getClass() != obj.getClass()) {
192 return false;
193 }
194 User other = (User) obj;
195 if (login == null) {
196 if (other.login != null) {
197 return false;
198 }
199 }
200 else if (!login.equals(other.login)) {
201 return false;
202 }
203 return true;
204 }
205
206 /**
207 * Returns the value of the <code>email</code> property.
208 *
209 * @return a {@link String}.
210 */
211 @Email
212 @Length(min = User.MINIMUM_EMAIL_LENGTH, max = User.MAXIMUM_EMAIL_LENGTH)
213 public String getEmail() {
214 return email;
215 }
216
217 /**
218 * Returns the value of the <code>id</code> property.
219 *
220 * @return a {@link Integer}.
221 */
222 @Id
223 @GeneratedValue
224 public Integer getId() {
225 return id;
226 }
227
228 /**
229 * Returns the value of the <code>login</code> property.
230 *
231 * @return a {@link String}.
232 */
233 @Column(nullable = false, unique = true)
234 @NotNull
235 @Length(min = User.MINIMUM_LOGIN_LENGTH, max = User.MAXIMUM_LOGIN_LENGTH)
236 public String getLogin() {
237 return login;
238 }
239
240 /**
241 * Returns the value of the <code>name</code> property.
242 *
243 * @return a {@link String}.
244 */
245 @Column(nullable = false)
246 @NotNull
247 @Length(min = User.MINIMUM_NAME_LENGTH, max = User.MAXIMUM_NAME_LENGTH)
248 public String getName() {
249 return name;
250 }
251
252 /**
253 * Returns the value of the <code>password</code> property.
254 *
255 * @return a {@link String}.
256 */
257 @Column(nullable = false, length = MAXIMUM_PASSWORD_LENGTH)
258 @NotNull
259 @Length(min = User.MINIMUM_PASSWORD_LENGTH, max = User.MAXIMUM_PASSWORD_LENGTH)
260 public String getPassword() {
261 return password;
262 }
263
264 /**
265 * Returns the value of the <code>permissionGroups</code> property.
266 *
267 * @return a {@link List<PermissionGroup>}.
268 */
269 @ManyToMany
270 @OrderBy("name asc")
271 @JoinTable(name = "user_permissiongroup", joinColumns = @JoinColumn(name = "user_id", nullable = false), inverseJoinColumns = @JoinColumn(name = "permissiongroup_id", nullable = false))
272 public List<PermissionGroup> getPermissionGroups() {
273 return permissionGroups;
274 }
275
276 /**
277 * Returns an unmodifiable list containing all the permissions granted to this user. It is
278 * comprised by the sum of all permissions in its permission groups, except the ones in its
279 * removed permissions list.
280 *
281 * @return a {@link List} of {@link Permission}s.
282 */
283 @Transient
284 final public List<Permission> getPermissions() {
285
286 Set<Permission> permissions = new HashSet<Permission>();
287
288 for (PermissionGroup group : getPermissionGroups()) {
289
290 for (Permission permission : group.getPermissions()) {
291 permissions.add(permission);
292 }
293
294 }
295
296 for (Permission permission : getRemovedPermissions()) {
297 permissions.remove(permission);
298 }
299
300 ArrayList<Permission> list = new ArrayList<Permission>(permissions);
301
302 Collections.sort(list);
303
304 return Collections.unmodifiableList(list);
305
306 }
307
308 /**
309 * Returns the value of the <code>removedPermissions</code> property.
310 *
311 * @return a {@link List<Permission>}.
312 */
313 @ManyToMany
314 @OrderBy("name asc")
315 @JoinTable(name = "user_removedpermission", joinColumns = @JoinColumn(name = "user_id", nullable = false), inverseJoinColumns = @JoinColumn(name = "permission_id", nullable = false))
316 public List<Permission> getRemovedPermissions() {
317 return removedPermissions;
318 }
319
320 /**
321 * Given a {@link Class} object, returns the corresponding {@link Role} instance or null if this
322 * user has no such role.
323 *
324 * @param <T> a {@link Role} subclass.
325 * @param clasz a {@link Class<T>}.
326 * @return a {@link #T}.
327 */
328 @SuppressWarnings("unchecked")
329 public final <T extends Role> T getRole(Class<T> clasz) {
330
331 T role = null;
332
333 for (Role r : getRoles()) {
334 if (r.getClass().equals(clasz)) {
335 role = (T) r;
336 break;
337 }
338 }
339
340 return role;
341
342 }
343
344 /**
345 * Returns the value of the <code>roles</code> property.
346 *
347 * @return a {@link List<Role>}.
348 */
349 @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
350 public List<Role> getRoles() {
351 return roles;
352 }
353
354 /**
355 * @see java.lang.Object#hashCode()
356 */
357 @Override
358 public int hashCode() {
359 return login != null ? login.hashCode() : super.hashCode();
360 }
361
362 /**
363 * Is this user's credentials expired?
364 *
365 * @return a {@link boolean}.
366 */
367 public boolean isCredentialsExpired() {
368 return credentialsExpired;
369 }
370
371 /**
372 * Is this user's account enabled?.
373 *
374 * @return a {@link boolean}.
375 */
376 public boolean isEnabled() {
377 return enabled;
378 }
379
380 /**
381 * Is this user's account expired?
382 *
383 * @return a {@link boolean}.
384 */
385 public boolean isExpired() {
386 return expired;
387 }
388
389 /**
390 * Is this user's account locked?
391 *
392 * @return a {@link boolean}.
393 */
394 public boolean isLocked() {
395 return locked;
396 }
397
398 /**
399 * Is this user's logged in now?
400 *
401 * @return a {@link boolean}.
402 */
403 public boolean isLoggedIn() {
404 return loggedIn;
405 }
406
407 /**
408 * Removes a role from this user.
409 *
410 * @param role a {@link Role}.
411 */
412 public void remove(Role role) {
413 permissionGroups.remove(role);
414 }
415
416 /**
417 * Removes all roles from a given type from this user.
418 *
419 * @param roleClass a {@link Class}.
420 */
421 public <T extends Role> void removeRole(Class<T> roleClass) {
422
423 for (Iterator<Role> i = roles.iterator(); i.hasNext();) {
424
425 Role role = i.next();
426
427 if (role.getClass().equals(roleClass)) {
428 i.remove();
429 }
430
431 }
432
433 }
434
435 /**
436 * Removes a permission group from this user.
437 *
438 * @param permissionGroup a {@link PermissionGroup}.
439 */
440 public void remove(PermissionGroup permissionGroup) {
441 permissionGroups.remove(permissionGroup);
442 }
443
444 /**
445 * Removes a removed permission from this user.
446 *
447 * @param permission a {@link Permission}.
448 */
449 public void removeRemovedPermission(Permission permission) {
450 removedPermissions.remove(permission);
451 }
452
453 /**
454 * Changes the value of the <code>credentialsExpired</code> property.
455 *
456 * @param credentialsExpired a {@link boolean}.
457 */
458 public void setCredentialsExpired(boolean credentialsExpired) {
459 this.credentialsExpired = credentialsExpired;
460 }
461
462 /**
463 * Changes the value of the <code>email</code> property.
464 *
465 * @param email a {@link String}.
466 */
467 public void setEmail(String email) {
468 this.email = email;
469 }
470
471 /**
472 * Changes the value of the <code>enabled</code> property.
473 *
474 * @param enabled a {@link boolean}.
475 */
476 public void setEnabled(boolean enabled) {
477 this.enabled = enabled;
478 }
479
480 /**
481 * Changes the value of the <code>expired</code> property.
482 *
483 * @param expired a {@link boolean}.
484 */
485 public void setExpired(boolean accountExpired) {
486 this.expired = accountExpired;
487 }
488
489 /**
490 * Changes the value of the <code>id</code> property.
491 *
492 * @param id a {@link Integer}.
493 */
494 public void setId(Integer id) {
495 this.id = id;
496 }
497
498 /**
499 * Changes the value of the <code>locked</code> property.
500 *
501 * @param locked a {@link boolean}.
502 */
503 public void setLocked(boolean accountLocked) {
504 this.locked = accountLocked;
505 }
506
507 /**
508 * Changes the value of the <code>loggedIn</code> property.
509 *
510 * @param loggedIn a {@link boolean}.
511 */
512 public void setLoggedIn(boolean loggedIn) {
513 this.loggedIn = loggedIn;
514 }
515
516 /**
517 * Changes the value of the <code>login</code> property.
518 *
519 * @param login a {@link String}.
520 */
521 public void setLogin(String login) {
522 this.login = login;
523 }
524
525 /**
526 * Changes the value of the <code>name</code> property.
527 *
528 * @param name a {@link String}.
529 */
530 public void setName(String name) {
531 this.name = name;
532 }
533
534 /**
535 * Changes the value of the <code>password</code> property.
536 *
537 * @param password a {@link String}.
538 */
539 public void setPassword(String password) {
540 this.password = password;
541 }
542
543 /**
544 * Changes the value of the <code>permissionGroups</code> property.
545 *
546 * @param permissionGroups a {@link List<PermissionGroup>}.
547 * @deprecated Use {@link #add(PermissionGroup)} and {@link #remove(PermissionGroup)} instead.
548 */
549 @Deprecated
550 public void setPermissionGroups(List<PermissionGroup> permissionGroups) {
551 this.permissionGroups = permissionGroups;
552 }
553
554 /**
555 * Changes the value of the <code>removedPermissions</code> property.
556 *
557 * @param removedPermissions a {@link List<Permission>}.
558 * @deprecated Use {@link #addRemovedPermission(Permission)} and
559 * {@link #removeRemovedPermisson(Permission)} instead.
560 */
561 @Deprecated
562 public void setRemovedPermissions(List<Permission> removedRoles) {
563 this.removedPermissions = removedRoles;
564 }
565
566 /**
567 * Changes the value of the <code>roles</code> property.
568 *
569 * @param roles a {@link List<Role>}.
570 * @deprecated Use {@link #add(Role)} and {@link #remove(Role)} instead.
571 */
572 @Deprecated
573 public void setRoles(List<Role> roles) {
574 this.roles = roles;
575 }
576
577 /**
578 * Returns the <code>name</code> property.
579 *
580 * @return a {@link String}.
581 */
582 @Override
583 public String toString() {
584 return getName();
585 }
586
587 }