[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