[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