[jboss-cvs] jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/users ...
Christian Bauer
christian.bauer at jboss.com
Wed Feb 21 11:24:09 EST 2007
User: cbauer
Date: 07/02/21 11:24:09
Added: examples/wiki/src/org/jboss/seam/wiki/core/users
UserImage.java User.java Role.java
Authenticator.java UserHome.java
Log:
User registration/login and some security
JBSEAM-870
JBSEAM-871
JBSEAM-874
Revision Changes Path
1.1 date: 2007/02/21 16:24:09; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/users/UserImage.java
Index: UserImage.java
===================================================================
package org.jboss.seam.wiki.core.users;
import org.jboss.seam.annotations.Name;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Entity
@Table(name = "USER_IMAGE")
@Name("userImage")
public class UserImage implements Serializable {
@Id
@GeneratedValue
@Column(name = "USER_IMAGE_ID")
private Long id;
@Version
@Column(name = "OBJ_VERSION")
protected Integer version;
@ManyToOne
@JoinColumn(name = "USER_ID")
private User user;
@Lob
@Column(name = "IMAGE_DATA")
private byte[] data;
@Column(name = "CONTENT_TYPE")
private String contentType;
@Column(name = "CREATED_ON", nullable = false, updatable = false)
private Date createdOn = new Date();
public UserImage(User user, byte[] data, String contentType) {
this.user = user;
this.data = data;
this.contentType = contentType;
}
// Immutable properties
public Long getId() { return id; }
public Integer getVersion() { return version; }
public Date getCreatedOn() { return createdOn; }
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
public byte[] getData() { return data; }
public void setData(byte[] data) { this.data = data; }
public String getContentType() { return contentType; }
public void setContentType(String contentType) { this.contentType = contentType; }
}
1.1 date: 2007/02/21 16:24:09; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/users/User.java
Index: User.java
===================================================================
package org.jboss.seam.wiki.core.users;
import org.hibernate.validator.NotNull;
import org.hibernate.validator.Pattern;
import org.hibernate.validator.Length;
import org.hibernate.validator.Email;
import javax.persistence.*;
import java.io.Serializable;
import java.util.*;
@Entity
@Table(name = "USERS")
public class User implements Serializable {
@Id @GeneratedValue
@Column(name = "USER_ID")
private Long id = null;
@Version
@Column(name = "OBJ_VERSION")
private int version = 0;
@Column(name = "FIRSTNAME", length = 63, nullable = false)
@NotNull
@Length(min = 3, max = 63)
@Pattern(regex="[a-zA-Z]+", message="First name must only contain letters")
private String firstname;
@Column(name = "LASTNAME", length = 63, nullable = false)
@NotNull
@Length(min = 3, max = 63)
@Pattern(regex="[a-zA-Z]+", message="Last name must only contain letters")
private String lastname;
@Column(name = "USERNAME", length = 16, nullable = false, unique = true)
@NotNull
@Length(min = 3, max = 16)
@Pattern(regex="[a-zA-Z]?[a-zA-Z0-9_]+",
message="Member name must start with a letter, and only contain letters, numbers or underscores")
private String username; // Unique and immutable
@Column(name = "PASSWORDHASH", length = 255, nullable = false)
private String passwordHash;
@Column(name = "EMAIL", length = 255, nullable = false)
@NotNull @Email
private String email;
@Column(name = "ACTIVATED", nullable = false)
private boolean activated = false;
@Column(name = "ACTIVATION_CODE", length = 255, nullable = true)
private String activationCode;
@Column(name = "CREATED_ON", nullable = false, updatable = false)
private Date createdOn = new Date();
@ManyToMany
@JoinTable(
name = "USER_ROLE",
joinColumns = @JoinColumn(name = "USER_ID"),
inverseJoinColumns = @JoinColumn(name = "ROLE_ID")
)
@org.hibernate.annotations.Sort(type = org.hibernate.annotations.SortType.NATURAL)
private SortedSet<Role> roles = new TreeSet<Role>();
public User() {}
public User(String firstname, String lastname,
String username, String passwordHash, String email) {
this.firstname = firstname;
this.lastname = lastname;
this.username = username;
this.passwordHash = passwordHash;
this.email = email;
}
// Immutable properties
public Long getId() { return id; }
public Integer getVersion() { return version; }
public Date getCreatedOn() { return createdOn; }
// Mutable properties
public String getFirstname() { return firstname; }
public void setFirstname(String firstname) { this.firstname = firstname; }
public String getLastname() { return lastname; }
public void setLastname(String lastname) { this.lastname = lastname; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public boolean isActivated() { return activated; }
public void setActivated(boolean activated) { this.activated = activated; }
public String getActivationCode() { return activationCode; }
public void setActivationCode(String activationCode) { this.activationCode = activationCode; }
public SortedSet<Role> getRoles() {
return Collections.unmodifiableSortedSet(roles);
}
public void addRole(Role role) {
this.roles.add(role);
}
public void removeRole(Role role) {
this.roles.remove(role);
}
public String toString() {
return "User ('" + getId() + "'), " +
"Username: '" + getUsername() + "'";
}
}
1.1 date: 2007/02/21 16:24:09; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/users/Role.java
Index: Role.java
===================================================================
package org.jboss.seam.wiki.core.users;
import org.hibernate.validator.Length;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Entity
@Table(name = "ROLE")
public class Role implements Serializable, Comparable {
@Id
@GeneratedValue
@Column(name = "ROLE_ID")
private Long id = null;
@Version
@Column(name = "OBJ_VERSION")
private int version = 0;
@Column(name = "NAME", length = 255, nullable = false, unique = true)
private String name;
@Column(name = "DISPLAY_NAME", length = 255, nullable = false, unique = true)
@Length(min = 3, max = 40)
private String displayName;
@Column(name = "CREATED_ON", nullable = false, updatable = false)
private Date createdOn = new Date();
public Role() {}
public Role(String name, String displayName) {
this.name = name;
this.displayName = displayName;
}
// Immutable properties
public Long getId() { return id; }
public Integer getVersion() { return version; }
public Date getCreatedOn() { return createdOn; }
// Mutable properties
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }
public String toString() {
return "Role ('" + getId() + "'), " +
"Name: '" + getName() + "'";
}
public int compareTo(Object o) {
return getDisplayName().compareTo(((Role)o).getDisplayName());
}
}
1.1 date: 2007/02/21 16:24:09; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/users/Authenticator.java
Index: Authenticator.java
===================================================================
package org.jboss.seam.wiki.core.users;
import org.jboss.seam.annotations.*;
import org.jboss.seam.wiki.core.dao.UserDAO;
import org.jboss.seam.wiki.util.Hash;
import org.jboss.seam.ScopeType;
import org.jboss.seam.security.Identity;
@Name("authenticator")
public class Authenticator {
@In(create = true)
private UserDAO userDAO;
@In(create = true)
private Hash hashUtil;
@Out(required = false, scope = ScopeType.SESSION)
private User authenticatedUser;
@In
private Identity identity;
@RequestParameter
private String activationCode;
@Transactional
public boolean authenticate() {
User user = userDAO.findUser(identity.getUsername(), true);
if (user == null ||
identity.getPassword() == null ||
!user.getPasswordHash().equalsIgnoreCase(hashUtil.hash(identity.getPassword())))
return false;
authenticatedUser = user;
for (Role role : user.getRoles()) identity.addRole(role.getName());
return true;
}
@Transactional
public String activate() {
User user = userDAO.findUserWithActivationCode(activationCode);
if (user != null) {
user.setActivated(true);
user.setActivationCode(null);
return "activated";
} else {
return "notFound";
}
}
}
1.1 date: 2007/02/21 16:24:09; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/users/UserHome.java
Index: UserHome.java
===================================================================
package org.jboss.seam.wiki.core.users;
import org.jboss.seam.annotations.*;
import org.jboss.seam.core.FacesMessages;
import org.jboss.seam.core.Renderer;
import org.jboss.seam.framework.EntityHome;
import org.jboss.seam.wiki.core.dao.UserDAO;
import org.jboss.seam.wiki.core.prefs.GlobalPreferences;
import org.jboss.seam.wiki.core.node.NodeBrowser;
import org.jboss.seam.wiki.util.Hash;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import javax.faces.application.FacesMessage;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Name("userHome")
public class UserHome extends EntityHome<User> {
@RequestParameter
private Long userId;
@In(create=true)
private FacesMessages facesMessages;
@In(create = true)
private UserDAO userDAO;
@In(create = true)
private Hash hashUtil;
@In
private GlobalPreferences globalPrefs;
@In(required = false)
@Out(required = false, scope = ScopeType.SESSION)
private User authenticatedUser;
@In(create=true)
private Renderer renderer;
private Role defaultRole;
private String oldUsername;
private String password;
private String passwordControl;
@Override
public Object getId() {
if (userId == null) {
return super.getId();
} else {
return userId;
}
}
@Begin(flushMode = FlushModeType.MANUAL, join = true)
@Transactional
public void create() {
super.create();
defaultRole = userDAO.findRole(globalPrefs.getNewUserInRole());
if (defaultRole == null) throw new RuntimeException("Default role for new users not configured");
oldUsername = getInstance().getUsername();
}
public String persist() {
// Validate
if (!isUniqueUsername() ||
!passwordAndControlNotNull() ||
!passwordMatchesRegex() ||
!passwordMatchesControl()) {
// Force re-entry
setPassword(null);
setPasswordControl(null);
return null;
}
// Assign default role
getInstance().addRole(defaultRole);
// Set password hash
getInstance().setPasswordHash(hashUtil.hash(getPassword()));
// Set activation code (unique user in time)
String seed = getInstance().getUsername() + System.currentTimeMillis() + globalPrefs.getActivationCodeSalt();
getInstance().setActivationCode( ((Hash)Component.getInstance("hashUtil")).hash(seed) );
String outcome = super.persist();
if (outcome != null) {
try {
// Send confirmation email
renderer.render("/themes/" + globalPrefs.getThemeName() + "/mailtemplates/confirmationRegistration.xhtml");
// Redirect to last viewed page with message
facesMessages.addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
getMessageKeyPrefix() + "confirmationEmailSent",
"A confirmation e-mail has been sent to '" + getInstance().getEmail() + "'. " +
"Please read this e-mail to activate your account.");
((NodeBrowser) Component.getInstance(NodeBrowser.class)).redirectToLastBrowsedPageWithConversation();
} catch (Exception ex) {
facesMessages.add(FacesMessage.SEVERITY_ERROR, "Couldn't send confirmation email: " + ex.getMessage());
return "error";
}
}
return outcome;
}
public String update() {
// Validate
if (!isUniqueUsername())
return null;
boolean loginCredentialsModified = false;
// User wants to change his password
if (getPassword() != null && getPassword().length() != 0) {
if (!passwordAndControlNotNull() ||
!passwordMatchesRegex() ||
!passwordMatchesControl()) {
// Force re-entry
setPassword(null);
setPasswordControl(null);
return null;
} else {
// Set password hash
getInstance().setPasswordHash(hashUtil.hash(getPassword()));
loginCredentialsModified = true;
}
}
// User changed his username
if (!getInstance().getUsername().equals(oldUsername)) loginCredentialsModified = true;
String outcome = super.update();
if (outcome != null) {
if (getInstance().getId().equals(authenticatedUser.getId())) {
// Updated profile of currently logged-in user
authenticatedUser = getInstance();
// TODO: If identity.logout() wouldn't kill my session, I could call it here...
// And I don't have cleartext password in all cases, so I can't relogin the user automatically
if (loginCredentialsModified) {
facesMessages.addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
getMessageKeyPrefix() + "reloginRequired",
"Credentials updated, please logout and authenticate yourself with the new credentials."
);
}
}
((NodeBrowser) Component.getInstance(NodeBrowser.class)).redirectToLastBrowsedPageWithConversation();
}
return outcome;
}
public String remove() {
// Remove all role assignments
getInstance().getRoles().clear();
return super.remove();
}
protected String getCreatedMessageKey() {
return getMessageKeyPrefix() + "registrationComplete";
}
public String getCreatedMessage() {
return "Your account '" + getInstance().getUsername() + "' has been created.";
}
protected String getUpdatedMessageKey() {
return getMessageKeyPrefix() + "profileUpdated";
}
public String getUpdatedMessage() {
return "The profile '" + getInstance().getUsername() + "' has been updated.";
}
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getPasswordControl() { return passwordControl; }
public void setPasswordControl(String passwordControl) { this.passwordControl = passwordControl; }
// Validation rules for persist(), update(), and remove();
private boolean passwordAndControlNotNull() {
if (getPassword() == null || getPassword().length() == 0 ||
getPasswordControl() == null || getPasswordControl().length() == 0) {
facesMessages.addToControlFromResourceBundleOrDefault(
"password",
FacesMessage.SEVERITY_ERROR,
getMessageKeyPrefix() + "passwordOrPasswordControlEmpty",
"Please enter your password twice."
);
return false;
}
return true;
}
private boolean passwordMatchesRegex() {
Matcher matcher = Pattern.compile(globalPrefs.getPasswordRegex()).matcher(getPassword());
if (!matcher.find()) {
facesMessages.addToControlFromResourceBundleOrDefault(
"password",
FacesMessage.SEVERITY_ERROR,
getMessageKeyPrefix() + "passwordNoRegexMatch",
"Password does not match the pattern: " + globalPrefs.getPasswordRegex()
);
return false;
}
return true;
}
private boolean passwordMatchesControl() {
if (!password.equals(passwordControl) ) {
facesMessages.addToControlFromResourceBundleOrDefault(
"password",
FacesMessage.SEVERITY_ERROR,
getMessageKeyPrefix() + "passwordControlNoMatch",
"The passwords don't match."
);
return false;
}
return true;
}
@Transactional
private boolean isUniqueUsername() {
getEntityManager().joinTransaction();
User foundUser = userDAO.findUser(getInstance().getUsername(), false);
if ( foundUser != null && foundUser != getInstance()) {
facesMessages.addToControlFromResourceBundleOrDefault(
"username",
FacesMessage.SEVERITY_ERROR,
getMessageKeyPrefix() + "usernameExists",
"A user with that name already exists."
);
return false;
}
return true;
}
}
More information about the jboss-cvs-commits
mailing list