Package org.jboss.seam.wiki.core.action

Source Code of org.jboss.seam.wiki.core.action.UserHome

/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.wiki.core.action;

import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.faces.Renderer;
import org.jboss.seam.framework.EntityHome;
import org.jboss.seam.international.StatusMessages;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.AuthorizationException;
import org.jboss.seam.security.Identity;
import org.jboss.seam.wiki.core.action.prefs.UserManagementPreferences;
import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
import org.jboss.seam.wiki.core.dao.BlacklistDAO;
import org.jboss.seam.wiki.core.dao.UserDAO;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.model.Blacklist;
import org.jboss.seam.wiki.core.model.Role;
import org.jboss.seam.wiki.core.model.User;
import org.jboss.seam.wiki.core.model.WikiComment;
import org.jboss.seam.wiki.core.model.WikiDocument;
import org.jboss.seam.wiki.core.model.WikiNode;
import org.jboss.seam.wiki.core.model.WikiUploadImage;
import org.jboss.seam.wiki.core.upload.Uploader;
import org.jboss.seam.wiki.core.exception.InvalidWikiRequestException;
import org.jboss.seam.wiki.core.wikitext.editor.WikiTextEditor;
import org.jboss.seam.wiki.preferences.PreferenceVisibility;
import org.jboss.seam.wiki.preferences.Preferences;
import org.jboss.seam.wiki.preferences.PreferenceProvider;
import org.jboss.seam.wiki.preferences.metamodel.PreferenceEntity;
import org.jboss.seam.wiki.util.Hash;
import org.jboss.seam.wiki.util.WikiUtil;

import static org.jboss.seam.international.StatusMessage.Severity.WARN;
import static org.jboss.seam.international.StatusMessage.Severity.INFO;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.context.FacesContext;

@Name("userHome")
@Scope(ScopeType.CONVERSATION)
public class UserHome extends EntityHome<User> {

   @Logger
   static Log log;
  
    // TODO: This is a performance optimization, our EM is always already joined (SMPC)
    //protected void joinTransaction() {}

    @In
    private StatusMessages statusMessages;
   
    @In(required = false)
    private String clientAddress;

    @In
    private UserDAO userDAO;
   
    @In
    private BlacklistDAO blacklistDAO;
   
    @In
    private Hash hashUtil;

    @In(create = true)
    private Renderer renderer;

    @In("#{preferences.get('UserManagement')}")
    UserManagementPreferences prefs;

    private String oldUsername;
    private String password;
    private String passwordControl;
    private List<Role> roles;
    private org.jboss.seam.wiki.core.model.Role defaultRole;
    private Uploader uploader;
    private Long createdWikiNodeCount;
    private String requestedUsername;
    private WikiTextEditor bioTextEditor;
    private WikiTextEditor signatureTextEditor;

    public Uploader getUploader() {
        return uploader;
    }

    public void setUploader(Uploader uploader) {
        this.uploader = uploader;
    }

    public Long getUserId() {
        return (Long)getId();
    }

    public void setUserId(Long userId) {
        setId(userId);
    }

    public String getRequestedUsername() {
        return requestedUsername;
    }

    public void setRequestedUsername(String requestedUsername) {
        getLog().debug("requested user name: " + requestedUsername);
        this.requestedUsername = requestedUsername;
    }

    public void init() {
        if (isManaged()) {
            if (!Identity.instance().hasPermission("User", "edit", getInstance()) ) {
                throw new AuthorizationException("You don't have permission for this operation");
            }
            if (roles == null) roles = getInstance().getRoles();
            if (oldUsername == null) oldUsername = getInstance().getUsername();

            createdWikiNodeCount = userDAO.countNodesCreatedBy(getInstance().getId());

            uploader = (Uploader)Component.getInstance(Uploader.class);

        } else {
            if (!prefs.getEnableRegistration() &&
                !Identity.instance().hasPermission("User", "isAdmin", Component.getInstance("currentUser"))) {
                throw new AuthorizationException("User registration is disabled");
            }

            if (defaultRole == null) defaultRole = (Role)Component.getInstance("newUserDefaultRole");
        }

        if (bioTextEditor == null || signatureTextEditor == null) {
            bioTextEditor        = new WikiTextEditor("bio", 1023, false, false, 5);
            signatureTextEditor  = new WikiTextEditor("signature", 1023, false, false, 5);
            syncInstanceToWikiTextEditors();
        }

    }

