Project

General

Profile

Download (10.1 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
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.
8
*/
9

    
10
package eu.etaxonomy.cdm.model.common;
11

    
12
import java.util.Collection;
13
import java.util.HashSet;
14
import java.util.Set;
15

    
16
import javax.persistence.Column;
17
import javax.persistence.Entity;
18
import javax.persistence.FetchType;
19
import javax.persistence.ManyToMany;
20
import javax.persistence.OneToOne;
21
import javax.persistence.Table;
22
import javax.persistence.Transient;
23
import javax.validation.constraints.NotNull;
24
import javax.xml.bind.annotation.XmlAccessType;
25
import javax.xml.bind.annotation.XmlAccessorType;
26
import javax.xml.bind.annotation.XmlElement;
27
import javax.xml.bind.annotation.XmlElementWrapper;
28
import javax.xml.bind.annotation.XmlIDREF;
29
import javax.xml.bind.annotation.XmlRootElement;
30
import javax.xml.bind.annotation.XmlSchemaType;
31
import javax.xml.bind.annotation.XmlTransient;
32
import javax.xml.bind.annotation.XmlType;
33

    
34
import org.apache.commons.lang3.StringUtils;
35
import org.apache.log4j.Logger;
36
import org.hibernate.annotations.Cascade;
37
import org.hibernate.annotations.CascadeType;
38
import org.hibernate.envers.Audited;
39
import org.hibernate.envers.NotAudited;
40
import org.hibernate.search.annotations.Analyze;
41
import org.hibernate.search.annotations.Field;
42
import org.hibernate.search.annotations.IndexedEmbedded;
43
import org.springframework.security.core.Authentication;
44
import org.springframework.security.core.GrantedAuthority;
45
import org.springframework.security.core.context.SecurityContextHolder;
46
import org.springframework.security.core.userdetails.UserDetails;
47

    
48
import eu.etaxonomy.cdm.model.agent.Person;
49

    
50
@XmlAccessorType(XmlAccessType.FIELD)
51
@XmlType(name = "User", propOrder = {
52
    "username",
53
    "password",
54
    "salt",
55
    "emailAddress",
56
    "grantedAuthorities",
57
    "groups",
58
    "enabled",
59
    "accountNonExpired",
60
    "credentialsNonExpired",
61
    "accountNonLocked",
62
    "person"
63
})
64
@XmlRootElement(name = "User")
65
@Entity
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")
68
@Audited
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);
73

    
74
 // **************************** FACTORY *****************************************/
75

    
76
    public static User NewInstance(String username, String pwd){
77
        User user = new User();
78
        user.setUsername(username);
79
        user.setPassword(pwd);
80

    
81
        user.setAccountNonExpired(true);
82
        user.setAccountNonLocked(true);
83
        user.setCredentialsNonExpired(true);
84
        user.setEnabled(true);
85

    
86
        return user;
87
    }
88

    
89
    public static User NewInstance(String personTitle, String username, String pwd){
90
        User user = new User();
91
        user.setUsername(username);
92
        user.setPassword(pwd);
93

    
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);
100

    
101
        return user;
102
    }
103

    
104
//***************************** Fields *********************** /
105

    
106
    @XmlElement(name = "Username")
107
    @Column(unique = true)
108
    @Field(analyze = Analyze.NO)
109
    @NotNull
110
    protected String username;
111

    
112
    /**
113
     * a salted, MD5 encoded hash of the plain text password
114
     */
115
    @XmlElement(name = "Password")
116
    @NotAudited
117
    protected String password;
118

    
119

    
120
    /**
121
     * The salt for password hashing.
122
     * @see https://dev.e-taxonomy.eu/redmine/issues/7210
123
     * @see https://code-bude.net/2015/03/30/grundlagen-sicheres-passwort-hashing-mit-salts/
124
     */
125
    @XmlElement(name = "Salt")
126
    @NotAudited
127
    protected String salt;
128

    
129
    @XmlElement(name = "EmailAddress")
130
    @Column(unique = true)
131
    protected String emailAddress;
132

    
133
    @XmlElementWrapper(name = "GrantedAuthorities")
134
    @XmlElement(name = "GrantedAuthority", type = GrantedAuthorityImpl.class)
135
    @XmlIDREF
136
    @XmlSchemaType(name = "IDREF")
137
    @ManyToMany(fetch = FetchType.LAZY, targetEntity = GrantedAuthorityImpl.class)
138
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.REFRESH}) // see #2414 (Group updating doesn't work)
139
    @NotAudited
140
    protected Set<GrantedAuthority> grantedAuthorities = new HashSet<>();  //authorities of this user only
141

    
142
    @XmlElementWrapper(name = "Groups")
143
    @XmlElement(name = "Group")
144
    @XmlIDREF
145
    @XmlSchemaType(name = "IDREF")
146
    @ManyToMany(fetch = FetchType.LAZY)
147
        @Cascade({CascadeType.REFRESH, CascadeType.SAVE_UPDATE,CascadeType.MERGE}) // see #2414 (Group updating doesn't work)
148
    @IndexedEmbedded(depth = 1)
149
    @NotAudited
150
    protected Set<Group> groups = new HashSet<>();
151

    
152
    @XmlElement(name = "Enabled")
153
    protected boolean enabled;
154

    
155
    @XmlElement(name = "AccountNonExpired")
156
    protected boolean accountNonExpired;
