2 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.domain;
21 import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22 import gr.ebs.gss.server.domain.dto.UserDTO;
24 import java.io.Serializable;
25 import java.security.SecureRandom;
26 import java.util.Calendar;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.Random;
32 import javax.persistence.CascadeType;
33 import javax.persistence.Column;
34 import javax.persistence.Embedded;
35 import javax.persistence.Entity;
36 import javax.persistence.FetchType;
37 import javax.persistence.GeneratedValue;
38 import javax.persistence.Id;
39 import javax.persistence.ManyToMany;
40 import javax.persistence.ManyToOne;
41 import javax.persistence.OneToMany;
42 import javax.persistence.OrderBy;
43 import javax.persistence.Table;
44 import javax.persistence.Temporal;
45 import javax.persistence.TemporalType;
46 import javax.persistence.Version;
48 import org.hibernate.annotations.Cache;
49 import org.hibernate.annotations.CacheConcurrencyStrategy;
52 * The class that holds information about a particular user of the system.
57 @Table(name = "GSS_User")
58 @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
59 public class User implements Serializable {
62 * Length of generated random password.
64 private static final int PASSWORD_LENGTH = 15;
67 * These characters will be used to generate random password.
69 private static final String allowedPasswordCharacters =
70 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
73 * The authentication token size in bytes.
75 private static final int TOKEN_SIZE = 40;
78 * The persistence ID of the object.
85 * Version field for optimistic locking.
87 @SuppressWarnings("unused")
92 * The audit information.
95 private AuditInfo auditInfo;
98 * The first name of the user.
100 private String firstname;
103 * The last name of the user.
105 private String lastname;
108 * The full name of the user.
113 * The username of the user.
115 @Column(unique = true)
116 private String username;
119 * The e-mail address of the user.
121 private String email;
124 * A unique ID provided by the Shibboleth IdP.
126 @SuppressWarnings("unused")
127 private String identityProviderId;
132 @SuppressWarnings("unused")
133 private String identityProvider;
136 * The list of groups that have been specified by this user.
138 @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
140 private List<Group> groupsSpecified;
143 * The set of groups of which this user is member.
145 @ManyToMany(fetch = FetchType.LAZY, mappedBy = "members")
146 private Set<Group> groupsMember;
149 * The list of all tags this user has specified on all files.
151 @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
153 private List<FileTag> fileTags;
156 * The user class to which this user belongs.
159 private UserClass userClass;
162 * The authentication token issued for this user.
164 private byte[] authToken;
167 * The time that the user's issued authentication token
170 @Temporal(TemporalType.TIMESTAMP)
171 private Date authTokenExpiryDate;
174 * The active nonce issued for logging in this user, in
177 private String nonce;
180 * The active nonce expiry date.
182 private Date nonceExpiryDate;
185 * Flag that denotes whether the user has accepted the terms and
186 * conditions of the service.
187 * XXX: the columnDefinition is postgres specific, if deployment
188 * database is changed this shall be changed too
190 @Column(columnDefinition=" boolean DEFAULT false")
191 private boolean acceptedPolicy;
194 * A flag that denotes whether the user is active or not. Users may be
195 * administratively forbidden to use the service by setting this flag to
198 @Column(columnDefinition=" boolean DEFAULT true")
199 private boolean active;
202 * Password for WebDAV
204 private String webDAVPassword;
207 * The HTTP_SHIB_HOMEORGANIZATION schiboleth attribute that is not used to determine the AUTH users
209 private String homeOrganization;
212 * Retrieve the firstname.
214 * @return the firstname
216 public String getFirstname() {
221 * Modify the firstname.
223 * @param newFirstname the firstname to set
225 public void setFirstname(final String newFirstname) {
226 firstname = newFirstname;
230 * Retrieve the lastname.
232 * @return the lastname
234 public String getLastname() {
239 * Modify the lastname.
241 * @param newLastname the lastname to set
243 public void setLastname(final String newLastname) {
244 lastname = newLastname;
252 public String getName() {
259 * @param newName the name to set
261 public void setName(final String newName) {
266 * Retrieve the email.
270 public String getEmail() {
277 * @param newEmail the email to set
279 public void setEmail(final String newEmail) {
288 public Long getId() {
293 * Retrieve the groups specified by this user.
297 public List<Group> getGroupsSpecified() {
298 return groupsSpecified;
302 * Modify the groups specified by this user.
304 * @param newGroupsSpecified the groups to set
306 public void setGroupsSpecified(final List<Group> newGroupsSpecified) {
307 groupsSpecified = newGroupsSpecified;
311 * Retrieve the groups of which this user is member.
315 public Set<Group> getGroupsMember() {
320 * Modify the groups of which this user is member.
322 * @param newGroupsMember the groups to set
324 public void setGroupsMember(final Set<Group> newGroupsMember) {
325 groupsMember = newGroupsMember;
329 * Retrieve the audit info.
331 * @return the audit info
333 public AuditInfo getAuditInfo() {
338 * Modify the audit info.
340 * @param newAuditInfo the new audit info
342 public void setAuditInfo(final AuditInfo newAuditInfo) {
343 auditInfo = newAuditInfo;
347 * Retrieve the file tags.
349 * @return a list of file tags
351 public List<FileTag> getFileTags() {
356 * Replace the list of file tags.
358 * @param newFileTags the new file tags
360 public void setFileTags(final List<FileTag> newFileTags) {
361 fileTags = newFileTags;
365 * Retrieve the user class.
367 * @return the user class
369 public UserClass getUserClass() {
374 * Modify the user class.
376 * @param newUserClass the new user class
378 public void setUserClass(final UserClass newUserClass) {
379 userClass = newUserClass;
383 * Retrieve the username.
385 * @return the username
387 public String getUsername() {
392 * Modify the username.
394 * @param aUsername the username to set
396 public void setUsername(String aUsername) {
397 username = aUsername;
401 * Retrieve the acceptedPolicy flag.
403 * @return the acceptedPolicy
405 public boolean hasAcceptedPolicy() {
406 return acceptedPolicy;
409 * Modify the acceptedPolicy flag.
411 * @param newAcceptedPolicy the acceptedPolicy to set
413 public void setAcceptedPolicy(boolean newAcceptedPolicy) {
414 acceptedPolicy = newAcceptedPolicy;
418 public String getWebDAVPassword() {
419 return webDAVPassword;
421 public void setWebDAVPassword(String aWebDAVPassword1) {
422 webDAVPassword = aWebDAVPassword1;
425 // ********************** Business Methods ********************** //
431 * Modify the identityProviderId.
433 * @param anIdentityProviderId the identityProviderId to set
435 public void setIdentityProviderId(String anIdentityProviderId) {
436 identityProviderId = anIdentityProviderId;
441 * Modify the identityProvider.
443 * @param anIdentityProvider the identityProvider to set
445 public void setIdentityProvider(String anIdentityProvider) {
446 identityProvider = anIdentityProvider;
450 * Retrieve the authentication token. If it is not valid
451 * or non-existent, this method returns null. Therefore, call
452 * sites must request a regeneration of the authentication
453 * token in both cases.
455 * @return the authToken
457 public byte[] getAuthToken() {
458 if (isAuthTokenValid())
464 * Add a tag from this user to specified file.
466 * @param file the file
467 * @param tag the tag string
469 public void addTag(final FileHeader file, final String tag) {
470 @SuppressWarnings("unused")
471 final FileTag fileTag = new FileTag(this, file, tag);
472 // Cascade should take care of saving here.
476 * Return a Data Transfer Object for this User object.
480 public UserDTO getDTO() {
481 final UserDTO u = new UserDTO();
484 u.setLastname(lastname);
485 u.setFirstname(firstname);
487 u.setUsername(username);
490 u.setUserClass(userClass.getDTOWithoutUsers());
495 * Removes a group from this user's specified groups list.
497 * @param group the group to remove
498 * @throws IllegalArgumentException if group is null
500 public void removeSpecifiedGroup(final Group group) {
502 throw new IllegalArgumentException("Can't remove a null group.");
503 getGroupsSpecified().remove(group);
504 group.setOwner(null);
510 public void createGroup(final String name2) {
511 final Group group = new Group(name2);
512 group.setOwner(this);
513 final Date now = new Date();
514 final AuditInfo ai = new AuditInfo();
515 ai.setCreatedBy(this);
516 ai.setCreationDate(now);
517 ai.setModifiedBy(this);
518 ai.setModificationDate(now);
519 group.setAuditInfo(ai);
520 groupsSpecified.add(group);
524 * Removes the specified tag from this user
528 public void removeTag(FileTag tag) {
529 fileTags.remove(tag);
534 * Creates a new authentication token and resets
537 public void generateAuthToken() {
538 SecureRandom random = new SecureRandom();
539 authToken = new byte[TOKEN_SIZE];
540 random.nextBytes(authToken);
541 Calendar cal = Calendar.getInstance();
542 // Set token time-to-live to the number of days specified in
544 cal.add(Calendar.DAY_OF_MONTH, getConfiguration().getInt("tokenTTL", 1));
545 authTokenExpiryDate = cal.getTime();
549 * Return true if the authentication token is usable, or false
550 * if a new one must be regenerated.
552 * @return true if the authentication token is valid
554 private boolean isAuthTokenValid() {
555 if (authToken == null)
557 if (authTokenExpiryDate == null)
559 if (authTokenExpiryDate.before(new Date()))
565 * Request the invalidation of the authentication token.
566 * After this method is called, a new token must be generated.
568 public void invalidateAuthToken() {
570 authTokenExpiryDate = null;
574 * Retrieve the nonce. If it is not valid or non-existent,
575 * this method returns null.
579 public String getNonce() {
586 * Return true if the nonce is usable, or false
589 * @return true if the nonce is valid
591 private boolean isNonceValid() {
594 if (nonceExpiryDate == null)
596 if (nonceExpiryDate.before(new Date()))
604 * @param aNonce the nonce to set
606 public void setNonce(String aNonce) {
611 * Modify the nonce expiry date.
613 * @param aNonceExpiryDate the nonce expiry date to set
615 public void setNonceExpiryDate(Date aNonceExpiryDate) {
616 nonceExpiryDate = aNonceExpiryDate;
619 public boolean isActive() {
623 public void setActive(boolean isActive) {
628 public boolean equals(Object o) {
629 if (this == o) return true;
630 if (!(o instanceof User)) return false;
631 User user = (User) o;
632 return user.getUsername().equals(username) && user.getName().equals(name);
636 public int hashCode() {
637 return 37 * username.hashCode() + name.hashCode();
640 public void generateWebDAVPassword() {
641 Random random = new Random();
642 StringBuilder sb = new StringBuilder();
643 int length = allowedPasswordCharacters.length();
644 for (int i=0; i<PASSWORD_LENGTH; i++) {
645 int j = random.nextInt(length);
646 sb.append(allowedPasswordCharacters.charAt(j));
648 webDAVPassword = sb.toString();
651 public String getHomeOrganization() {
652 return homeOrganization;
655 public void setHomeOrganization(String homeOrganization) {
656 this.homeOrganization = homeOrganization;