[jboss-cvs] jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action ...

Christian Bauer christian at hibernate.org
Sun Mar 18 11:44:37 EDT 2007


  User: cbauer  
  Date: 07/03/18 11:44:37

  Modified:    examples/wiki/src/main/org/jboss/seam/wiki/core/action           
                        Authenticator.java FileHome.java DirectoryHome.java
                        NodeBrowser.java NodeHome.java UserHome.java
                        NodeHistory.java Menu.java DocumentHome.java
                        NodePermissions.java
  Added:       examples/wiki/src/main/org/jboss/seam/wiki/core/action           
                        WikiIdentity.java
  Log:
  Basic access level/role security, automatic home page for activated users
  
  Revision  Changes    Path
  1.2       +74 -6     jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Authenticator.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: Authenticator.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Authenticator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- Authenticator.java	7 Mar 2007 18:37:37 -0000	1.1
  +++ Authenticator.java	18 Mar 2007 15:44:37 -0000	1.2
  @@ -2,9 +2,15 @@
   
   import org.jboss.seam.annotations.*;
   import org.jboss.seam.wiki.core.dao.UserDAO;
  +import org.jboss.seam.wiki.core.dao.NodeDAO;
  +import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
   import org.jboss.seam.wiki.core.model.*;
  +import org.jboss.seam.wiki.core.model.Role;
  +import org.jboss.seam.wiki.core.ui.WikiUtil;
   import org.jboss.seam.wiki.util.Hash;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.Component;
  +import org.jboss.seam.contexts.Contexts;
   import org.jboss.seam.security.Identity;
   
   @Name("authenticator")
  @@ -14,10 +20,10 @@
       private UserDAO userDAO;
   
       @In
  -    private Hash hashUtil;
  +    private NodeDAO nodeDAO;
   
  -    @Out(required = false, scope = ScopeType.SESSION)
  -    private User authenticatedUser;
  +    @In
  +    private Hash hashUtil;
   
       @In
       private Identity identity;
  @@ -27,14 +33,24 @@
   
       @Transactional
       public boolean authenticate() {
  -        User user = userDAO.findUser(identity.getUsername(), true);
  +
  +        if (org.jboss.seam.wiki.core.dao.UserRoleAccessFactory.GUEST_USERNAME.equals(identity.getUsername())) return false;
  +
  +        User user = userDAO.findUser(identity.getUsername(), true, true);
           if (user == null ||
               identity.getPassword() == null ||
               !user.getPasswordHash().equalsIgnoreCase(hashUtil.hash(identity.getPassword())))
               return false;
   
  -        authenticatedUser = user;
  -        for (org.jboss.seam.wiki.core.model.Role role : user.getRoles()) identity.addRole(role.getName());
  +        // We don't use Seams Role class, wiki currently only uses numeric access levels
  +        Role bestRole = (Role)Component.getInstance("guestRole");
  +        for (Role role : user.getRoles()) {
  +            if (role.getAccessLevel() > bestRole.getAccessLevel()) bestRole = role;
  +        }
  +
  +        // Outject current user and access level
  +        Contexts.getSessionContext().set("currentUser", user);
  +        Contexts.getSessionContext().set("currentAccessLevel", bestRole.getAccessLevel());
   
           return true;
       }
  @@ -45,10 +61,62 @@
           if (user != null) {
               user.setActivated(true);
               user.setActivationCode(null);
  +
  +            // Create home directory
  +            Directory memberArea = (Directory)Component.getInstance("memberArea");
  +
  +            Directory homeDirectory = new Directory(user.getUsername());
  +            homeDirectory.setWikiname(WikiUtil.convertToWikiName(homeDirectory.getName()));
  +            homeDirectory.setAreaNumber(memberArea.getAreaNumber());
  +            homeDirectory.setCreatedBy(user);
  +            homeDirectory.setWriteAccessLevel(UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL);
  +            homeDirectory.setReadAccessLevel(UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL);
  +            memberArea.addChild(homeDirectory);
  +            user.setMemberHome(homeDirectory);
  +            nodeDAO.makePersistent(homeDirectory);
  +
  +            // Create home page
  +            Document homePage = new Document("Home of " + user.getUsername());
  +            homePage.setWikiname(WikiUtil.convertToWikiName(homePage.getName()));
  +            homePage.setCreatedBy(user);
  +            homePage.setAreaNumber(homeDirectory.getAreaNumber());
  +            homePage.setContent("This is the homepage of " + user.getFirstname() + " " + user.getLastname() + ".");
  +            homePage.setWriteAccessLevel(UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL);
  +            homePage.setReadAccessLevel(UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL);
  +            homeDirectory.addChild(homePage);
  +            homeDirectory.setDefaultDocument(homePage);
  +            nodeDAO.makePersistent(homeDirectory);
  +
  +            Contexts.getEventContext().set("activatedUser", user);
  +
               return "activated";
           } else {
               return "notFound";
           }
       }
   
  +    public String logout() {
  +        Identity.instance().logout();
  +        return "loggedOut";
  +    }
  +
  +    /**
  +     * Assigns the Guest user to 'currentUser' when 'currentUser' is first referenced. If a
  +     * user actually logs in, the 'currentUser' is reset.
  +     * @return User Guest user
  +     */
  +    @Factory(value = "currentUser", scope = ScopeType.SESSION, autoCreate = true)
  +    public User getGuestUser() {
  +        return (User) Component.getInstance("guestUser");
  +    }
  +
  +    /**
  +     * Assigns the context variable 'currentAccessLevel' when no user is logged in.
  +     * @return Integer Guest access level.
  +     */
  +    @Factory(value = "currentAccessLevel", scope = ScopeType.SESSION, autoCreate = true)
  +    public Integer getGuestAccessLevel() {
  +        return ((Role)Component.getInstance("guestRole")).getAccessLevel();
  +    }
  +
   }
  
  
  
  1.4       +12 -0     jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/FileHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: FileHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/FileHome.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -b -r1.3 -r1.4
  --- FileHome.java	9 Mar 2007 08:02:09 -0000	1.3
  +++ FileHome.java	18 Mar 2007 15:44:37 -0000	1.4
  @@ -1,5 +1,7 @@
   package org.jboss.seam.wiki.core.action;
   
  +import static javax.faces.application.FacesMessage.SEVERITY_WARN;
  +
   import javax.swing.*;
   
   import org.jboss.seam.annotations.*;
  @@ -27,6 +29,16 @@
       @Override
       public String persist() {
   
  +        // Validate
  +        if (filedata == null || filedata.length == 0) {
  +            getFacesMessages().addFromResourceBundleOrDefault(
  +                SEVERITY_WARN,
  +                getMessageKeyPrefix() + "noFileUploaded",
  +                "Please select a file to upload"
  +            );
  +            return null;
  +        }
  +
           // Sync file instance with form data
           syncFile();
   
  
  
  
  1.3       +17 -9     jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DirectoryHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: DirectoryHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DirectoryHome.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- DirectoryHome.java	8 Mar 2007 17:50:58 -0000	1.2
  +++ DirectoryHome.java	18 Mar 2007 15:44:37 -0000	1.3
  @@ -1,6 +1,7 @@
   package org.jboss.seam.wiki.core.action;
   
   import org.jboss.seam.annotations.*;
  +import org.jboss.seam.annotations.security.Restrict;
   import org.jboss.seam.annotations.datamodel.DataModel;
   import org.jboss.seam.annotations.datamodel.DataModelSelection;
   import org.jboss.seam.ScopeType;
  @@ -11,11 +12,14 @@
   
   import java.util.List;
   import java.util.Collections;
  +import java.util.ArrayList;
   
   @Name("directoryHome")
   @Scope(ScopeType.CONVERSATION)
   public class DirectoryHome extends NodeHome<Directory> {
   
  +    private List<Document> childDocuments = new ArrayList<Document>();
  +
       @Override
       @Transactional
       public void create() {
  @@ -30,12 +34,12 @@
       @Transactional
       public String persist() {
   
  -        if (parentDirectory.getParent() != null) {
  +        if (getParentDirectory().getParent() != null) {
               // This is a subdirectory in an area
  -            getInstance().setAreaNumber(parentDirectory.getAreaNumber());
  +            getInstance().setAreaNumber(getParentDirectory().getAreaNumber());
               return super.persist();
           } else {
  -            // This is a logical area
  +            // This is a logical area in the wiki root
   
               // Satisfy NOT NULL constraint
               getInstance().setAreaNumber(Long.MAX_VALUE);
  @@ -51,40 +55,44 @@
           }
       }
   
  -
       @Override
       public String remove() {
           if (getInstance().getParent() == null) return null; // Can not delete wiki root
           return super.remove();
       }
   
  +    public List<Document> getChildDocuments() {
  +        return childDocuments;
  +    }
  +
       @DataModel
       List<Node> childNodes;
   
       @DataModelSelection
       Node selectedChildNode;
   
  +    @Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}")
       public void moveNodeUpInList() {
           int position = getInstance().getChildren().indexOf(selectedChildNode);
           Collections.rotate(getInstance().getChildren().subList(position-1, position+1), 1);
           refreshChildNodes();
       }
   
  +    @Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}")
       public void moveNodeDownInList() {
           int position = getInstance().getChildren().indexOf(selectedChildNode);
           Collections.rotate(getInstance().getChildren().subList(position, position+2), 1);
           refreshChildNodes();
       }
   
  -    public void selectDefaultDocument() {
  -        getInstance().setDefaultDocument((Document)selectedChildNode);
  -        refreshChildNodes();
  -    }
  -
       private void refreshChildNodes() {
           childNodes = getInstance().getChildren();
  +        for (Node childNode : childNodes) {
  +            if (childNode instanceof Document) childDocuments.add((Document)childNode);
  +        }
       }
   
  +    @Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}")
       public void previewMenuItems() {
           // Refresh UI
           Events.instance().raiseEvent("Nodes.menuStructureModified");
  
  
  
  1.3       +24 -13    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeBrowser.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: NodeBrowser.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeBrowser.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- NodeBrowser.java	9 Mar 2007 08:02:09 -0000	1.2
  +++ NodeBrowser.java	18 Mar 2007 15:44:37 -0000	1.3
  @@ -2,10 +2,12 @@
   
   import org.jboss.seam.annotations.*;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.security.Identity;
   import org.jboss.seam.wiki.core.dao.NodeDAO;
   import org.jboss.seam.wiki.core.model.Node;
   import org.jboss.seam.wiki.core.model.Directory;
   import org.jboss.seam.wiki.core.model.Document;
  +import org.jboss.seam.wiki.core.model.GlobalPreferences;
   import org.jboss.seam.wiki.core.ui.WikiUtil;
   
   import java.util.*;
  @@ -47,26 +49,28 @@
       public void setNodeId(Long nodeId) { this.nodeId = nodeId; }
   
       @In
  -    protected org.jboss.seam.core.Redirect redirect;
  +    private Directory wikiRoot;
  +
  +    @In
  +    private GlobalPreferences globalPrefs;
   
       @In
  -    protected Directory wikiRoot;
  +    protected org.jboss.seam.core.Redirect redirect;
   
       @In
       protected NodeDAO nodeDAO;
   
       // These are only EVENT scoped, we don't want them to jump from DocumentBrowser to
       // DirectoryBrowser over redirects
  -    @In(required=false) @Out(scope = ScopeType.EVENT, required = false)
  +    @Out(scope = ScopeType.EVENT, required = false)
       protected Document currentDocument;
   
  -    @In(required=false) @Out(scope = ScopeType.EVENT, required = false)
  +    @Out(scope = ScopeType.EVENT, required = false)
       protected Directory currentDirectory;
   
       @Out(scope = ScopeType.EVENT)
       protected  List<Node> currentDirectoryPath = new ArrayList<Node>();
   
  -
       /**
        * Executes a redirect to the last view-id that was prepare()ed.
        * <p>
  @@ -107,12 +111,14 @@
   
       // Just a convenience method for recursive calling
       protected void addDirectoryToPath(List<Node> path, Node directory) {
  +        if (Identity.instance().hasPermission("Node", "read", directory) ||
  +            directory.getId().equals(wikiRoot.getId())
  +           )
           path.add(directory);
           if (directory.getParent() != null )
               addDirectoryToPath(path, directory.getParent());
       }
   
  -
       @Transactional
       public String prepare() {
   
  @@ -121,7 +127,7 @@
           // TODO: I'm not using captureCurrentView() because it starts a conversation (and it doesn't capture all request parameters)
   
           // Have we been called with a nodeId request parameter, could be document or directory
  -        if (nodeId != null && !nodeId.equals(wikiRoot.getId())) {
  +        if (nodeId != null) {
   
               // Try to find a document
               currentDocument = nodeDAO.findDocument(nodeId);
  @@ -131,7 +137,7 @@
                   currentDirectory = nodeDAO.findDirectory(nodeId);
   
                   // Try to get a default document of that directory
  -                if (currentDirectory != null) currentDocument = currentDirectory.getDefaultDocument();
  +                currentDocument = nodeDAO.findDefaultDocument(currentDirectory);
   
               } else {
                   // Document found, take its directory
  @@ -147,7 +153,7 @@
                   Node node = nodeDAO.findNodeInArea(area.getAreaNumber(), nodeName);
                   if (WikiUtil.isDirectory(node)) {
                       currentDirectory = (Directory)node;
  -                    currentDocument = currentDirectory.getDefaultDocument();
  +                    currentDocument = nodeDAO.findDefaultDocument(currentDirectory);
                    } else {
                       currentDocument = (Document)node;
                       currentDirectory = currentDocument != null ? currentDocument.getParent() : area;
  @@ -157,11 +163,16 @@
           // Or have we been called just with an areaName request parameter
           } else if (areaName != null) {
               currentDirectory = nodeDAO.findArea(areaName);
  -            if (currentDirectory != null) currentDocument = currentDirectory.getDefaultDocument();
  +            currentDocument = nodeDAO.findDefaultDocument(currentDirectory);
           }
   
  -        // Fall back to wiki root
  -        if (currentDirectory== null) currentDirectory = wikiRoot;
  +        // Fall back to default document
  +        if (currentDirectory == null) {
  +            currentDocument = nodeDAO.findDocument(globalPrefs.getDefaultDocumentId());
  +            if (currentDocument == null)
  +                throw new RuntimeException("Couldn't find default document with id '" + globalPrefs.getDefaultDocumentId() +"'");
  +            currentDirectory = currentDocument.getParent();
  +        }
   
           // Set the id for later
           nodeId = currentDocument != null ? currentDocument.getId() : currentDirectory.getId();
  
  
  
  1.3       +78 -61    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: NodeHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeHome.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- NodeHome.java	9 Mar 2007 08:02:09 -0000	1.2
  +++ NodeHome.java	18 Mar 2007 15:44:37 -0000	1.3
  @@ -1,6 +1,7 @@
   package org.jboss.seam.wiki.core.action;
   
   import static javax.faces.application.FacesMessage.SEVERITY_ERROR;
  +import javax.persistence.EntityManager;
   
   import org.jboss.seam.framework.EntityHome;
   import org.jboss.seam.wiki.core.dao.NodeDAO;
  @@ -10,12 +11,13 @@
   import org.jboss.seam.wiki.core.model.Node;
   import org.jboss.seam.wiki.core.ui.WikiUtil;
   import org.jboss.seam.annotations.In;
  -import org.jboss.seam.annotations.Out;
   import org.jboss.seam.annotations.RequestParameter;
   import org.jboss.seam.core.Conversation;
   import org.jboss.seam.core.Events;
   import org.jboss.seam.Component;
  -import org.jboss.seam.ScopeType;
  +import org.jboss.seam.contexts.Contexts;
  +import org.jboss.seam.security.AuthorizationException;
  +import org.jboss.seam.security.Identity;
   
   /**
    * Superclass for all creating and editing documents, directories, files, etc.
  @@ -27,13 +29,12 @@
       // Convenience wiring for subclasses
       @In private NodeDAO nodeDAO;
       @In private UserDAO userDAO;
  -    @In private User authenticatedUser;
  -
  -    protected Directory parentDirectory; // Assigned in create()
  +    @In private User currentUser;
  +    private Directory parentDirectory; // Assigned in create()
   
       protected NodeDAO getNodeDAO() { return nodeDAO; }
       protected UserDAO getUserDAO() { return userDAO; }
  -    protected User getAuthenticatedUser() { return authenticatedUser; }
  +    protected User getCurrentUser() { return currentUser; }
       public Directory getParentDirectory() { return parentDirectory; }
   
       // 'Edit' request parameter
  @@ -42,25 +43,9 @@
       // 'Create' request parameter
       @RequestParameter private Long parentDirId;
   
  -    @Out(required = true, scope = ScopeType.CONVERSATION)
  -    protected N currentNode;
  -
  -    // TODO: Typical exit method to get out of a root or nested conversation, JBSEAM-906
  -    public void exitConversation(Boolean endBeforeRedirect) {
  -        Conversation currentConversation = Conversation.instance();
  -        if (currentConversation.isNested()) {
  -            // End this nested conversation and return to last rendered view-id of parent
  -            currentConversation.endAndRedirect(endBeforeRedirect);
  -        } else {
  -            // End this root conversation
  -            currentConversation.end();
  -            // Return to the view-id that was captured when this conversation started
  -            NodeBrowser browser = (NodeBrowser) Component.getInstance("browser");
  -            if (endBeforeRedirect)
  -                browser.redirectToLastBrowsedPage();
  -            else
  -                browser.redirectToLastBrowsedPageWithConversation();
  -        }
  +    @Override
  +    protected String getPersistenceContextName() {
  +        return "restrictedEntityManager";
       }
   
       // 'Edit' or 'Create'
  @@ -74,26 +59,42 @@
           }
       }
   
  +    // Access level filtered DAO
  +    @Override
  +    public N find() {
  +        N result = (N)nodeDAO.findNode((Long)getId());
  +        if (result==null) handleNotFound();
  +        return result;
  +    }
  +
       @Override
       public void create() {
           super.create();
   
  -        // Load the parent directory (needs to be called first, ugly dependency in createInstance() )
  -        // The parentDirectory (and parentDirId) parameter can actually be null but this onl happens
  -        // when the wiki root is edited... it can only be update()ed anyway.
  +
  +        // Load the parent directory (needs to be called first)
  +        // The parentDirectory (and parentDirId) parameter can actually be null but this only happens
  +        // when the wiki root is edited... it can only be update()ed anyway, all the other code is null-safe.
           parentDirectory = nodeDAO.findDirectory(parentDirId);
   
  +        // Permission checks
  +        if (!isManaged() && !Identity.instance().hasPermission("Node", "create", getParentDirectory()) ) {
  +            throw new AuthorizationException("You don't have permission for this operation");
  +        } else if ( !Identity.instance().hasPermission("Node", "edit", getInstance()) ) {
  +            throw new AuthorizationException("You don't have permission for this operation");
  +        }
  +
           // Outject current node
  -        currentNode = getInstance();
  +        Contexts.getConversationContext().set("currentNode", getInstance());
       }
   
       @Override
       protected N createInstance() {
           N node = super.createInstance();
   
  -        // Set default permissions for new nodes - just like parent directory
  -        node.setWriteAccessLevel(parentDirectory.getWriteAccessLevel());
  -        node.setReadAccessLevel(parentDirectory.getReadAccessLevel());
  +        // Set default permissions for new nodes - default to same access as parent directory
  +        node.setWriteAccessLevel(getParentDirectory().getWriteAccessLevel());
  +        node.setReadAccessLevel(getParentDirectory().getReadAccessLevel());
   
           return node;
       }
  @@ -101,22 +102,24 @@
       @Override
       public String persist() {
   
  +        // Permission check (double check if subclass already called it)
  +        checkNodeAccessLevelChangePermission();
  +
           // Set the wikiname
           getInstance().setWikiname(WikiUtil.convertToWikiName(getInstance().getName()));
   
  -        // Link the document with a directory
  -        parentDirectory.addChild(getInstance());
  +        // Link the node with its parent directory
  +        getParentDirectory().addChild(getInstance());
   
           // Set created by user
  -        getInstance().setCreatedBy(authenticatedUser);
  +        getInstance().setCreatedBy(getCurrentUser());
   
  -        // Set its area number
  +        // Set its area number (if subclass didn't already set it)
           if (getInstance().getAreaNumber() == null)
  -            getInstance().setAreaNumber(parentDirectory.getAreaNumber());
  +            getInstance().setAreaNumber(getParentDirectory().getAreaNumber());
   
           // Validate
  -        if (!isUniqueWikinameInDirectory() ||
  -            !isUniqueWikinameInArea()) return null;
  +        if (!isValidModel()) return null;
   
           return super.persist();
       }
  @@ -124,12 +127,14 @@
       @Override
       public String update() {
   
  +        // Permission check (double check if subclass already called it)
  +        checkNodeAccessLevelChangePermission();
  +
           // Set last modified by user
  -        getInstance().setLastModifiedBy(authenticatedUser);
  +        getInstance().setLastModifiedBy(getCurrentUser());
   
           // Validate
  -        if (!isUniqueWikinameInDirectory() ||
  -            !isUniqueWikinameInArea()) return null;
  +        if (!isValidModel()) return null;
   
           // Refresh UI
           Events.instance().raiseEvent("Nodes.menuStructureModified");
  @@ -152,12 +157,39 @@
           return super.remove();
       }
   
  +    // TODO: Typical exit method to get out of a root or nested conversation, JBSEAM-906
  +    public void exitConversation(Boolean endBeforeRedirect) {
  +        Conversation currentConversation = Conversation.instance();
  +        if (currentConversation.isNested()) {
  +            // End this nested conversation and return to last rendered view-id of parent
  +            currentConversation.endAndRedirect(endBeforeRedirect);
  +        } else {
  +            // End this root conversation
  +            currentConversation.end();
  +            // Return to the view-id that was captured when this conversation started
  +            NodeBrowser browser = (NodeBrowser) Component.getInstance("browser");
  +            if (endBeforeRedirect)
  +                browser.redirectToLastBrowsedPage();
  +            else
  +                browser.redirectToLastBrowsedPageWithConversation();
  +        }
  +    }
  +
  +    protected void checkNodeAccessLevelChangePermission() {
  +
  +        if (!Identity.instance().hasPermission("Node", "changeAccessLevel", getInstance()))
  +            throw new AuthorizationException("You don't have permission for this operation");
  +    }
  +
       // Validation rules for persist(), update(), and remove();
   
  -    protected boolean isUniqueWikinameInDirectory() {
  -        if (parentDirectory == null) return true; // Editing wiki root
  -        Node foundNode = nodeDAO.findNodeInDirectory(parentDirectory, getInstance().getWikiname());
  -        if (foundNode != null && foundNode != getInstance()) {
  +    private boolean isValidModel() {
  +        if (getParentDirectory() == null) return true; // Special case, editing the wiki root
  +
  +        // Unique wiki name
  +        if (nodeDAO.isUniqueWikiname(getInstance())) {
  +            return true;
  +        } else {
               getFacesMessages().addToControlFromResourceBundleOrDefault(
                   "name",
                   SEVERITY_ERROR,
  @@ -166,22 +198,7 @@
               );
               return false;
           }
  -        return true;
  -    }
   
  -    protected boolean isUniqueWikinameInArea() {
  -        if (parentDirectory == null) return true; // Editing wiki root
  -        Node foundNode = nodeDAO.findNodeInArea(parentDirectory.getAreaNumber(), getInstance().getWikiname());
  -        if (foundNode != null && foundNode != getInstance()) {
  -            getFacesMessages().addToControlFromResourceBundleOrDefault(
  -                "name",
  -                SEVERITY_ERROR,
  -                getMessageKeyPrefix() + "duplicateNameInArea",
  -                "This name is already used in this area, please change it."
  -            );
  -            return false;
  -        }
  -        return true;
       }
   
   }
  
  
  
  1.2       +32 -16    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/UserHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: UserHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/UserHome.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- UserHome.java	7 Mar 2007 18:37:37 -0000	1.1
  +++ UserHome.java	18 Mar 2007 15:44:37 -0000	1.2
  @@ -2,21 +2,26 @@
   
   
   import org.jboss.seam.annotations.*;
  +import org.jboss.seam.annotations.security.Restrict;
   import org.jboss.seam.core.FacesMessages;
   import org.jboss.seam.core.Renderer;
   import org.jboss.seam.core.Conversation;
   import org.jboss.seam.framework.EntityHome;
   import org.jboss.seam.wiki.core.dao.UserDAO;
   import org.jboss.seam.wiki.core.model.*;
  +import org.jboss.seam.wiki.core.model.Role;
   import org.jboss.seam.wiki.util.Hash;
   import org.jboss.seam.Component;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.contexts.Contexts;
   
   import javax.faces.application.FacesMessage;
   import java.util.regex.Matcher;
   import java.util.regex.Pattern;
  +import java.util.List;
   
   @Name("userHome")
  + at Scope(ScopeType.CONVERSATION)
   public class UserHome extends EntityHome<User> {
   
       @RequestParameter
  @@ -29,18 +34,11 @@
       private UserDAO userDAO;
   
       @In
  -    private NodeBrowser browser;
  -
  -    @In
       private Hash hashUtil;
   
       @In
       private GlobalPreferences globalPrefs;
   
  -    @In(required = false)
  -    @Out(required = false, scope = ScopeType.SESSION)
  -    private User authenticatedUser;
  -
       @In
       private Renderer renderer;
   
  @@ -49,6 +47,7 @@
       private String oldUsername;
       private String password;
       private String passwordControl;
  +    private List<Role> roles;
   
       @Override
       public Object getId() {
  @@ -64,10 +63,9 @@
       public void create() {
           super.create();
   
  -        defaultRole = userDAO.findRole(globalPrefs.getNewUserInRole());
  -        if (defaultRole == null) throw new RuntimeException("Default role for new users not configured");
  -
  +        defaultRole = (Role)Component.getInstance("newUserDefaultRole");
           oldUsername = getInstance().getUsername();
  +        if (isManaged()) roles = getInstance().getRoles();
       }
   
       // TODO: Typical exit method to get out of a root or nested conversation, JBSEAM-906
  @@ -80,6 +78,7 @@
               // End this root conversation
               currentConversation.end();
               // Return to the view-id that was captured when this conversation started
  +            NodeBrowser browser = (NodeBrowser) Component.getInstance("browser");
               if (endBeforeRedirect)
                   browser.redirectToLastBrowsedPage();
               else
  @@ -103,7 +102,7 @@
           }
   
           // Assign default role
  -        getInstance().addRole(defaultRole);
  +        getInstance().getRoles().add(defaultRole);
   
           // Set password hash
           getInstance().setPasswordHash(hashUtil.hash(getPassword()));
  @@ -116,6 +115,7 @@
           if (outcome != null) {
   
               try {
  +
                   // Send confirmation email
                   renderer.render("/themes/" + globalPrefs.getThemeName() + "/mailtemplates/confirmationRegistration.xhtml");
   
  @@ -126,9 +126,17 @@
                       "A confirmation e-mail has been sent to '" + getInstance().getEmail() + "'. " +
                       "Please read this e-mail to activate your account.");
   
  +                /* For debugging
  +                facesMessages.addFromResourceBundleOrDefault(
  +                    FacesMessage.SEVERITY_INFO,
  +                    getMessageKeyPrefix() + "confirmationEmailSent",
  +                    "Activiate account: confirmRegistration.seam?activationCode=" + getInstance().getActivationCode());
  +                */
  +
                   exitConversation(false);
   
               } catch (Exception ex) {
  +                ex.printStackTrace(System.out);
                   facesMessages.add(FacesMessage.SEVERITY_ERROR, "Couldn't send confirmation email: " + ex.getMessage());
                   return "error";
               }
  @@ -137,13 +145,17 @@
           return outcome;
       }
   
  -
  +    @Restrict("#{s:hasPermission('User', 'edit', userHome.instance)}")
       public String update() {
   
           // Validate
           if (!isUniqueUsername())
                   return null;
   
  +        // Roles
  +        getInstance().getRoles().clear();
  +        getInstance().getRoles().addAll(roles);
  +
           boolean loginCredentialsModified = false;
   
           // User wants to change his password
  @@ -170,9 +182,10 @@
           String outcome = super.update();
           if (outcome != null) {
   
  -            if (authenticatedUser != null && getInstance().getId().equals(authenticatedUser.getId())) {
  +            User currentUser = (User)Component.getInstance("currentUser");
  +            if (getInstance().getId().equals(currentUser.getId())) {
                   // Updated profile of currently logged-in user
  -                authenticatedUser = getInstance();
  +                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
  @@ -220,6 +233,9 @@
       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; }
   
       // Validation rules for persist(), update(), and remove();
   
  @@ -268,8 +284,8 @@
       @Transactional
       private boolean isUniqueUsername() {
           getEntityManager().joinTransaction();
  -        User foundUser = userDAO.findUser(getInstance().getUsername(), false);
  -        if ( foundUser != null && foundUser != getInstance()) {
  +        User foundUser = userDAO.findUser(getInstance().getUsername(), false, false);
  +        if ( foundUser != null && foundUser != getInstance() ) {
               facesMessages.addToControlFromResourceBundleOrDefault(
                   "username",
                   FacesMessage.SEVERITY_ERROR,
  
  
  
  1.2       +22 -10    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeHistory.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: NodeHistory.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeHistory.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- NodeHistory.java	7 Mar 2007 18:37:37 -0000	1.1
  +++ NodeHistory.java	18 Mar 2007 15:44:37 -0000	1.2
  @@ -4,6 +4,7 @@
   import org.jboss.seam.annotations.datamodel.DataModel;
   import org.jboss.seam.annotations.datamodel.DataModelSelection;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.Component;
   import org.jboss.seam.core.FacesMessages;
   import org.jboss.seam.core.Conversation;
   import org.jboss.seam.wiki.core.dao.NodeDAO;
  @@ -22,9 +23,6 @@
   public class NodeHistory implements Serializable {
   
       @In
  -    private NodeBrowser browser;
  -
  -    @In
       NodeDAO nodeDAO;
   
       @In
  @@ -46,9 +44,23 @@
       private String diffResult;
   
       @Factory("historicalNodeList")
  -    public void initialize() {
  +    public void initializeHistoricalNodeList() {
  +        if (historicalNodeList == null)
  +            historicalNodeList = nodeDAO.findHistoricalNodes(currentNode);
  +    }
  +
  +    @Create
  +    public void create() {
           historicalNodeList = nodeDAO.findHistoricalNodes(currentNode);
           currentDirectory = (Directory)currentNode.getParent();
  +
  +        if (historicalNodeList.size() == 0) {
  +            facesMessages.addFromResourceBundleOrDefault(
  +                FacesMessage.SEVERITY_INFO,
  +                "noHistory",
  +                "No stored history for this document.");
  +            exitConversation(false);
  +        }
       }
   
       // TODO: Typical exit method to get out of a root or nested conversation, JBSEAM-906
  @@ -61,6 +73,7 @@
               // End this root conversation
               currentConversation.end();
               // Return to the view-id that was captured when this conversation started
  +            NodeBrowser browser = (NodeBrowser) Component.getInstance("browser");
               if (endBeforeRedirect)
                   browser.redirectToLastBrowsedPage();
               else
  @@ -69,26 +82,25 @@
       }
   
       public void diff() {
  -        System.out.println("#### GENERATING NEW DIFF");
   
           String revision = ((Document)currentNode).getContent();
           String original = ((Document)selectedHistoricalNode).getContent();
   
           Diff diff = new Diff() {
               protected String getDeletionStartMarker() {
  -                return "xXx";
  +                return "XXXXXXX";
               }
   
               protected String getDeletionEndMarker() {
  -                return "XxX";
  +                return "XXXXXXX";
               }
   
               protected String getAdditionStartMarker() {
  -                return "aAa";
  +                return "AAAAAAA";
               }
   
               protected String getAdditionEndMarker() {
  -                return "AaA";
  +                return "AAAAAAA";
               }
           };
   
  @@ -110,7 +122,7 @@
           facesMessages.addFromResourceBundleOrDefault(
               FacesMessage.SEVERITY_INFO,
               "rollingBackDocument",
  -            "Rolling back to revision '" + selectedHistoricalNode.getRevision() + "'");
  +            "Rolling back to revision " + selectedHistoricalNode.getRevision());
           return "rollback";
       }
   
  
  
  
  1.2       +4 -2      jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Menu.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: Menu.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Menu.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- Menu.java	7 Mar 2007 18:37:37 -0000	1.1
  +++ Menu.java	18 Mar 2007 15:44:37 -0000	1.2
  @@ -3,6 +3,7 @@
   import org.jboss.seam.annotations.*;
   import org.jboss.seam.ScopeType;
   import org.jboss.seam.Component;
  +import org.jboss.seam.security.Identity;
   import org.jboss.seam.wiki.core.model.Node;
   import org.jboss.seam.wiki.core.model.Directory;
   import org.jboss.seam.wiki.core.ui.WikiUtil;
  @@ -33,7 +34,7 @@
       @Observer("Nodes.menuStructureModified")
       public void refreshMenuItems() {
           items = new ArrayList<MenuItem>();
  -        for(Node area : ((Directory)Component.getInstance("wikiRoot")).getChildren())
  +        for(Node area : ((Directory)Component.getInstance("restrictedWikiRoot")).getChildren())
               addNodesToMenuTree(items, 0, area);
       }
   
  @@ -41,7 +42,8 @@
       private void addNodesToMenuTree(List<MenuItem> menuItems, int i, Node node) {
           MenuItem menuItem = new MenuItem(node, WikiUtil.renderURL(node));
           menuItem.setLevel(i);
  -        if (node.isMenuItem()) menuItems.add(menuItem); // Check flag in-memory
  +        if (node.isMenuItem() && Identity.instance().hasPermission("Node", "read", node))
  +            menuItems.add(menuItem); // Check flag in-memory
           if (node.getChildren() != null && node.getChildren().size() > 0) {
               i++;
               for (Node child : node.getChildren()) {
  
  
  
  1.4       +37 -26    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DocumentHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: DocumentHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DocumentHome.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -b -r1.3 -r1.4
  --- DocumentHome.java	8 Mar 2007 17:50:58 -0000	1.3
  +++ DocumentHome.java	18 Mar 2007 15:44:37 -0000	1.4
  @@ -6,15 +6,13 @@
   import org.jboss.seam.core.Events;
   import org.jboss.seam.Component;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.security.AuthorizationException;
   import org.jboss.seam.contexts.Contexts;
   
   @Name("documentHome")
   @Scope(ScopeType.CONVERSATION)
   public class DocumentHome extends NodeHome<Document> {
   
  -    @In
  -    WikiLinkResolver wikiLinkResolver;
  -
       private String formContent;
       private boolean enabledPreview = false;
   
  @@ -40,23 +38,18 @@
   
       @Override
       public String persist() {
  +        checkNodeAccessLevelChangePermission();
   
  -        // Convert and set form content onto entity instance
  -        getInstance().setContent(
  -            wikiLinkResolver.convertToWikiLinks(parentDirectory, getFormContent())
  -        );
  -
  +        syncFormText();
           return super.persist();
       }
   
  -
       @Override
  +    @Transactional
       public String update() {
  +        checkNodeAccessLevelChangePermission();
   
  -        // Convert and set form content onto entity instance
  -        getInstance().setContent(
  -            wikiLinkResolver.convertToWikiLinks(parentDirectory, getFormContent())
  -        );
  +        syncFormText();
   
           Events.instance().raiseEvent("Nodes.menuStructureModified");
   
  @@ -64,6 +57,7 @@
           if (!isMinorRevision()) {
               getNodeDAO().persistHistoricalNode(historicalCopy);
               getInstance().incrementRevision();
  +            // New historical copy in conversation
               historicalCopy = new Document(getInstance());
           }
   
  @@ -71,18 +65,30 @@
       }
   
       @Override
  +    @Transactional
       public String remove() {
   
           // Delete all history nodes
           getNodeDAO().removeHistoricalNodes(getInstance());
   
  +        // Unset the default document id
  +        if (getParentDirectory().getDefaultDocument().equals(getInstance()))
  +            getParentDirectory().setDefaultDocument(null);
  +
           return super.remove();
       }
   
       public String getFormContent() {
           // Load the document content and resolve links
  -        if (formContent == null)
  -            formContent = wikiLinkResolver.convertFromWikiLinks(parentDirectory, getInstance().getContent());
  +        if (formContent == null) {
  +
  +            // Outject instances required for WikiLinkResolver
  +            Contexts.getEventContext().set("currentDocument", getInstance());
  +            Contexts.getEventContext().set("currentDirectory", getParentDirectory());
  +
  +            WikiLinkResolver wikiLinkResolver = (WikiLinkResolver)Component.getInstance("wikiLinkResolver");
  +            formContent = wikiLinkResolver.convertFromWikiLinks(getParentDirectory(), getInstance().getContent());
  +        }
           return formContent;
       }
   
  @@ -96,16 +102,8 @@
   
       public void setEnabledPreview(boolean enabledPreview) {
           this.enabledPreview = enabledPreview;
  -
  -        // Convert and set form content onto entity instance
  -        getInstance().setContent(
  -            wikiLinkResolver.convertToWikiLinks(parentDirectory, getFormContent())
  -        );
  -
  -        // Outject instances required for WikiLinkResolver during preview rendering
  -        Contexts.getEventContext().set("currentDocument", getInstance());
  -        Contexts.getEventContext().set("currentDirectory", getParentDirectory());
  -
  +        syncFormText();
  +        Events.instance().raiseEvent("Nodes.menuStructureModified");
       }
   
       public boolean isMinorRevision() {
  @@ -116,4 +114,17 @@
           this.minorRevision = minorRevision;
       }
   
  +    private void syncFormText() {
  +
  +        // Outject instances required for WikiLinkResolver
  +        Contexts.getEventContext().set("currentDocument", getInstance());
  +        Contexts.getEventContext().set("currentDirectory", getParentDirectory());
  +
  +        // Convert and set form content onto entity instance
  +        WikiLinkResolver wikiLinkResolver = (WikiLinkResolver)Component.getInstance("wikiLinkResolver");
  +        getInstance().setContent(
  +            wikiLinkResolver.convertToWikiLinks(getParentDirectory(), getFormContent())
  +        );
  +    }
  +
   }
  
  
  
  1.2       +35 -19    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodePermissions.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: NodePermissions.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodePermissions.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- NodePermissions.java	8 Mar 2007 17:50:58 -0000	1.1
  +++ NodePermissions.java	18 Mar 2007 15:44:37 -0000	1.2
  @@ -5,8 +5,12 @@
   import org.jboss.seam.annotations.Scope;
   import org.jboss.seam.annotations.Create;
   import org.jboss.seam.wiki.core.model.Node;
  -import org.jboss.seam.wiki.core.dao.UserDAO;
  +import org.jboss.seam.wiki.core.model.Role;
  +import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.Component;
  +
  +import java.util.List;
   
   @Name("nodePermissions")
   @Scope(ScopeType.CONVERSATION)
  @@ -15,36 +19,48 @@
       @In
       Node currentNode;
   
  -    private org.jboss.seam.wiki.core.model.Role writableByRole;
  -    private org.jboss.seam.wiki.core.model.Role readableByRole;
  -
  -    @In
  -    private UserDAO userDAO;
  +    private Role.AccessLevel writeAccessLevel;
  +    private Role.AccessLevel readAccessLevel;
   
       @Create
       public void setCurrentNodePermissions() {
  +
           // Set permission defaults
  -        writableByRole = userDAO.findRole(currentNode.getWriteAccessLevel());
  -        readableByRole = userDAO.findRole(currentNode.getReadAccessLevel());
  -    }
  +        List<Role.AccessLevel> accessLevelsList =
  +                (List<Role.AccessLevel>) Component.getInstance("accessLevelsList");
   
  -    public org.jboss.seam.wiki.core.model.Role getWritableByRole() {
  -        return writableByRole;
  +        writeAccessLevel = accessLevelsList.get(
  +            accessLevelsList.indexOf(
  +                new Role.AccessLevel(currentNode.getWriteAccessLevel())
  +            )
  +        );
  +        readAccessLevel = accessLevelsList.get(
  +            accessLevelsList.indexOf(
  +                new Role.AccessLevel(currentNode.getReadAccessLevel())
  +            )
  +        );
       }
   
  -    public void setWritableByRole(org.jboss.seam.wiki.core.model.Role writableByRole) {
  -        this.writableByRole = writableByRole;
  -        currentNode.setWriteAccessLevel(writableByRole != null ? writableByRole.getAccessLevel() : 1000);
  +    public Role.AccessLevel getWriteAccessLevel() {
  +        return writeAccessLevel;
       }
   
  -    public org.jboss.seam.wiki.core.model.Role getReadableByRole() {
  -        return readableByRole;
  +    public void setWriteAccessLevel(Role.AccessLevel writeAccessLevel) {
  +        this.writeAccessLevel = writeAccessLevel;
  +        currentNode.setWriteAccessLevel(
  +            writeAccessLevel != null ? writeAccessLevel.getAccessLevel() : UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL
  +        );
       }
   
  -    public void setReadableByRole(org.jboss.seam.wiki.core.model.Role readableByRole) {
  -        this.readableByRole = readableByRole;
  -        currentNode.setReadAccessLevel(readableByRole != null ? readableByRole.getAccessLevel() : 1000);
  +    public Role.AccessLevel getReadAccessLevel() {
  +        return readAccessLevel;
       }
   
  +    public void setReadAccessLevel(Role.AccessLevel readAccessLevel) {
  +        this.readAccessLevel = readAccessLevel;
  +        currentNode.setReadAccessLevel(
  +            readAccessLevel != null ? readAccessLevel.getAccessLevel() : UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL
  +        );
  +    }
   
   }
  
  
  
  1.1      date: 2007/03/18 15:44:37;  author: cbauer;  state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/WikiIdentity.java
  
  Index: WikiIdentity.java
  ===================================================================
  package org.jboss.seam.wiki.core.action;
  
  import static org.jboss.seam.InterceptionType.NEVER;
  import static org.jboss.seam.ScopeType.SESSION;
  import static org.jboss.seam.annotations.Install.APPLICATION;
  
  import org.jboss.seam.security.Identity;
  import org.jboss.seam.annotations.*;
  import org.jboss.seam.wiki.core.model.User;
  import org.jboss.seam.wiki.core.model.Directory;
  import org.jboss.seam.wiki.core.model.Node;
  import org.jboss.seam.wiki.core.model.GlobalPreferences;
  import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
  import org.jboss.seam.Component;
  
  /**
   * Need this until Drools fixes bugs and becomes usable/debuggable.
   *
   */
  @Name("org.jboss.seam.security.identity")
  @Scope(SESSION)
  @Intercept(NEVER)
  @Install(precedence=APPLICATION)
  @Startup
  public class WikiIdentity extends Identity {
  
      private User currentUser;
      private Integer currentAccessLevel;
      private GlobalPreferences globalPrefs;
  
      public boolean hasPermission(String name, String action, Object... args) {
  
          currentUser = (User)Component.getInstance("currentUser");
          currentAccessLevel = (Integer)Component.getInstance("currentAccessLevel");
          globalPrefs = (GlobalPreferences)Component.getInstance("globalPrefs");
  
          if (args == null || args.length == 0) {
              // All the security checks currently need arguments...
              return false;
          }
  
          if ("Node".equals(name) && "create".equals(action)) {
              return checkCreateAccess( (Directory)args[0]);
          } else
          if ("Node".equals(name) && "edit".equals(action)) {
              return checkEditAccess((Node)args[0]);
          } else
          if ("Node".equals(name) && "read".equals(action)) {
              return checkReadAccess((Node)args[0]);
          } else
          if ("Node".equals(name) && "changeAccessLevel".equals(action)) {
              return checkRaiseAccessLevel((Node)args[0]);
          } else
          if ("User".equals(name) && "edit".equals(action)) {
              return checkEditUser((User)args[0]);
          } else
          if ("User".equals(name) && "editRoles".equals(action)) {
              return checkEditUserRoles((User)args[0]);
          } else
          if ("Node".equals(name) && "editMenu".equals(action)) {
              return checkEditMenu((Node)args[0]);
          }
  
          return false;
      }
  
      /*
          User either needs to have the access level of the parent directory
          or the user is the creator of the parent directory
      */
      private boolean checkCreateAccess(Directory directory) {
          if (globalPrefs.getMemberAreaId().equals(directory.getId())) return false; // Member home dir is immutable
          if (directory.getWriteAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL) return true;
          int dirWriteAccessLevel = directory.getWriteAccessLevel();
          User dirCreator = directory.getCreatedBy();
          if (
              currentAccessLevel >= dirWriteAccessLevel
              ||
              currentUser.getId().equals(dirCreator.getId())
             )
             return true;
  
          return false;
      }
  
      /*
          User either needs to have the access level of the edited node or has to be the creator
      */
      private boolean checkReadAccess(Node node) {
          if (node.getReadAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL) return true;
          int nodeReadAccessLevel = node.getReadAccessLevel();
          User nodeCreator = node.getCreatedBy();
  
          if (currentAccessLevel >= nodeReadAccessLevel
              ||
              currentUser.getId().equals(nodeCreator.getId())
             )
             return true;
  
          return false;
      }
  
      /*
          User either needs to have the access level of the edited node or has to be the creator
      */
      private boolean checkEditAccess(Node node) {
          if (globalPrefs.getMemberAreaId().equals(node.getId())) return false; // Member home dir is immutable
          if (node.getWriteAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL) return true;
          int nodeWriteAccessLevel = node.getWriteAccessLevel();
          User nodeCreator = node.getCreatedBy();
  
          if (currentAccessLevel >= nodeWriteAccessLevel
              ||
              currentUser.getId().equals(nodeCreator.getId())
             )
             return true;
  
          return false;
      }
  
      /*
          User can't persist or update a node and assign a higher access level than
          he has, unless he is the creator
      */
      private boolean checkRaiseAccessLevel(Node node) {
          if (globalPrefs.getMemberAreaId().equals(node.getId())) return false; // Member home dir is immutable
          int desiredWriteAccessLevel = node.getWriteAccessLevel();
          int desiredReadAccessLevel = node.getReadAccessLevel();
          User nodeCreator = node.getCreatedBy();
  
          if (
              ( desiredReadAccessLevel <= currentAccessLevel
                &&
                desiredWriteAccessLevel <= currentAccessLevel )
              ||
              ( nodeCreator == null
                ||
                currentUser.getId().equals(nodeCreator.getId()) )
             )
             return true;
  
          return false;
      }
  
      /*
          Only admins can change roles of a user
      */
      private boolean checkEditUserRoles(User currentUser) {
          return currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL;
      }
  
      /*
          Only admins can edit users, or the user himself
      */
      private boolean checkEditUser(User user) {
          if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
          if (currentUser.getId() == user.getId()) return true;
          return false;
      }
  
      /*
          Only admins can edit the main menu
      */
      private boolean checkEditMenu(Node node) {
          if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
          return false;
      }
  
  }
  
  
  



More information about the jboss-cvs-commits mailing list