157

    
158
    @XmlElement(name = "CredentialsNonExpired")
159
    protected boolean credentialsNonExpired;
160

    
161
    @XmlElement(name = "AccountNonLocked")
162
    protected boolean accountNonLocked;
163

    
164
    @XmlElement(name = "Person")
165
    @XmlIDREF
166
    @XmlSchemaType(name = "IDREF")
167
    @OneToOne(fetch = FetchType.LAZY)
168
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
169
    @IndexedEmbedded(depth = 1)
170
    protected Person person;
171

    
172
    @XmlTransient
173
    @Transient
174
    private Set<GrantedAuthority> authorities;  //authorities of this user and of all groups the user belongs to
175

    
176
//***************************** Constructor *********************** /
177

    
178
    protected User(){
179
        super();
180
    }
181

    
182
// ***************************** METHODS ******************************/
183

    
184
    /**
185
     * Initializes or refreshes the collection of authorities, See
186
     * {@link #getAuthorities()}
187
     */
188
    //FIXME made public as preliminary solution to #4053 (Transient field User.authorities not refreshed on reloading entity)
189
    public void initAuthorities() {
190
        authorities = new HashSet<>();
191
        authorities.addAll(grantedAuthorities);
192
        for(Group group : groups) {
193
            authorities.addAll(group.getGrantedAuthorities());
194
        }
195
    }
196

    
197
    /**
198
     * Implementation of {@link UserDetails#getAuthorities()}
199
     *
200
     * {@inheritDoc}
201
     *
202
     * @return returns all {@code Set<GrantedAuthority>} instances contained in
203
     *         the sets {@link #getGrantedAuthorities()} and
204
     *         {@link #getGroups()}
205
     */
206
    @Override
207
    @Transient
208
    public Collection<GrantedAuthority> getAuthorities() {
209
        if(authorities == null || authorities.size() == 0) {
210
            initAuthorities();
211
        }
212
        return authorities;
213
    }
214

    
215
    @Override
216
    public String getPassword() {
217
        return password;
218
    }
219

    
220
    @Override
221
    public String getUsername() {
222
        return username;
223
    }
224

    
225
    @Override
226
    public boolean isAccountNonExpired() {
227
        return accountNonExpired;
228
    }
229

    
230
    @Override
231
    public boolean isAccountNonLocked() {
232
        return accountNonLocked;
233
    }
234

    
235
    @Override
236
    public boolean isCredentialsNonExpired() {
237
        return credentialsNonExpired;
238
    }
239

    
240
    @Override
241
    public boolean isEnabled() {
242
        return enabled;
243
    }
244

    
245
    public String getEmailAddress() {
246
        return emailAddress;
247
    }
248

    
249
    public void setEmailAddress(String emailAddress) {
250
        this.emailAddress = emailAddress;
251
    }
252

    
253
    public Set<GrantedAuthority> getGrantedAuthorities() {
254
        return grantedAuthorities;
255
    }
256

    
257
    public void setGrantedAuthorities(Set<GrantedAuthority> grantedAuthorities) {
258
        this.grantedAuthorities = grantedAuthorities;
259
        initAuthorities();
260
    }
261

    
262
    public void setUsername(String username) {
263
        this.username = username;
264
    }
265

    
266
    public void setPassword(String password) {
267
        this.password = password;
268
    }
269

    
270
    public void setEnabled(boolean enabled) {
271
        this.enabled = enabled;
272
    }
273

    
274
    public void setAccountNonExpired(boolean accountNonExpired) {
275
        this.accountNonExpired = accountNonExpired;
276
    }
277

    
278
    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
279
        this.credentialsNonExpired = credentialsNonExpired;
280
    }
281

    
282
    public void setAccountNonLocked(boolean accountNonLocked) {
283
        this.accountNonLocked = accountNonLocked;
284
    }
285

    
286
    protected void setGroups(Set<Group> groups) {
287
        this.groups = groups;
288
        initAuthorities();
289
    }
290

    
291
    public Set<Group> getGroups() {
292
        return groups;
293
    }
294

    
295

    
296
    public Person getPerson() {
297
        return person;
298
    }
299

    
300
    public void setPerson(Person person) {
301
        this.person = person;
302
    }
303

    
304
    public static User getCurrentAuthenticatedUser() {
305
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
306
        if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
307
            return (User)authentication.getPrincipal();
308
        }
309
        return null;
310
    }
311

    
312
//*********************** CLONE ********************************************************/
313

    
314
    /**
315
     * Clones <i>this</i> User. This is a shortcut that enables to create
316
     * a new instance that differs only slightly from <i>this</i> User.
317
     * The corresponding person is cloned.
318
     *
319
     * @see eu.etaxonomy.cdm.model.common.CdmBase#clone()
320
     * @see java.lang.Object#clone()
321
     */
322
    @Override
323
    public Object clone() {
324
        try{
325
            User result = (User)super.clone();
326
            result.setPerson((Person)this.person.clone());
327
            return result;
328
        } catch (CloneNotSupportedException e){
329
            logger.warn("Object does not implement cloneable");
330
            e.printStackTrace();
331
            return null;
332
        }
333

    
334

    
335
    }
336

    
337
//************************************** toString ***************************************
338

    
339
    @Override
340
    public String toString() {
341
        if (StringUtils.isNotBlank(username)){
342
            return username;
343
        }else{
344
            return super.toString();
345
        }
346
    }
347
}
(74-74/80)