    public void initEdit() {
        if (getUserId() == null) {
            throw new InvalidWikiRequestException("Missing userId request parameter");
        }
        init();
    }

    public void initDisplay() {
        if (getUserId() == null && getRequestedUsername() == null) {
            throw new InvalidWikiRequestException("Missing userId or username request parameter");
        }
    }

    @Override
    protected void initInstance() {
       if ( isIdDefined() || (getRequestedUsername() != null && getRequestedUsername().length() >0) ) {
          if ( !isTransactionMarkedRollback() ) {
             setInstance( find() );
          }
       } else {
          setInstance( createInstance() );
       }
    }

    @Override
    protected User loadInstance()  {
        if (getRequestedUsername() != null && getRequestedUsername().length() >0) {
            getLog().debug("loading user from database: " + getRequestedUsername());
            return userDAO.findUser(getRequestedUsername(), false, true);
        } else {
            return getEntityManager().find(getEntityClass(), getId());
        }
    }

    @Override
    public String persist() {

       if (clientAddress != null)
       {
          getInstance().setRegisteredAddress(clientAddress);
       }
      
       if (isBlacklisted())
       {
          return "blacklisted";
       }
      
        // Validate
        if (!isUniqueUsername() ||
            !passwordAndControlNotNull() ||
            !passwordMatchesRegex() ||
            !passwordMatchesControl()) {

            // Force re-entry
            setPassword(null);
            setPasswordControl(null);

            return null;
        }

        // Assign default role
        getInstance().getRoles().add(defaultRole);

        // Set password hash
        getInstance().setPasswordHash(hashUtil.hash(getPassword()));

        if (Identity.instance().hasPermission("User", "isAdmin", Component.getInstance("currentUser"))) {
            // Current user is admin and creating a new account, the new account is active automatically
            getInstance().setActivated(true);
            String outcome = super.persist();
            if (outcome != null) {
                org.jboss.seam.core.Events.instance().raiseEvent("User.persisted", getInstance());
            }
            return outcome;
        } else {

            // Set activation code (unique user in time)
            String seed = getInstance().getUsername() + System.currentTimeMillis() + prefs.getActivationCodeSalt();
            getInstance().setActivationCode( ((Hash)Component.getInstance(Hash.class)).hash(seed) );
            getLog().debug("setting activation code of newly registered user: " + getInstance().getActivationCode());

            String outcome = super.persist();
            if (outcome != null) {

                getLog().debug("sending activation e-mail to registered user");

                // Send confirmation email
                renderer.render("/themes/"
                        + Preferences.instance().get(WikiPreferences.class).getThemeName()
                        + "/mailtemplates/confirmationRegistration.xhtml");

                /* For debugging
                statusMessages.addFromResourceBundleOrDefault(
                    INFO,
                    getMessageKeyPrefix() + "confirmationEmailSent",
                    "Activiate account: /confirmRegistration.seam?activationCode=" + getInstance().getActivationCode());
                */

                org.jboss.seam.core.Events.instance().raiseEvent("User.registered", getInstance());
                org.jboss.seam.core.Events.instance().raiseEvent("User.persisted", getInstance());
            }
            return outcome;
        }
    }

