-/**\r
-* Copyright (C) 2007 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*\r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-\r
-package eu.etaxonomy.cdm.model.common;\r
-\r
-import java.util.Collection;\r
-import java.util.HashSet;\r
-import java.util.Set;\r
-\r
-import javax.persistence.Entity;\r
-import javax.persistence.FetchType;\r
-import javax.persistence.ManyToMany;\r
-import javax.persistence.OneToOne;\r
-import javax.persistence.Table;\r
-import javax.persistence.Transient;\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlElementWrapper;\r
-import javax.xml.bind.annotation.XmlIDREF;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-import javax.xml.bind.annotation.XmlSchemaType;\r
-import javax.xml.bind.annotation.XmlTransient;\r
-import javax.xml.bind.annotation.XmlType;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.hibernate.annotations.Cascade;\r
-import org.hibernate.annotations.CascadeType;\r
-import org.hibernate.annotations.NaturalId;\r
-import org.hibernate.envers.Audited;\r
-import org.hibernate.envers.NotAudited;\r
-import org.hibernate.search.annotations.Analyze;\r
-import org.hibernate.search.annotations.Field;\r
-import org.hibernate.search.annotations.Indexed;\r
-import org.hibernate.search.annotations.IndexedEmbedded;\r
-import org.springframework.security.core.GrantedAuthority;\r
-import org.springframework.security.core.userdetails.UserDetails;\r
-\r
-import eu.etaxonomy.cdm.model.agent.Person;\r
-\r
-@XmlAccessorType(XmlAccessType.FIELD)\r
-@XmlType(name = "User", propOrder = {\r
- "username",\r
- "password",\r
- "emailAddress",\r
- "grantedAuthorities",\r
- "groups",\r
- "enabled",\r
- "accountNonExpired",\r
- "credentialsNonExpired",\r
- "accountNonLocked",\r
- "person"\r
-})\r
-@XmlRootElement(name = "User")\r
-@Entity\r
-@Indexed(index = "eu.etaxonomy.cdm.model.common.User")\r
-@Audited\r
-@Table(name = "UserAccount")\r
-public class User extends CdmBase implements UserDetails {\r
- private static final long serialVersionUID = 6582191171369439163L;\r
- private static final Logger logger = Logger.getLogger(User.class);\r
-\r
- protected User(){\r
- super();\r
- }\r
-\r
- public static User NewInstance(String username, String pwd){\r
- User user = new User();\r
- user.setUsername(username);\r
- user.setPassword(pwd);\r
-\r
- user.setAccountNonExpired(true);\r
- user.setAccountNonLocked(true);\r
- user.setCredentialsNonExpired(true);\r
- user.setEnabled(true);\r
-\r
- return user;\r
- }\r
-\r
- public static User NewInstance(String personTitle, String username, String pwd){\r
- User user = new User();\r
- user.setUsername(username);\r
- user.setPassword(pwd);\r
-\r
- user.setAccountNonExpired(true);\r
- user.setAccountNonLocked(true);\r
- user.setCredentialsNonExpired(true);\r
- user.setEnabled(true);\r
- Person userPerson = Person.NewTitledInstance(personTitle);\r
- user.setPerson(userPerson);\r
-\r
- return user;\r
- }\r
-\r
- @XmlElement(name = "Username")\r
- @NaturalId\r
- @Field(analyze = Analyze.NO)\r
- protected String username;\r
-\r
- /**\r
- * a salted, MD5 encoded hash of the plaintext password\r
- */\r
- @XmlElement(name = "Password")\r
- @NotAudited\r
- protected String password;\r
-\r
- @XmlElement(name = "EmailAddress")\r
- protected String emailAddress;\r
-\r
- @XmlElementWrapper(name = "GrantedAuthorities")\r
- @XmlElement(name = "GrantedAuthority", type = GrantedAuthorityImpl.class)\r
- @XmlIDREF\r
- @XmlSchemaType(name = "IDREF")\r
- @ManyToMany(fetch = FetchType.LAZY, targetEntity = GrantedAuthorityImpl.class)\r
- @Cascade(CascadeType.SAVE_UPDATE)\r
- @NotAudited\r
- protected Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>(); //authorities of this user only\r
-\r
- @XmlElementWrapper(name = "Groups")\r
- @XmlElement(name = "Group")\r
- @XmlIDREF\r
- @XmlSchemaType(name = "IDREF")\r
- @ManyToMany(fetch = FetchType.LAZY)\r
- @IndexedEmbedded(depth = 1)\r
- @NotAudited\r
- protected Set<Group> groups = new HashSet<Group>();\r
-\r
- @XmlElement(name = "Enabled")\r
- protected boolean enabled;\r
-\r
- @XmlElement(name = "AccountNonExpired")\r
- protected boolean accountNonExpired;\r
-\r
- @XmlElement(name = "CredentialsNonExpired")\r
- protected boolean credentialsNonExpired;\r
-\r
- @XmlElement(name = "AccountNonLocked")\r
- protected boolean accountNonLocked;\r
-\r
- @XmlElement(name = "Person")\r
- @XmlIDREF\r
- @XmlSchemaType(name = "IDREF")\r
- @OneToOne(fetch = FetchType.LAZY)\r
- @Cascade({CascadeType.SAVE_UPDATE})\r
- @IndexedEmbedded(depth = 1)\r
- protected Person person;\r
-\r
- @XmlTransient\r
- @Transient\r
- private Set<GrantedAuthority> authorities; //authorities of this user and of all groups the user belongs to\r
-\r
- private void initAuthorities() {\r
- authorities = new HashSet<GrantedAuthority>();\r
- authorities.addAll(grantedAuthorities);\r
- for(Group group : groups) {\r
- authorities.addAll(group.getGrantedAuthorities());\r
- }\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- *\r
- * @return returns a {@code Set<GrantedAuthority>} as Collection\r
- */\r
- @Override\r
- @Transient\r
- public Collection<GrantedAuthority> getAuthorities() {\r
- if(authorities == null || authorities.size() == 0) {\r
- initAuthorities();\r
- }\r
- return authorities;\r
- }\r
-\r
- @Override\r
- public String getPassword() {\r
- return password;\r
- }\r
-\r
- @Override\r
- public String getUsername() {\r
- return username;\r
- }\r
-\r
- @Override\r
- public boolean isAccountNonExpired() {\r
- return accountNonExpired;\r
- }\r
-\r
- @Override\r
- public boolean isAccountNonLocked() {\r
- return accountNonLocked;\r
- }\r
-\r
- @Override\r
- public boolean isCredentialsNonExpired() {\r
- return credentialsNonExpired;\r
- }\r
-\r
- @Override\r
- public boolean isEnabled() {\r
- return enabled;\r
- }\r
-\r
- public String getEmailAddress() {\r
- return emailAddress;\r
- }\r
-\r
- public void setEmailAddress(String emailAddress) {\r
- this.emailAddress = emailAddress;\r
- }\r
-\r
- public Set<GrantedAuthority> getGrantedAuthorities() {\r
- return grantedAuthorities;\r
- }\r
-\r
- public void setGrantedAuthorities(Set<GrantedAuthority> grantedAuthorities) {\r
- this.grantedAuthorities = grantedAuthorities;\r
- initAuthorities();\r
- }\r
-\r
- public void setUsername(String username) {\r
- this.username = username;\r
- }\r
-\r
- public void setPassword(String password) {\r
- this.password = password;\r
- }\r
-\r
- public void setEnabled(boolean enabled) {\r
- this.enabled = enabled;\r
- }\r
-\r
- public void setAccountNonExpired(boolean accountNonExpired) {\r
- this.accountNonExpired = accountNonExpired;\r
- }\r
-\r
- public void setCredentialsNonExpired(boolean credentialsNonExpired) {\r
- this.credentialsNonExpired = credentialsNonExpired;\r
- }\r
-\r
- public void setAccountNonLocked(boolean accountNonLocked) {\r
- this.accountNonLocked = accountNonLocked;\r
- }\r
-\r
- protected void setGroups(Set<Group> groups) {\r
- this.groups = groups;\r
- initAuthorities();\r
- }\r
-\r
- public Set<Group> getGroups() {\r
- return groups;\r
- }\r
-\r
-\r
- public Person getPerson() {\r
- return person;\r
- }\r
-\r
- public void setPerson(Person person) {\r
- this.person = person;\r
- }\r
-\r
-//*********************** CLONE ********************************************************/\r
-\r
- /**\r
- * Clones <i>this</i> User. This is a shortcut that enables to create\r
- * a new instance that differs only slightly from <i>this</i> User.\r
- * The corresponding person is cloned.\r
- *\r
- * @see eu.etaxonomy.cdm.model.common.CdmBase#clone()\r
- * @see java.lang.Object#clone()\r
- */\r
- @Override\r
- public Object clone() {\r
- try{\r
- User result = (User)super.clone();\r
- result.setPerson((Person)this.person.clone());\r
- return result;\r
- } catch (CloneNotSupportedException e){\r
- logger.warn("Object does not implement cloneable");\r
- e.printStackTrace();\r
- return null;\r
- }\r
-\r
-\r
- }\r
-}\r
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.cdm.model.common;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import javax.validation.constraints.NotNull;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.log4j.Logger;
+import org.hibernate.annotations.Cascade;
+import org.hibernate.annotations.CascadeType;
+import org.hibernate.envers.Audited;
+import org.hibernate.envers.NotAudited;
+import org.hibernate.search.annotations.Analyze;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.IndexedEmbedded;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import eu.etaxonomy.cdm.model.agent.Person;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "User", propOrder = {
+ "username",
+ "password",
+ "emailAddress",
+ "grantedAuthorities",
+ "groups",
+ "enabled",
+ "accountNonExpired",
+ "credentialsNonExpired",
+ "accountNonLocked",
+ "person"
+})
+@XmlRootElement(name = "User")
+@Entity
+//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
+//@Indexed(index = "eu.etaxonomy.cdm.model.common.User")
+@Audited
+@Table(name = "UserAccount")
+public class User extends CdmBase implements UserDetails {
+ private static final long serialVersionUID = 6582191171369439163L;
+ private static final Logger logger = Logger.getLogger(User.class);
+
+ // **************************** FACTORY *****************************************/
+
+ public static User NewInstance(String username, String pwd){
+ User user = new User();
+ user.setUsername(username);
+ user.setPassword(pwd);
+
+ user.setAccountNonExpired(true);
+ user.setAccountNonLocked(true);
+ user.setCredentialsNonExpired(true);
+ user.setEnabled(true);
+
+ return user;
+ }
+
+ public static User NewInstance(String personTitle, String username, String pwd){
+ User user = new User();
+ user.setUsername(username);
+ user.setPassword(pwd);
+
+ user.setAccountNonExpired(true);
+ user.setAccountNonLocked(true);
+ user.setCredentialsNonExpired(true);
+ user.setEnabled(true);
+ Person userPerson = Person.NewTitledInstance(personTitle);
+ user.setPerson(userPerson);
+
+ return user;
+ }
+
+//***************************** Fields *********************** /
+
+ @XmlElement(name = "Username")
+ @Column(unique = true)
+ @Field(analyze = Analyze.NO)
+ @NotNull
+ protected String username;
+
+ /**
+ * a salted, MD5 encoded hash of the plaintext password
+ */
+ @XmlElement(name = "Password")
+ @NotAudited
+ protected String password;
+
+ @XmlElement(name = "EmailAddress")
+ protected String emailAddress;
+
+ @XmlElementWrapper(name = "GrantedAuthorities")
+ @XmlElement(name = "GrantedAuthority", type = GrantedAuthorityImpl.class)
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ @ManyToMany(fetch = FetchType.LAZY, targetEntity = GrantedAuthorityImpl.class)
+ //preliminary #5369
+ @JoinTable(joinColumns = @JoinColumn( name="UserAccount_id"))
+ @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.REFRESH}) // see #2414 (Group updating doesn't work)
+ @NotAudited
+ protected Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>(); //authorities of this user only
+
+ @XmlElementWrapper(name = "Groups")
+ @XmlElement(name = "Group")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ @ManyToMany(fetch = FetchType.LAZY)
+ @Cascade({CascadeType.REFRESH, CascadeType.SAVE_UPDATE,CascadeType.MERGE}) // see #2414 (Group updating doesn't work)
+ @IndexedEmbedded(depth = 1)
+ @NotAudited
+ protected Set<Group> groups = new HashSet<Group>();
+
+ @XmlElement(name = "Enabled")
+ protected boolean enabled;
+
+ @XmlElement(name = "AccountNonExpired")
+ protected boolean accountNonExpired;
+
+ @XmlElement(name = "CredentialsNonExpired")
+ protected boolean credentialsNonExpired;
+
+ @XmlElement(name = "AccountNonLocked")
+ protected boolean accountNonLocked;
+
+ @XmlElement(name = "Person")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ @OneToOne(fetch = FetchType.LAZY)
+ @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
+ @IndexedEmbedded(depth = 1)
+ protected Person person;
+
+ @XmlTransient
+ @Transient
+ private Set<GrantedAuthority> authorities; //authorities of this user and of all groups the user belongs to
+
+//***************************** Constructor *********************** /
+
+ protected User(){
+ super();
+ }
+
+// ***************************** METHODS ******************************/
+
+ /**
+ * Initializes or refreshes the collection of authorities, See
+ * {@link #getAuthorities()}
+ */
+ //FIXME made public as preliminary solution to #4053 (Transient field User.authorities not refreshed on reloading entity)
+ public void initAuthorities() {
+ authorities = new HashSet<GrantedAuthority>();
+ authorities.addAll(grantedAuthorities);
+ for(Group group : groups) {
+ authorities.addAll(group.getGrantedAuthorities());
+ }
+ }
+
+ /**
+ * Implementation of {@link UserDetails#getAuthorities()}
+ *
+ * {@inheritDoc}
+ *
+ * @return returns all {@code Set<GrantedAuthority>} instances contained in
+ * the sets {@link #getGrantedAuthorities()} and
+ * {@link #getGroups()}
+ */
+ @Override
+ @Transient
+ public Collection<GrantedAuthority> getAuthorities() {
+ if(authorities == null || authorities.size() == 0) {
+ initAuthorities();
+ }
+ return authorities;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return accountNonExpired;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return accountNonLocked;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return credentialsNonExpired;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public String getEmailAddress() {
+ return emailAddress;
+ }
+
+ public void setEmailAddress(String emailAddress) {
+ this.emailAddress = emailAddress;
+ }
+
+ public Set<GrantedAuthority> getGrantedAuthorities() {
+ return grantedAuthorities;
+ }
+
+ public void setGrantedAuthorities(Set<GrantedAuthority> grantedAuthorities) {
+ this.grantedAuthorities = grantedAuthorities;
+ initAuthorities();
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public void setAccountNonExpired(boolean accountNonExpired) {
+ this.accountNonExpired = accountNonExpired;
+ }
+
+ public void setCredentialsNonExpired(boolean credentialsNonExpired) {
+ this.credentialsNonExpired = credentialsNonExpired;
+ }
+
+ public void setAccountNonLocked(boolean accountNonLocked) {
+ this.accountNonLocked = accountNonLocked;
+ }
+
+ protected void setGroups(Set<Group> groups) {
+ this.groups = groups;
+ initAuthorities();
+ }
+
+ public Set<Group> getGroups() {
+ return groups;
+ }
+
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+
+ public static User getCurrentAuthenticatedUser() {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
+ return (User)authentication.getPrincipal();
+ }
+ return null;
+ }
+
+//*********************** CLONE ********************************************************/
+
+ /**
+ * Clones <i>this</i> User. This is a shortcut that enables to create
+ * a new instance that differs only slightly from <i>this</i> User.
+ * The corresponding person is cloned.
+ *
+ * @see eu.etaxonomy.cdm.model.common.CdmBase#clone()
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() {
+ try{
+ User result = (User)super.clone();
+ result.setPerson((Person)this.person.clone());
+ return result;
+ } catch (CloneNotSupportedException e){
+ logger.warn("Object does not implement cloneable");
+ e.printStackTrace();
+ return null;
+ }
+
+
+ }
+}