--- /dev/null
+/*
+ * Copyright 2005-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.security.authentication;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import javax.persistence.Version;
+
+import org.wamblee.security.authentication.UserMgtException.Reason;
+import org.wamblee.security.encryption.MessageDigester;
+
+/**
+ * Represents a user. The methods for managing the groups of the user have
+ * package scope. Managing the groups of the user should be done through the
+ * {@link org.wamblee.security.authentication.UserAdministration} interface.
+ */
+@Entity
+@Table(name = "SEC_USER")
+@NamedQueries( {
+ @NamedQuery(name = User.QUERY_FIND_BY_NAME, query = "select u from User u where u.name = :" +
+ User.NAME_PARAM),
+ @NamedQuery(name = User.QUERY_FIND_BY_GROUP_NAME, query = "select user from User user join user.groups grp where grp.name = :name"),
+ @NamedQuery(name = User.QUERY_COUNT_USERS, query = "select count(u) from User u"),
+ @NamedQuery(name = User.QUERY_ALL_USERS, query = "select u from User u") })
+public class User implements Serializable, Comparable {
+
+ public static final String QUERY_FIND_BY_NAME = "User.findByName";
+ public static final String QUERY_FIND_BY_GROUP_NAME = "User.findByGroupName";
+ public static final String QUERY_COUNT_USERS = "User.count";
+ public static final String QUERY_ALL_USERS = "User.all";
+ public static final String NAME_PARAM = "name";
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Version
+ private int version;
+
+ /**
+ * User name.
+ */
+ private String name;
+
+ /**
+ * Password.
+ */
+ private String password;
+
+ /**
+ * Groups the user belongs to.
+ */
+ @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
+ @JoinTable(name = "SEC_USER_GROUP", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "GROUP_ID") })
+ private Set<Group> groups;
+
+ /**
+ * Password validator.
+ */
+ @Transient
+ private NameValidator passwordValidator;
+
+ /**
+ * Password encoder.
+ */
+ @Transient
+ private MessageDigester passwordEncoder;
+
+ /**
+ * Constructs the user.
+ *
+ * @param aName
+ * User name.
+ * @param aPassword
+ * Password.
+ */
+ User(String aName, String aPassword, NameValidator aPasswordValidator,
+ MessageDigester aPasswordEncoder) {
+ super();
+ name = aName;
+ aPasswordValidator.validate(aPassword);
+ password = aPasswordEncoder.hash(aPassword);
+ groups = new TreeSet<Group>();
+ passwordValidator = aPasswordValidator;
+ passwordEncoder = aPasswordEncoder;
+ }
+
+ /**
+ * Creates a new User object.
+ *
+ */
+ public User(User aUser) {
+ id = aUser.id;
+ version = aUser.version;
+ name = aUser.name;
+ password = aUser.password;
+ groups = new TreeSet<Group>();
+
+ for (Group group : aUser.groups) {
+ groups.add(new Group(group));
+ }
+
+ passwordValidator = aUser.passwordValidator;
+ passwordEncoder = aUser.passwordEncoder;
+ }
+
+ /**
+ * Creates a new User object.
+ */
+ User() {
+ super();
+ name = null;
+ password = null;
+ groups = null;
+ passwordValidator = null;
+ passwordEncoder = null;
+ }
+
+ /**
+ * Sets the password validator.
+ *
+ * @param aPasswordValidator
+ * Validator.
+ */
+ public void setPasswordValidator(NameValidator aPasswordValidator) {
+ passwordValidator = aPasswordValidator;
+ }
+
+ /**
+ * Sets the password encoder.
+ *
+ * @param aPasswordEncoder
+ * Encoder.
+ */
+ public void setPasswordEncoder(MessageDigester aPasswordEncoder) {
+ passwordEncoder = aPasswordEncoder;
+ }
+
+ /**
+ *
+ * @return Returns the password.
+ */
+ String getPassword() {
+ return password;
+ }
+
+ /**
+ * Checks the password.
+ *
+ * @param aPassword
+ * Password to check.
+ *
+ * @return True iff the password is correct.
+ */
+ public boolean checkPassword(String aPassword) {
+ String encoded = passwordEncoder.hash(aPassword);
+
+ return password.equals(encoded);
+ }
+
+ /**
+ * Changes the password.
+ *
+ * @param aOldPassword
+ * Old password.
+ * @param aNewPassword
+ * New password.
+ *
+ * @return True iff the password was changed successfully.
+ */
+ public boolean changePassword(String aOldPassword, String aNewPassword) {
+ if (!checkPassword(aOldPassword)) {
+ return false;
+ }
+ passwordValidator.validate(aNewPassword);
+ setPassword(aNewPassword);
+ return true;
+ }
+
+ /**
+ *
+ * @param aPassword
+ * The password to set.
+ *
+ */
+ public void setPassword(String aPassword) {
+ passwordValidator.validate(aPassword);
+ password = passwordEncoder.hash(aPassword);
+ }
+
+ /**
+ * For OR mapping.
+ *
+ * @return Password.
+ */
+ protected String getPasswordString() {
+ return password;
+ }
+
+ /**
+ * For OR mapping.
+ *
+ * @param aPassword
+ * Password.
+ */
+ protected void setPasswordString(String aPassword) {
+ password = aPassword;
+ }
+
+ /**
+ *
+ * @return Returns the _user.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ *
+ * @param aName
+ * The username to set.
+ */
+ void setName(String aName) {
+ name = aName;
+ }
+
+ /**
+ * Gets the groups the user belongs to.
+ *
+ * @return Groups.
+ */
+ public Set<Group> getGroups() {
+ Set<Group> result = new TreeSet<Group>();
+ result.addAll(groups);
+
+ return result;
+ }
+
+ /**
+ * Checks whether the user belongs to the given group.
+ *
+ * @param aGroup
+ * Group.
+ *
+ * @return True if the user belongs to the group.
+ */
+ public boolean isInGroup(Group aGroup) {
+ return groups.contains(aGroup);
+ }
+
+ /**
+ * Checks whether the user belongs to the given group.
+ *
+ * @param aGroup
+ * Group.
+ *
+ * @return True if the user belongs to the group.
+ */
+ public boolean isInGroup(String aGroup) {
+ return groups.contains(new Group(aGroup));
+ }
+
+ /**
+ * Gets the group set. For OR mapping.
+ *
+ * @return set of groups.
+ */
+ Set<Group> getGroupSet() {
+ return groups;
+ }
+
+ /**
+ * Sets the groups the user belongs to, for OR mapping.
+ *
+ * @param aGroups
+ * Groups.
+ */
+ void setGroupSet(Set<Group> aGroups) {
+ groups = aGroups;
+ }
+
+ /**
+ * Adds the user to a group.
+ *
+ * @param aGroup
+ * Group to add the user to.
+ *
+ * @throws UserMgtException
+ * In case the user already belongs to the group.
+ */
+ void addGroup(Group aGroup) throws UserMgtException {
+ if (groups.contains(aGroup)) {
+ throw new UserMgtException(Reason.USER_ALREADY_IN_GROUP, aGroup);
+ }
+
+ groups.add(aGroup);
+ }
+
+ /**
+ * Removes the user from a group.
+ *
+ * @param aGroup
+ * Group.
+ *
+ * @throws UserMgtException
+ * In case the user does not belong to the group.
+ */
+ void removeGroup(Group aGroup) {
+ if (!groups.contains(aGroup)) {
+ throw new UserMgtException(Reason.USER_NOT_IN_GROUP, this, aGroup);
+ }
+
+ groups.remove(aGroup);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object aUser) {
+ if (aUser == null) {
+ return false;
+ }
+ if (!(aUser instanceof User)) {
+ return false;
+ }
+
+ User user = (User) aUser;
+
+ return name.equals(user.name);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ String result = "User(name=" + name + ", password=" + password;
+
+ for (Group group : groups) {
+ result += (", group=" + group);
+ }
+
+ return result + ")";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(T)
+ */
+ public int compareTo(Object aUser) {
+ return name.compareTo(((User) aUser).name);
+ }
+
+ public Long getPrimaryKey() {
+ return id;
+ }
+}