    @Override
    @Restrict("#{s:hasPermission('User', 'edit', userHome.instance)}")
    public String update() {

        if (isManaged() && getCreatedWikiNodeCount() != null && getCreatedWikiNodeCount() > 0) {
            if (!validateWikiTextEditors()) {
                return null;
            }
            syncWikiTextEditorsToInstance();
        }

        if (uploader.hasData()) {
            uploader.uploadNewInstance();
            if (WikiUploadImage.class.isAssignableFrom(uploader.getUpload().getClass())) {
                WikiUploadImage portrait = (WikiUploadImage)uploader.getUpload();
                getLog().debug("updating portrait file data/type");
                getInstance().getProfile().setImageContentType(portrait.getContentType());
                getInstance().getProfile().setImage(
                    WikiUtil.resizeImage(portrait.getData(), portrait.getContentType(), 80) // TODO: Make size configurable?
                );
                getInstance().getProfile().setSmallImage(
                    WikiUtil.resizeImage(portrait.getData(), portrait.getContentType(), 40) // TODO: Make size configurable?
                );

            } else {
                statusMessages.addFromResourceBundleOrDefault(
                    WARN,
                    "lacewiki.msg.userHome.WrongPortraitImageType",
                    "The file type '{0}' is not supported, the portrait was not updated.",
                    uploader.getUpload().getContentType()
                );
            }
        }
        uploader.reset();

        User adminUser = (User)Component.getInstance("adminUser");
        User guestUser = (User)Component.getInstance("guestUser");

        if ( !getInstance().getId().equals(adminUser.getId()) &&
             !getInstance().getId().equals(guestUser.getId()) &&
             roles != null && roles.size() > 0) {
            // Roles
            getInstance().setRoles(new ArrayList<Role>()); // Clear out the collection
            getInstance().getRoles().addAll(roles);
        }

        // Preferences
        if (preferenceEditor != null) {
            String editorFailed = preferenceEditor.save();
            if (editorFailed != null) 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;

            // Validate
            if (!isUniqueUsername()) return null;
        }

        if (Identity.instance().hasPermission("User", "isAdmin", Component.getInstance("currentUser"))) {
            // Current user is admin and activated an account
            if (getInstance().isActivated()) {
                getInstance().setActivationCode(null);
            }
        }

        String outcome = super.update();
        if (outcome != null) {

            org.jboss.seam.core.Events.instance().raiseEvent("User.updated", getInstance());

            User currentUser = (User)Component.getInstance("currentUser");
            if (getInstance().getId().equals(currentUser.getId())) {
                // Updated profile of currently logged-in user
                Contexts.getSessionContext().set("currentUser", 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) {
                    Identity.instance().logout();
                    return "updatedCurrentCredentials";
                }
            }
        }

        return outcome;
    }

    @Override
    @Restrict("#{s:hasPermission('User', 'delete', userHome.instance)}")
    public String remove() {

        // All nodes created by this user are reset to be created by the admin user
        userDAO.resetNodeCreatorToAdmin(getInstance());

        // Remove preferences for this user
        PreferenceProvider prefProvider = (PreferenceProvider)Component.getInstance("preferenceProvider");
        prefProvider.deleteUserPreferenceValues(getInstance());
        prefProvider.flush();

        String outcome = super.remove();
        if (outcome != null) {
            org.jboss.seam.core.Events.instance().raiseEvent("User.removed", getInstance());
        }
        return outcome;
    }
   
