2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.model
.common
;
12 import java
.util
.Collection
;
13 import java
.util
.HashSet
;
16 import javax
.persistence
.Column
;
17 import javax
.persistence
.Entity
;
18 import javax
.persistence
.FetchType
;
19 import javax
.persistence
.JoinColumn
;
20 import javax
.persistence
.JoinTable
;
21 import javax
.persistence
.ManyToMany
;
22 import javax
.persistence
.OneToOne
;
23 import javax
.persistence
.Table
;
24 import javax
.persistence
.Transient
;
25 import javax
.validation
.constraints
.NotNull
;
26 import javax
.xml
.bind
.annotation
.XmlAccessType
;
27 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
28 import javax
.xml
.bind
.annotation
.XmlElement
;
29 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
30 import javax
.xml
.bind
.annotation
.XmlIDREF
;
31 import javax
.xml
.bind
.annotation
.XmlRootElement
;
32 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
33 import javax
.xml
.bind
.annotation
.XmlTransient
;
34 import javax
.xml
.bind
.annotation
.XmlType
;
36 import org
.apache
.log4j
.Logger
;
37 import org
.hibernate
.annotations
.Cascade
;
38 import org
.hibernate
.annotations
.CascadeType
;
39 import org
.hibernate
.envers
.Audited
;
40 import org
.hibernate
.envers
.NotAudited
;
41 import org
.hibernate
.search
.annotations
.Analyze
;
42 import org
.hibernate
.search
.annotations
.Field
;
43 import org
.hibernate
.search
.annotations
.IndexedEmbedded
;
44 import org
.springframework
.security
.core
.Authentication
;
45 import org
.springframework
.security
.core
.GrantedAuthority
;
46 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
47 import org
.springframework
.security
.core
.userdetails
.UserDetails
;
49 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
51 @XmlAccessorType(XmlAccessType
.FIELD
)
52 @XmlType(name
= "User", propOrder
= {
60 "credentialsNonExpired",
64 @XmlRootElement(name
= "User")
66 //@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
67 //@Indexed(index = "eu.etaxonomy.cdm.model.common.User")
69 @Table(name
= "UserAccount")
70 public class User
extends CdmBase
implements UserDetails
{
71 private static final long serialVersionUID
= 6582191171369439163L;
72 private static final Logger logger
= Logger
.getLogger(User
.class);
74 // **************************** FACTORY *****************************************/
76 public static User
NewInstance(String username
, String pwd
){
77 User user
= new User();
78 user
.setUsername(username
);
79 user
.setPassword(pwd
);
81 user
.setAccountNonExpired(true);
82 user
.setAccountNonLocked(true);
83 user
.setCredentialsNonExpired(true);
84 user
.setEnabled(true);
89 public static User
NewInstance(String personTitle
, String username
, String pwd
){
90 User user
= new User();
91 user
.setUsername(username
);
92 user
.setPassword(pwd
);
94 user
.setAccountNonExpired(true);
95 user
.setAccountNonLocked(true);
96 user
.setCredentialsNonExpired(true);
97 user
.setEnabled(true);
98 Person userPerson
= Person
.NewTitledInstance(personTitle
);
99 user
.setPerson(userPerson
);
104 //***************************** Fields *********************** /
106 @XmlElement(name
= "Username")
107 @Column(unique
= true)
108 @Field(analyze
= Analyze
.NO
)
110 protected String username
;
113 * a salted, MD5 encoded hash of the plaintext password
115 @XmlElement(name
= "Password")
117 protected String password
;
119 @XmlElement(name
= "EmailAddress")
120 protected String emailAddress
;
122 @XmlElementWrapper(name
= "GrantedAuthorities")
123 @XmlElement(name
= "GrantedAuthority", type
= GrantedAuthorityImpl
.class)
125 @XmlSchemaType(name
= "IDREF")
126 @ManyToMany(fetch
= FetchType
.LAZY
, targetEntity
= GrantedAuthorityImpl
.class)
128 @JoinTable(joinColumns
= @JoinColumn( name
="UserAccount_id"))
129 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
, CascadeType
.REFRESH
}) // see #2414 (Group updating doesn't work)
131 protected Set
<GrantedAuthority
> grantedAuthorities
= new HashSet
<GrantedAuthority
>(); //authorities of this user only
133 @XmlElementWrapper(name
= "Groups")
134 @XmlElement(name
= "Group")
136 @XmlSchemaType(name
= "IDREF")
137 @ManyToMany(fetch
= FetchType
.LAZY
)
138 @Cascade({CascadeType
.REFRESH
, CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
}) // see #2414 (Group updating doesn't work)
139 @IndexedEmbedded(depth
= 1)
141 protected Set
<Group
> groups
= new HashSet
<Group
>();
143 @XmlElement(name
= "Enabled")
144 protected boolean enabled
;
146 @XmlElement(name
= "AccountNonExpired")
147 protected boolean accountNonExpired
;
149 @XmlElement(name
= "CredentialsNonExpired")
150 protected boolean credentialsNonExpired
;
152 @XmlElement(name
= "AccountNonLocked")
153 protected boolean accountNonLocked
;
155 @XmlElement(name
= "Person")
157 @XmlSchemaType(name
= "IDREF")
158 @OneToOne(fetch
= FetchType
.LAZY
)
159 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
160 @IndexedEmbedded(depth
= 1)
161 protected Person person
;
165 private Set
<GrantedAuthority
> authorities
; //authorities of this user and of all groups the user belongs to
167 //***************************** Constructor *********************** /
173 // ***************************** METHODS ******************************/
176 * Initializes or refreshes the collection of authorities, See
177 * {@link #getAuthorities()}
179 //FIXME made public as preliminary solution to #4053 (Transient field User.authorities not refreshed on reloading entity)
180 public void initAuthorities() {
181 authorities
= new HashSet
<GrantedAuthority
>();
182 authorities
.addAll(grantedAuthorities
);
183 for(Group group
: groups
) {
184 authorities
.addAll(group
.getGrantedAuthorities());
189 * Implementation of {@link UserDetails#getAuthorities()}
193 * @return returns all {@code Set<GrantedAuthority>} instances contained in
194 * the sets {@link #getGrantedAuthorities()} and
195 * {@link #getGroups()}
199 public Collection
<GrantedAuthority
> getAuthorities() {
200 if(authorities
== null || authorities
.size() == 0) {
207 public String
getPassword() {
212 public String
getUsername() {
217 public boolean isAccountNonExpired() {
218 return accountNonExpired
;
222 public boolean isAccountNonLocked() {
223 return accountNonLocked
;
227 public boolean isCredentialsNonExpired() {
228 return credentialsNonExpired
;
232 public boolean isEnabled() {
236 public String
getEmailAddress() {
240 public void setEmailAddress(String emailAddress
) {
241 this.emailAddress
= emailAddress
;
244 public Set
<GrantedAuthority
> getGrantedAuthorities() {
245 return grantedAuthorities
;
248 public void setGrantedAuthorities(Set
<GrantedAuthority
> grantedAuthorities
) {
249 this.grantedAuthorities
= grantedAuthorities
;
253 public void setUsername(String username
) {
254 this.username
= username
;
257 public void setPassword(String password
) {
258 this.password
= password
;
261 public void setEnabled(boolean enabled
) {
262 this.enabled
= enabled
;
265 public void setAccountNonExpired(boolean accountNonExpired
) {
266 this.accountNonExpired
= accountNonExpired
;
269 public void setCredentialsNonExpired(boolean credentialsNonExpired
) {
270 this.credentialsNonExpired
= credentialsNonExpired
;
273 public void setAccountNonLocked(boolean accountNonLocked
) {
274 this.accountNonLocked
= accountNonLocked
;
277 protected void setGroups(Set
<Group
> groups
) {
278 this.groups
= groups
;
282 public Set
<Group
> getGroups() {
287 public Person
getPerson() {
291 public void setPerson(Person person
) {
292 this.person
= person
;
295 public static User
getCurrentAuthenticatedUser() {
296 Authentication authentication
= SecurityContextHolder
.getContext().getAuthentication();
297 if(authentication
!= null && authentication
.getPrincipal() != null && authentication
.getPrincipal() instanceof User
) {
298 return (User
)authentication
.getPrincipal();
303 //*********************** CLONE ********************************************************/
306 * Clones <i>this</i> User. This is a shortcut that enables to create
307 * a new instance that differs only slightly from <i>this</i> User.
308 * The corresponding person is cloned.
310 * @see eu.etaxonomy.cdm.model.common.CdmBase#clone()
311 * @see java.lang.Object#clone()
314 public Object
clone() {
316 User result
= (User
)super.clone();
317 result
.setPerson((Person
)this.person
.clone());
319 } catch (CloneNotSupportedException e
){
320 logger
.warn("Object does not implement cloneable");