/* * 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; /** * 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 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(); 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(); 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 getGroups() { Set result = new TreeSet(); 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 getGroupSet() { return groups; } /** * Sets the groups the user belongs to, for OR mapping. * * @param aGroups * Groups. */ void setGroupSet(Set 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; } }