    @Restrict("#{s:hasPermission('User', 'delete', userHome.instance)}")
    public String nuke() {
     
       // First delete their comments
      
       DocumentHome documentHome = (DocumentHome) Component.getInstance("documentHome");             
       WikiNodeDAO wikiNodeDAO = (WikiNodeDAO) Component.getInstance("wikiNodeDAO");
             
       // Find all the content that this user has created
       List<WikiNode> userNodes = wikiNodeDAO.findWikiNodes(getInstance());
      
       Set<WikiNode> nodesToDelete = new HashSet<WikiNode>();
      
       // Build a list of all the child nodes of the user's nodes
       for (WikiNode node : userNodes)
       {
          recursiveAddChildren(wikiNodeDAO, node, nodesToDelete);
       }
      
       while (!nodesToDelete.isEmpty())
       {
          WikiNode nodeToDelete = null;
                   
          main: for (WikiNode node : nodesToDelete)
          {
             // We need to find a node without children contained in the same set (which should contain any children if they exist)
             for (WikiNode n : nodesToDelete)
             {
                if (n.getParent().equals(node)) continue main;
             }
            
             nodeToDelete = node;
             break;
          }
         
          if (nodeToDelete == null)
          {
             throw new IllegalStateException("Error while deleting child nodes - no childless node found in set.");
          }
          else
          {
             if (nodeToDelete instanceof WikiComment)
             {
                WikiComment comment = (WikiComment) nodeToDelete;
               
                documentHome.setId(getCommentDocument(comment).getId());
                CommentHome commentHome = (CommentHome) Component.getInstance("commentHome");
               
                commentHome.setId(comment.getId());
                commentHome.remove(comment.getId());            
             }
             else if (nodeToDelete instanceof WikiDocument)
             {
                documentHome.setId(nodeToDelete.getId());
                documentHome.reallyRemove();
             }
             else
             {
                log.info("Unhandled node found, could not delete: " + nodeToDelete);
             }

          }
         
          nodesToDelete.remove(nodeToDelete);         
       }      
      
       Blacklist blacklist = new Blacklist();
       blacklist.setEmail(getInstance().getEmail());
       blacklist.setIpAddress(getInstance().getRegisteredAddress());
       getEntityManager().persist(blacklist);      
      
       // Remove preferences for this user
        PreferenceProvider prefProvider = (PreferenceProvider)Component.getInstance("preferenceProvider");
        prefProvider.deleteUserPreferenceValues(getInstance());
        prefProvider.flush();

        String outcome = super.remove();
        if (outcome != null) {
            org.jboss.seam.core.Events.instance().raiseEvent("User.removed", getInstance());
        }
        return outcome;
    }   
   
    private void recursiveAddChildren(WikiNodeDAO wikiNodeDAO, WikiNode parent, Set<WikiNode> nodeSet)
    {
       if (nodeSet.contains(parent)) return;
      
       List<WikiNode> children = wikiNodeDAO.findChildren(parent, WikiNode.SortableProperty.createdOn, true, 0, 0);
       for (WikiNode child : children)
       {
          recursiveAddChildren(wikiNodeDAO, child, nodeSet);         
       }
      
       nodeSet.add(parent);
    }
   
    private WikiDocument getCommentDocument(WikiComment comment)
    {
       WikiNode parent = comment.getParent();
       while (!(parent instanceof WikiDocument))
       {
          parent = parent.getParent();
       }
       return (WikiDocument) parent;
    }

    @Restrict("#{s:hasPermission('User', 'edit', userHome.instance)}")
    public void removePortrait() {
        getInstance().getProfile().setImage(null);
        getInstance().getProfile().setImageContentType(null);

        statusMessages.addFromResourceBundleOrDefault(
            INFO,
            "lacewiki.msg.userHome.PortraitRemoved",
            "The portrait has been removed, save to make changes permanent."
        );
    }

    protected void syncInstanceToWikiTextEditors() {
        bioTextEditor.setValue(getInstance().getProfile().getBio());
        signatureTextEditor.setValue(getInstance().getProfile().getSignature());
    }

    protected void syncWikiTextEditorsToInstance() {
        getInstance().getProfile().setBio(bioTextEditor.getValue());
        getInstance().getProfile().setSignature(signatureTextEditor.getValue());
    }

    protected boolean validateWikiTextEditors() {
        bioTextEditor.validate();
        signatureTextEditor.validate();
        return bioTextEditor.isValid() && signatureTextEditor.isValid();
    }


    /* -------------------------- Messages ------------------------------ */

    @Override
    protected void createdMessage() {
        statusMessages.addFromResourceBundleOrDefault(
                INFO,
                "lacewiki.msg.User.Persist",
                "User account '{0}' has been saved.",
                getInstance().getUsername()
        );
    }

    @Override
    protected void updatedMessage() {
        statusMessages.addFromResourceBundleOrDefault(
                INFO,
                "lacewiki.msg.User.Update",
                "User account '{0}' has been updated.",
                getInstance().getUsername()
        );
    }

    @Override
    protected void deletedMessage() {
        statusMessages.addFromResourceBundleOrDefault(
                INFO,
                "lacewiki.msg.User.Delete",
                "User account '{0}' has been deleted.",
                getInstance().getUsername()
        );
    }

    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; }

    public List<Role> getRoles() { return roles; }
    @Restrict("#{s:hasPermission('User', 'editRoles', currentUser)}")
    public void setRoles(List<Role> roles) { this.roles = roles; }

    @Restrict("#{s:hasPermission('User', 'isAdmin', currentUser)}")
    public void createHomeDirectory() {

        Authenticator auth = (Authenticator)Component.getInstance(Authenticator.class);
        auth.createHomeDirectory(getInstance());

        statusMessages.addFromResourceBundleOrDefault(
            INFO,
            "lacewiki.msg.HomeDirectoryCreated",
            "New home directory has been queued, save settings to commit."
        );
    }

    // Validation rules for persist(), update(), and remove();

    public boolean passwordAndControlNotNull() {
        if (getPassword() == null || getPassword().length() == 0 ||
            getPasswordControl() == null || getPasswordControl().length() == 0) {
            statusMessages.addToControlFromResourceBundleOrDefault(
                "passwordControl",
                WARN,
                "lacewiki.msg.PasswordOrPasswordControlEmpty",
                "Please enter your password twice!"
            );
            return false;
        }
        return true;
    }

    public boolean passwordMatchesRegex() {
        Matcher matcher = Pattern.compile(prefs.getPasswordRegex()).matcher(getPassword());
        if (!matcher.find()) {
            statusMessages.addToControlFromResourceBundleOrDefault(
                "password",
                WARN,
                "lacewiki.msg.PasswordDoesntMatchPattern",
                "Password does not match the pattern: {0}",
                prefs.getPasswordRegex()
            );
            return false;
        }
        return true;
    }

    public boolean passwordMatchesControl() {
        if (password == null || passwordControl == null || !password.equals(passwordControl) ) {
            statusMessages.addToControlFromResourceBundleOrDefault(
                "passwordControl",
                WARN,
                "lacewiki.msg.PasswordControlNoMatch",
                "The passwords don't match."
            );
            return false;
        }
        return true;
    }

    public boolean isUniqueUsername() {
        User foundUser = userDAO.findUser(getInstance().getUsername(), false, false);
        if ( foundUser != null && foundUser != getInstance() ) {
            statusMessages.addToControlFromResourceBundleOrDefault(
                "username",
                WARN,
                "lacewiki.msg.UsernameExists",
                "A user with that name already exists."
            );
            return false;
        }
        return true;
    }
   
    public boolean isBlacklisted()
    {
       return blacklistDAO.isEmailBlacklisted(getInstance().getEmail()) ||
              blacklistDAO.isIpAddressBlacklisted(getInstance().getRegisteredAddress());
    }

    public void validateUsername() {
        isUniqueUsername();
    }

    public void validatePassword() {
        if (getPassword() != null && getPassword().length() > 0)
            passwordMatchesRegex();
    }

    public void validatePasswordControl() {
        passwordMatchesControl();
    }

    public long getRatingPoints() {
        return userDAO.findRatingPoints(getInstance().getId());
    }

    public Long getCreatedWikiNodeCount() {
        return createdWikiNodeCount;
    }

    public WikiTextEditor getBioTextEditor() {
        return bioTextEditor;
    }

    public WikiTextEditor getSignatureTextEditor() {
        return signatureTextEditor;
    }

    // ####################### PREFERENCES ##################################

    PreferenceEditor preferenceEditor;

    @DataModel(value = "userPreferenceEntities")
    private List<PreferenceEntity> userPreferenceEntities;

    @Factory("userPreferenceEntities")
    public void initPreferencesEditor() {
        preferenceEditor = (PreferenceEditor)Component.getInstance(PreferenceEditor.class);
        preferenceEditor.setVisibilities(new PreferenceVisibility[] {PreferenceVisibility.USER});
        preferenceEditor.setUser(getInstance());
        userPreferenceEntities = preferenceEditor.getPreferenceEntities();
        Contexts.getConversationContext().set("preferenceEditor", preferenceEditor);
    }

}
TOP

Related Classes of org.jboss.seam.wiki.core.action.UserHome

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.