Author: dkuleshov
Date: 2011-01-21 03:01:45 -0500 (Fri, 21 Jan 2011)
New Revision: 3825
Added:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/AclCommand.java
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/acl/
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/acl/ACLProperties.java
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestAclCommand.java
Modified:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavService.java
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/FileResource.java
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/WebDavConstants.java
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/utils/TestUtils.java
Log:
EXOJCR-1032: Limited support WedDav ACL specification
Modified:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavService.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavService.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavService.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -256,4 +256,17 @@
* @return the instance of javax.ws.rs.core.Response
*/
Response search(String repoName, String repoPath, UriInfo baseURI,
HierarchicalProperty body);
+
+ /**
+ * WebDAV ACL method according to protocol extension - Access Control Protocol:
RFC3744
+ * More details here: <a
href='http://www.webdav.org/specs/rfc3744.html'>Web Distributed
+ * Authoring and Versioning (WebDAV) Access Control Protocol</a>
+ * @param repoName repository name
+ * @param repoPath path in repository
+ * @param lockTokenHeader Lock-Token HTTP header
+ * @param ifHeader If- HTTP Header
+ * @param body Request body
+ * @return the instance of javax.ws.rs.core.Response
+ */
+ Response acl(String repoName, String repoPath, String lockTokenHeader, String
ifHeader, HierarchicalProperty body);
}
Modified:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -27,6 +27,7 @@
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.app.ThreadLocalSessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
+import org.exoplatform.services.jcr.webdav.command.AclCommand;
import org.exoplatform.services.jcr.webdav.command.CopyCommand;
import org.exoplatform.services.jcr.webdav.command.DeleteCommand;
import org.exoplatform.services.jcr.webdav.command.GetCommand;
@@ -51,6 +52,7 @@
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.rest.ExtHttpHeaders;
+import org.exoplatform.services.rest.ext.webdav.method.ACL;
import org.exoplatform.services.rest.ext.webdav.method.CHECKIN;
import org.exoplatform.services.rest.ext.webdav.method.CHECKOUT;
import org.exoplatform.services.rest.ext.webdav.method.COPY;
@@ -935,7 +937,7 @@
+ "<exo:xpath
xmlns:exo=\"http://exoplatform.com/jcr\"/>";
return Response.ok().header(ExtHttpHeaders.ALLOW, /* allowCommands
*/ALLOW).header(ExtHttpHeaders.DAV,
- "1, 2, ordered-collections").header(ExtHttpHeaders.DASL,
DASL_VALUE).header(ExtHttpHeaders.MSAUTHORVIA, "DAV")
+ "1, 2, ordered-collections,
access-control").header(ExtHttpHeaders.DASL,
DASL_VALUE).header(ExtHttpHeaders.MSAUTHORVIA, "DAV")
.build();
}
@@ -1261,6 +1263,41 @@
}
/**
+ * {@inheritDoc}
+ */
+ @ACL
+ @Path("/{repoName}/{repoPath:.*}/")
+ public Response acl(@PathParam("repoName") String repoName,
@PathParam("repoPath") String repoPath,
+ @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
@HeaderParam(ExtHttpHeaders.IF) String ifHeader,
+ HierarchicalProperty body)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("ACL " + repoName + "/" + repoPath);
+ }
+
+ repoPath = normalizePath(repoPath);
+
+ try
+ {
+ List<String> lockTokens = lockTokens(lockTokenHeader, ifHeader);
+ Session session = session(repoName, workspaceName(repoPath), lockTokens);
+ return new AclCommand().acl(session, path(repoPath), body);
+ }
+
+ catch (NoSuchWorkspaceException exc)
+ {
+ log.error("NoSuchWorkspace. " + exc.getMessage());
+ return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
+ }
+ catch (Exception exc)
+ {
+ log.error(exc.getMessage(), exc);
+ return
Response.status(HTTPStatus.INTERNAL_ERROR).entity(exc.getMessage()).build();
+ }
+ }
+
+ /**
* Gives access to the current session.
*
* @param repoName repository name
Added:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/AclCommand.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/AclCommand.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/AclCommand.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -0,0 +1,317 @@
+/**
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ *
+ */
+
+package org.exoplatform.services.jcr.webdav.command;
+
+import org.exoplatform.common.http.HTTPStatus;
+import org.exoplatform.common.util.HierarchicalProperty;
+import org.exoplatform.services.jcr.access.AccessControlList;
+import org.exoplatform.services.jcr.access.PermissionType;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.webdav.command.acl.ACLProperties;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.services.security.IdentityConstants;
+
+import java.security.AccessControlException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * Created by The eXo Platform SAS.
+ * ACL method implementation for Web Distributed Authoring and Versioning (WebDAV)
+ * protocol extension - Access Control Protocol: RFC3744.
+ *
+ * @author <a href="mailto:gavrikvetal@gmail.com">Vitaliy
Gulyy</a>
+ * @version $
+ */
+
+public class AclCommand
+{
+
+ /**
+ * logger.
+ */
+ private static Log log = ExoLogger.getLogger(AclCommand.class);
+
+ /**
+ * Applies changes for JCR node's {@link AccessControlList}
+ * according to WebDAV ACL method request body represented by {@link
HierarchicalProperty}
+ * @param session - actual session
+ * @param path - absolute path to jcr node
+ * @param requestBody - tree like structure to contain ACL method request body
+ * @return response - http response for ACL method request
+ */
+ public Response acl(Session session, String path, HierarchicalProperty requestBody)
+ {
+ NodeImpl node;
+ try
+ {
+ node = (NodeImpl)session.getItem(path);
+
+ boolean isSessionToBeSaved = false;
+
+ boolean nodeIsNotCheckedOut = node.isNodeType("mix:versionable")
&& !node.isCheckedOut();
+
+ // to set ACL the node necessarily must be exo:owneable
+ if (!node.isNodeType("exo:owneable"))
+ {
+ if (nodeIsNotCheckedOut)
+ {
+ node.checkout();
+ }
+ node.addMixin("exo:owneable");
+ isSessionToBeSaved = true;
+ }
+
+ // to set ACL the node necessarily must be exo:privilegeable
+ if (!node.isNodeType("exo:privilegeable"))
+ {
+ if (nodeIsNotCheckedOut)
+ {
+ node.checkout();
+ }
+ node.addMixin("exo:privilegeable");
+ isSessionToBeSaved = true;
+ }
+
+ if (isSessionToBeSaved)
+ {
+ session.save();
+ if (nodeIsNotCheckedOut)
+ {
+ node.checkin();
+ session.save();
+ }
+ }
+
+
+ changeNodeACL(node, requestBody);
+
+ }
+ catch (PathNotFoundException e)
+ {
+ return Response.status(HTTPStatus.NOT_FOUND).entity(e.getMessage()).build();
+ }
+ catch (RepositoryException exc)
+ {
+ log.error(exc.getMessage(), exc);
+ return
Response.status(HTTPStatus.INTERNAL_ERROR).entity(exc.getMessage()).build();
+ }
+ catch (AccessControlException exc)
+ {
+ log.error(exc.getMessage(), exc);
+ return Response.status(HTTPStatus.FORBIDDEN).entity(exc.getMessage()).build();
+ }
+ catch (IllegalArgumentException exc)
+ {
+ log.error(exc.getMessage(), exc);
+ return
Response.status(HTTPStatus.BAD_REQUEST).entity(exc.getMessage()).build();
+ }
+ catch (Exception exc)
+ {
+ log.error(exc.getMessage(), exc);
+ return Response.status(HTTPStatus.BAD_REQUEST).build();
+ }
+
+ return Response.status(HTTPStatus.OK).build();
+ }
+
+ /**
+ * Changes JCR node ACL by addition or removal mentioned in {@link
HierarchicalProperty} requestBody permissions.
+ * @param node - node to change its ACL
+ * @param requestBody - tree like structure to contain ACL method request body
+ * @throws AccessControlException
+ * @throws RepositoryException
+ */
+ private void changeNodeACL(NodeImpl node, HierarchicalProperty requestBody) throws
AccessControlException,
+ RepositoryException
+ {
+ Map<String, String[]> permissionsToGrant = new HashMap<String,
String[]>();
+ Map<String, String[]> permissionsToDeny = new HashMap<String,
String[]>();
+
+ for (HierarchicalProperty ace : requestBody.getChildren())
+ {
+
+ HierarchicalProperty principalProperty = ace.getChild(ACLProperties.PRINCIPAL);
+ // each ace element must contain principal element
+ // TODO invert element is not implemented
+ // <!ELEMENT ace ((principal | invert), (grant|deny), protected?,
inherited?)>
+ if (principalProperty == null)
+ {
+ throw new IllegalArgumentException("Malformed ace element (seems that no
principal element specified)");
+ }
+
+ String principal;
+
+ if (principalProperty.getChild(ACLProperties.HREF) != null)
+ {
+ principal = principalProperty.getChild(ACLProperties.HREF).getValue();
+ }
+ else if (principalProperty.getChild(ACLProperties.ALL) != null)
+ {
+ principal = IdentityConstants.ANY;
+ }
+
+ // each principal must contain either href or all element
+ // TODO authenticated, unauthenticated, property, self are not implemented
+ // <!ELEMENT principal (href | all | authenticated | unauthenticated |
property | self)>
+ else
+ {
+ throw new IllegalArgumentException("Malformed principal element");
+ }
+
+ HierarchicalProperty denyProperty = ace.getChild(ACLProperties.DENY);
+ HierarchicalProperty grantProperty = ace.getChild(ACLProperties.GRANT);
+
+ // each ace element must contain at least one grant or deny property
+ // <!ELEMENT ace ((principal | invert), (grant|deny), protected?,
inherited?)>
+ if (denyProperty == null && grantProperty == null)
+ {
+ throw new IllegalArgumentException("Malformed ace element (seems that no
deny|grant element specified)");
+ }
+
+ if (denyProperty != null)
+ {
+ permissionsToDeny.put(principal, getPermissions(denyProperty));
+ }
+
+ if (grantProperty != null)
+ {
+ permissionsToGrant.put(principal, getPermissions(grantProperty));
+ }
+
+ // request must not grant and deny the same privilege in a single ace
+ //
http://www.webdav.org/specs/rfc3744.html#rfc.section.8.1.5
+ if (permissionsToDeny.size() != 0 && permissionsToGrant.size() != 0)
+ {
+ for (String denyPermission : permissionsToDeny.get(principal))
+ {
+ for (String grantPermission : permissionsToGrant.get(principal))
+ {
+ if (denyPermission.equals(grantPermission))
+ {
+ throw new IllegalArgumentException(
+ "Malformed ace element (seems that a client is trying to
grant and denay the same privilege in a single ace)");
+
+ }
+ }
+ }
+ }
+ }
+ if (permissionsToDeny.size() != 0)
+ {
+ for (Entry<String, String[]> entry : permissionsToDeny.entrySet())
+ {
+ for (String p : entry.getValue())
+ {
+ node.removePermission(entry.getKey(), p);
+ }
+ }
+ node.getSession().save();
+ }
+ if (permissionsToGrant.size() != 0)
+ {
+ for (Entry<String, String[]> entry : permissionsToGrant.entrySet())
+ {
+ node.setPermission(entry.getKey(), entry.getValue());
+ }
+ node.getSession().save();
+ }
+ }
+
+ /**
+ * Processes {@link HierarchicalProperty} instance, representing grant or deny
+ * element of ACL request body, to pull out permissions set represented as {@link
String} array.
+ * @param property
+ * @return String[] - permissions set
+ */
+ private String[] getPermissions(HierarchicalProperty property)
+ {
+ Set<String> permissionsToBeChanged = new HashSet<String>();
+
+ // grant|deny element must have at least one privilege element
+ // <!ELEMENT grant (privilege+)>
+ // <!ELEMENT deny (privilege+)>
+ if (property.getChildren().size() == 0)
+ {
+ throw new IllegalArgumentException("Malformed grant|deny element (seems
that no privilige is specified)");
+ }
+
+ for (HierarchicalProperty propertyRunner : property.getChildren())
+ {
+ HierarchicalProperty permissionProperty;
+
+ // obviously privilege must be single named
+ // <!ELEMENT privilege ANY>
+ if (ACLProperties.PRIVILEGE.equals(propertyRunner.getName()))
+ {
+ if (propertyRunner.getChildren().size() > 1)
+ {
+ throw new IllegalArgumentException(
+ "Malformed privilege name (element privilege must contain only one
element)");
+ }
+ permissionProperty = propertyRunner.getChild(0);
+ }
+ else
+ {
+ permissionProperty = propertyRunner;
+ }
+
+ if (ACLProperties.READ.equals(permissionProperty.getName()))
+ {
+ permissionsToBeChanged.add(PermissionType.READ);
+
+ }
+ else if (ACLProperties.WRITE.equals(permissionProperty.getName()))
+ {
+ permissionsToBeChanged.add(PermissionType.ADD_NODE);
+ permissionsToBeChanged.add(PermissionType.SET_PROPERTY);
+ permissionsToBeChanged.add(PermissionType.REMOVE);
+
+ }
+ else if (ACLProperties.ALL.equals(permissionProperty.getName()))
+ {
+ permissionsToBeChanged.add(PermissionType.READ);
+ permissionsToBeChanged.add(PermissionType.ADD_NODE);
+ permissionsToBeChanged.add(PermissionType.SET_PROPERTY);
+ permissionsToBeChanged.add(PermissionType.REMOVE);
+ }
+ // in case privilege with specified name is unsupported
+ // or simply incorrect privilege name
+ else
+ {
+ throw new IllegalArgumentException("Malformed privilege element
(unsupported privilege name)");
+ }
+ }
+ return permissionsToBeChanged.toArray(new String[0]);
+
+ }
+
+}
Added:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/acl/ACLProperties.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/acl/ACLProperties.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/acl/ACLProperties.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -0,0 +1,236 @@
+/**
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ *
+ */
+
+package org.exoplatform.services.jcr.webdav.command.acl;
+
+import org.exoplatform.common.util.HierarchicalProperty;
+import org.exoplatform.services.jcr.access.AccessControlEntry;
+import org.exoplatform.services.jcr.access.AccessControlList;
+import org.exoplatform.services.jcr.access.PermissionType;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.webdav.util.PropertyConstants;
+import org.exoplatform.services.security.IdentityConstants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.xml.namespace.QName;
+
+/**
+ * Created by The eXo Platform SAS.
+ * Utility class to simplify operations with ACL properties of JCR nodes
+ * for PROPFIND method.
+ *
+ * @author <a href="mailto:gavrikvetal@gmail.com">Vitaliy
Gulyy</a>
+ * @version $
+ */
+
+public class ACLProperties
+{
+ /**
+ * Defines the name of the element corresponding to a protected property that
specifies
+ * the list of access control entries.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl">...;.
+ */
+ public final static QName ACL = new QName("DAV:", "acl");
+
+ /**
+ * Defines the name of the element corresponding to a property that the set of
privileges
+ * to be either granted or denied to a single principal.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl">...;.
+ */
+ public final static QName ACE = new QName("DAV:", "ace");
+
+ /**
+ * Defines the name of the element corresponding to a property which identifies the
principal
+ * to which this ACE applies.
+ * More details can be found <a
href='http://www.webdav.org/specs/rfc3744.html#principals'>her...
+ * and <a
href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl">...;.
+ */
+ public final static QName PRINCIPAL = new QName("DAV:",
"principal");
+
+ /**
+ * Defines the name of the element corresponding to a property that can be either an
aggregate
+ * privilege that contains the entire set of privileges that can be applied to the
resource or
+ * an aggregate principal that contains the entire set of principals.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#PRIVILEGE_all"&g...;.
+ */
+ public final static QName ALL = new QName("DAV:", "all");
+
+ /**
+ * Defines the name of the element corresponding to a property which is used to
uniquely
+ * identify a principal.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_principal-UR...;.
+ */
+ public final static QName HREF = new QName("DAV:", "href");
+
+ /**
+ * Defines the name of the element containing privilege's name.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#privileges">h...;.
+ */
+ public final static QName PRIVILEGE = new QName("DAV:",
"privilege");
+
+ /**
+ * Defines the name of the element containing privileges to be granted.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#rfc.section.5.5.2&quo...;.
+ */
+ public final static QName GRANT = new QName("DAV:", "grant");
+
+ /**
+ * Defines the name of the element containing privileges to be denied.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#rfc.section.5.5.2&quo...;.
+ */
+ public final static QName DENY = new QName("DAV:", "deny");
+
+ /**
+ * Defines the name of the element corresponding to write privilege
+ * which in current implementation aggregate:
+ * ADD_NODE, SET_PROPERTY, REMOVE permissions.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#privileges">h...;.
+ */
+ public final static QName WRITE = new QName("DAV:", "write");
+
+ /**
+ * Defines the name of the element corresponding to read privilege
+ * which in current implementation aggregate:
+ * READ permission.
+ * More details can be found <a
href="http://www.webdav.org/specs/rfc3744.html#privileges">h...;.
+ */
+ public final static QName READ = new QName("DAV:", "read");
+
+ /**
+ * Gets {@link AccessControlList} and transform it to DAV:acl property view
+ * represented by a {@link HierarchicalProperty} instance.
+ * @param node - {@link NodeImpl} from which we are to get an ACL
+ * @return HierarchicalProperty - tree like structure corresponding to an DAV:acl
property
+ * @throws RepositoryException
+ */
+ public static HierarchicalProperty getACL(NodeImpl node) throws RepositoryException
+ {
+ HierarchicalProperty property = new HierarchicalProperty(ACL);
+
+ AccessControlList acl = node.getACL();
+
+ HashMap<String, List<String>> principals = new HashMap<String,
List<String>>();
+
+ List<AccessControlEntry> entryList = acl.getPermissionEntries();
+ for (AccessControlEntry entry : entryList)
+ {
+ String principal = entry.getIdentity();
+ String grant = entry.getPermission();
+
+ List<String> grantList = principals.get(principal);
+ if (grantList == null)
+ {
+ grantList = new ArrayList<String>();
+ principals.put(principal, grantList);
+ }
+
+ grantList.add(grant);
+ }
+
+ Iterator<String> principalIter = principals.keySet().iterator();
+ while (principalIter.hasNext())
+ {
+ HierarchicalProperty aceProperty = new HierarchicalProperty(ACE);
+
+ String curPrincipal = principalIter.next();
+
+ aceProperty.addChild(getPrincipalProperty(curPrincipal));
+
+ aceProperty.addChild(getGrantProperty(principals.get(curPrincipal)));
+
+ property.addChild(aceProperty);
+ }
+
+ return property;
+ }
+
+ /**
+ * Transform owner got from node's {@link AccessControlList}
+ * to tree like {@link HierarchicalProperty} instance to use in PROPFIND response body
+ * @param node
+ * @return {@link HierarchicalProperty} representation of node owner
+ * @throws RepositoryException
+ */
+ public static HierarchicalProperty getOwner(NodeImpl node) throws RepositoryException
+ {
+ HierarchicalProperty ownerProperty = new
HierarchicalProperty(PropertyConstants.OWNER);
+
+ HierarchicalProperty href = new HierarchicalProperty(new QName("DAV:",
"href"));
+ href.setValue(node.getACL().getOwner());
+
+ ownerProperty.addChild(href);
+
+ return ownerProperty;
+ }
+
+ // TODO support for DAV:supported-privilege-set property
+ // specified here:
http://www.webdav.org/specs/rfc3744.html#PROPERTY_supported-privilege-set
+ // TODO support for DAV:acl-restrictions property
+ // specified here:
http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl-restrictions
+ // TODO support for DAV:current-user-privilege-set property
+ // specified here:
http://www.webdav.org/specs/rfc3744.html#PROPERTY_current-user-privilege-set
+
+ private static HierarchicalProperty getPrincipalProperty(String principal)
+ {
+ HierarchicalProperty principalProperty = new HierarchicalProperty(PRINCIPAL);
+
+ if (IdentityConstants.ANY.equals(principal))
+ {
+ HierarchicalProperty all = new HierarchicalProperty(ALL);
+ principalProperty.addChild(all);
+ }
+ else
+ {
+ HierarchicalProperty href = new HierarchicalProperty(HREF);
+ href.setValue(principal);
+ principalProperty.addChild(href);
+ }
+
+ return principalProperty;
+ }
+
+ private static HierarchicalProperty getGrantProperty(List<String> grantList)
+ {
+ HierarchicalProperty grant = new HierarchicalProperty(GRANT);
+
+ if (grantList.contains(PermissionType.ADD_NODE) ||
grantList.contains(PermissionType.SET_PROPERTY)
+ || grantList.contains(PermissionType.REMOVE))
+ {
+ HierarchicalProperty privilege = new HierarchicalProperty(PRIVILEGE);
+ privilege.addChild(new HierarchicalProperty(WRITE));
+ grant.addChild(privilege);
+ }
+
+ if (grantList.contains(PermissionType.READ))
+ {
+ HierarchicalProperty privilege = new HierarchicalProperty(PRIVILEGE);
+ privilege.addChild(new HierarchicalProperty(READ));
+ grant.addChild(privilege);
+ }
+
+ return grant;
+ }
+
+}
Modified:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -20,6 +20,8 @@
import org.exoplatform.common.util.HierarchicalProperty;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.webdav.command.acl.ACLProperties;
import org.exoplatform.services.jcr.webdav.util.TextUtil;
import org.exoplatform.services.jcr.webdav.xml.WebDavNamespaceContext;
import org.exoplatform.services.log.ExoLogger;
@@ -311,6 +313,14 @@
throw new PathNotFoundException();
}
+ else if (name.equals(ACLProperties.ACL))
+ {
+ return ACLProperties.getACL((NodeImpl)node);
+ }
+ else if (name.equals(OWNER))
+ {
+ return ACLProperties.getOwner((NodeImpl)node);
+ }
else
{
Modified:
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/FileResource.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/FileResource.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/FileResource.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -19,7 +19,9 @@
package org.exoplatform.services.jcr.webdav.resource;
import org.exoplatform.common.util.HierarchicalProperty;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.webdav.WebDavConst;
+import org.exoplatform.services.jcr.webdav.command.acl.ACLProperties;
import org.exoplatform.services.jcr.webdav.xml.WebDavNamespaceContext;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -292,6 +294,14 @@
{
return supportedMethodSet();
}
+ else if (name.equals(ACLProperties.ACL))
+ {
+ return ACLProperties.getACL((NodeImpl)node);
+ }
+ else if (name.equals(OWNER))
+ {
+ return ACLProperties.getOwner((NodeImpl)node);
+ }
else
{
try
Modified:
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/WebDavConstants.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/WebDavConstants.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/WebDavConstants.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -208,6 +208,8 @@
public static final String ORDERPATCH = "ORDERPATCH";
+ public static final String ACL = "ACL";
+
}
}
Added:
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestAclCommand.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestAclCommand.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestAclCommand.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -0,0 +1,780 @@
+/**
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ *
+ */
+
+package org.exoplatform.services.jcr.webdav.command;
+
+import org.exoplatform.common.http.HTTPStatus;
+import org.exoplatform.services.jcr.access.AccessControlEntry;
+import org.exoplatform.services.jcr.access.PermissionType;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.webdav.BaseStandaloneTest;
+import org.exoplatform.services.jcr.webdav.WebDavConstants;
+import org.exoplatform.services.rest.impl.ContainerResponse;
+import org.exoplatform.services.rest.impl.EnvironmentContext;
+import org.exoplatform.services.rest.impl.MultivaluedMapImpl;
+import org.exoplatform.services.rest.impl.RequestHandlerImpl;
+import org.exoplatform.services.rest.tools.DummySecurityContext;
+import org.exoplatform.services.rest.tools.ResourceLauncher;
+import org.exoplatform.services.security.IdentityConstants;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+
+
+/**
+ *
+ * Created by The eXo Platform SAS .
+ *
+ * @author <a href="mailto:gavrikvetal@gmail.com">Vitaliy
Gulyy</a>
+ * @version $
+ */
+
+public class TestAclCommand extends BaseStandaloneTest
+{
+
+ private final String USER_ONE = "Oksana";
+
+ private final String USER_TWO = "Anya";
+
+ private final String USER_ROOT = "root";
+
+ private final String BASE_URI = "http://localhost";
+
+ private final String TEST_NODE_NAME = "test_node" +
System.currentTimeMillis();
+
+ /**
+ * Here we check for correct addition of privileges to users,
+ * besides, we check for correct addition of mix:pribilegeable.
+ * @throws Exception
+ */
+ public void testSetACLForTwoUsersOnNonPrivilegeableResource() throws Exception
+ {
+
+
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ session.save();
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:href>" + USER_ONE + "</D:href>" +
"</D:principal>" + "<D:grant>"
+ + "<D:privilege><D:write/></D:privilege>" +
"</D:grant>" + "</D:ace>" + "<D:ace>" +
"<D:principal>"
+ + "<D:href>" + USER_TWO + "</D:href>" +
"</D:principal>" + "<D:grant>" +
"<D:write/>" + "</D:grant>"
+ + "</D:ace>" + "</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.OK, response.getStatus());
+
+ session.refresh(false);
+ testNode = (NodeImpl)root.getNode(TEST_NODE_NAME);
+ testNode.setPermission(USER_ROOT, new String[]{"read",
"add_node", "set_property", "remove"});
+ testNode.removePermission(IdentityConstants.ANY);
+ session.save();
+
+ checkPermissionSet(testNode, USER_ONE, PermissionType.ADD_NODE);
+ checkPermissionSet(testNode, USER_ONE, PermissionType.SET_PROPERTY);
+ checkPermissionSet(testNode, USER_ONE, PermissionType.REMOVE);
+
+ checkPermissionSet(testNode, USER_TWO, PermissionType.ADD_NODE);
+ checkPermissionSet(testNode, USER_TWO, PermissionType.SET_PROPERTY);
+ checkPermissionSet(testNode, USER_TWO, PermissionType.REMOVE);
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct write permission removal from
+ * the mix:versionable and exo:privelegeable node. We add permissions manually
+ * and then remove them via ACL method. After this operation they are expected
+ * to be removed from node ACL
+ * @throws Exception
+ */
+ public void testDenyPermissionOnPrivilegeableResource() throws Exception
+ {
+
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ testNode.addMixin("mix:versionable");
+ testNode.addMixin("exo:privilegeable");
+ testNode.setPermission(USER_ROOT, new String[]{"read",
"add_node", "set_property", "remove"});
+ testNode.setPermission(USER_ONE, new String[]{"add_node",
"set_property", "remove"});
+ testNode.removePermission(IdentityConstants.ANY);
+ session.save();
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:href>" + USER_ONE + "</D:href>" +
"</D:principal>" + "<D:deny>" +
"<D:privilege><D:write/></D:privilege>"
+ + "</D:deny>" + "</D:ace>" +
"</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.OK, response.getStatus());
+
+ session.refresh(false);
+ testNode = (NodeImpl)root.getNode(TEST_NODE_NAME);
+
+ checkPermissionRemoved(testNode, USER_ONE, PermissionType.ADD_NODE);
+ checkPermissionRemoved(testNode, USER_ONE, PermissionType.SET_PROPERTY);
+ checkPermissionRemoved(testNode, USER_ONE, PermissionType.REMOVE);
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct processing of knowingly malformed request.
+ * We are trying to grant and deny the same privilege and expect
+ * BAD_REQUEST status.
+ * @throws Exception
+ */
+ public void testDenyAndGrantInASingleACE() throws Exception
+ {
+
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ testNode.addMixin("mix:versionable");
+ testNode.addMixin("exo:privilegeable");
+ testNode.setPermission(USER_ROOT, new String[]{"read",
"add_node", "set_property", "remove"});
+ testNode.removePermission(IdentityConstants.ANY);
+ session.save();
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:href>" + USER_ONE + "</D:href>" +
"</D:principal>" + "<D:deny>"
+ + "<D:privilege><D:write/></D:privilege>" +
"</D:deny>" + "<D:grant>"
+ + "<D:privilege><D:write/></D:privilege>" +
"</D:grant>" + "</D:ace>" + "</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we test for correct setting all permissions for ANY user.
+ * We create a node without all permissions for ANY user and expect
+ * them to appear after receiving a response.
+ * @throws Exception
+ */
+ public void testSetAllPermissionsForAllUsersOnPrivilegeableResource() throws
Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ session.save();
+
+ Map<String, String[]> defaultPermissions = new HashMap<String,
String[]>();
+ String[] initPermissions =
+ new String[]{PermissionType.ADD_NODE, PermissionType.READ,
PermissionType.SET_PROPERTY};
+ defaultPermissions.put(USER_TWO, initPermissions);
+ testNode.setPermissions(defaultPermissions);
+ session.save();
+
+ System.out.println("Node before: " + testNode);
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant>" +
"<D:privilege><D:all/></D:privilege>" +
"</D:grant>"
+ + "</D:ace>" + "</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI,
+ headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.OK, response.getStatus());
+
+ session.refresh(false);
+ testNode = (NodeImpl)root.getNode(TEST_NODE_NAME);
+
+ System.out.println("Node after: " + testNode);
+
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.ADD_NODE);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.SET_PROPERTY);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.REMOVE);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.READ);
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct processing of knowingly malformed grant element
+ * in ACL request body.
+ * @throws Exception
+ */
+ public void testWrongGrantElementAceElementInAclBody() throws Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ testNode.setPermission(USER_ROOT, new String[]{"read",
"add_node", "set_property", "remove"});
+ testNode.removePermission(IdentityConstants.ANY);
+ session.save();
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant>" + "<D:privilege><D:read /><D:write
/></D:privilege>"
+ + "</D:grant>" + "</D:ace>" +
"</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant></D:grant>" + "</D:ace>" +
"</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant><D:privilege></D:privilege></D:grant>" +
"</D:ace>"
+ + "</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct processing of knowingly malformed ace element
+ * in ACL request body.
+ * @throws Exception
+ */
+ public void testWrongAceElementInAclBody() throws Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ session.save();
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ session.save();
+
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "</D:ace>" + "</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI,
+ headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:grant>" +
"<D:privilege><D:read /><D:write /></D:privilege>"
+ + "</D:grant>" + "</D:ace>" +
"</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI,
+ headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"</D:ace>" + "</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI,
+ headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct processing of knowingly malformed principal element
+ * in ACL request body.
+ * @throws Exception
+ */
+ public void testWrongPrincipalElementInAclBody() throws Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ session.save();
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ session.save();
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "</D:principal>" + "<D:grant>" +
"<D:privilege><D:read /><D:write /></D:privilege>" +
"</D:grant>"
+ + "</D:ace>" + "</D:acl>";
+
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant>" + "<D:privilege><D:read /><D:write
/></D:privilege>"
+ + "</D:grant>" + "</D:ace>" +
"</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:href>" + "</D:href>" +
"</D:principal>" + "<D:grant>"
+ + "<D:privilege><D:read /><D:write
/></D:privilege>" + "</D:grant>" +
"</D:ace>" + "</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:href>" + USER_ONE + "</D:href>" +
"<href>" + USER_TWO + "</href>" +
"</D:principal>" + "<D:grant>"
+ + "<D:privilege><D:read /><D:write
/></D:privilege>" + "</D:grant>" +
"</D:ace>" + "</D:acl>";
+
+ response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.BAD_REQUEST, response.getStatus());
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct ACL setting for mix:versionable, exo:owneable,
exo:privilegeable,
+ * checked out node. Node is manually set to have any permission for user
"root". Node expected
+ * to have any permission for any user
+ * after ACL method completion.
+ * @throws Exception
+ */
+ public void testSetAclForVersionableOwneablePrivilegeableCheckedOutNode() throws
Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ session.save();
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ testNode.addMixin("mix:versionable");
+ testNode.setPermission(USER_ROOT, new String[]{"read",
"add_node", "set_property", "remove"});
+ testNode.removePermission(IdentityConstants.ANY);
+ session.save();
+
+ //let us make node version
+ testNode.checkin();
+ testNode.checkout();
+
+ session.save();
+
+ //now let us try to grant all permissions for any user
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant>" +
"<D:privilege><D:all/></D:privilege>" +
"</D:grant>"
+ + "</D:ace>" + "</D:acl>";
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.OK, response.getStatus());
+
+ session.refresh(false);
+ testNode = (NodeImpl)root.getNode(TEST_NODE_NAME);
+
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.ADD_NODE);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.SET_PROPERTY);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.REMOVE);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.READ);
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct ACL setting for mix:versionable, checkedin node. Node is
manually set
+ * to have any permission for user USER_ONE. Node expected to get checked out, added
corresponding mixins,
+ * and to set any permission for any user.
+ * after ACL method completion.
+ * @throws Exception
+ */
+ public void testSetAclForVersionableCheckedInNode() throws Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ session.save();
+ testNode.addMixin("mix:versionable");
+ session.save();
+
+ //let us make node version
+ testNode.checkin();
+ testNode.checkout();
+ testNode.checkin();
+ session.save();
+
+ //now let us try to grant all permissions for user USER_ONE
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:href>" + USER_ONE + "</D:href>" +
"</D:principal>" + "<D:grant>"
+ + "<D:privilege><D:all/></D:privilege>" +
"</D:grant>"
+ + "</D:ace>" + "</D:acl>";
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.OK, response.getStatus());
+
+ session.refresh(false);
+ testNode = (NodeImpl)root.getNode(TEST_NODE_NAME);
+
+ checkPermissionSet(testNode, USER_ONE, PermissionType.ADD_NODE);
+ checkPermissionSet(testNode, USER_ONE, PermissionType.SET_PROPERTY);
+ checkPermissionSet(testNode, USER_ONE, PermissionType.REMOVE);
+ checkPermissionSet(testNode, USER_ONE, PermissionType.READ);
+
+ testNode.remove();
+ session.save();
+ }
+
+ /**
+ * Here we check for correct ACL setting for mix:versionable, exo:owneable,
exo:privilegeable,
+ * checked in node. Node is manually set to have any permission for user
"root". Node expected
+ * to have any permission for any user
+ * after ACL method completion.
+ * @throws Exception
+ */
+ public void testSetAclForVersionableOwneablePrivilegeableCheckedInNode() throws
Exception
+ {
+ NodeImpl testNode = (NodeImpl)root.addNode(TEST_NODE_NAME, "nt:folder");
+ session.save();
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ testNode.addMixin("mix:versionable");
+ testNode.setPermission(USER_ROOT, new String[]{"read",
"add_node", "set_property", "remove"});
+ testNode.removePermission(IdentityConstants.ANY);
+ session.save();
+
+ //let us make node version
+ testNode.checkin();
+ testNode.checkout();
+ testNode.checkin();
+
+ session.save();
+
+ //now let us try to grant all permissions for any user
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:acl xmlns:D=\"DAV:\">" +
"<D:ace>" + "<D:principal>"
+ + "<D:all />" + "</D:principal>" +
"<D:grant>" +
"<D:privilege><D:all/></D:privilege>" +
"</D:grant>"
+ + "</D:ace>" + "</D:acl>";
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+ ContainerResponse response =
+ launcher.service(WebDavConstants.WebDAVMethods.ACL, getPathWS() +
testNode.getPath(), BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.OK, response.getStatus());
+
+ session.refresh(false);
+ testNode = (NodeImpl)root.getNode(TEST_NODE_NAME);
+
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.ADD_NODE);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.SET_PROPERTY);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.REMOVE);
+ checkPermissionSet(testNode, IdentityConstants.ANY, PermissionType.READ);
+
+ testNode.remove();
+ session.save();
+ }
+
+ private void checkPermissionSet(NodeImpl node, String identity, String permission)
throws RepositoryException
+ {
+ for (AccessControlEntry entry : node.getACL().getPermissionEntries())
+ {
+ if (entry.getIdentity().equals(identity) &&
entry.getPermission().equals(permission))
+ {
+ return;
+ }
+ }
+
+ fail();
+ }
+
+ private void checkPermissionRemoved(NodeImpl node, String identity, String permission)
throws RepositoryException
+ {
+ for (AccessControlEntry entry : node.getACL().getPermissionEntries())
+ {
+ if (entry.getIdentity().equals(identity) &&
entry.getPermission().equals(permission))
+ {
+ fail();
+ }
+ }
+ }
+
+ @Override
+ protected String getRepositoryName()
+ {
+ return null;
+ }
+
+}
Modified:
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -20,22 +20,37 @@
import org.exoplatform.common.http.HTTPStatus;
import org.exoplatform.common.util.HierarchicalProperty;
+import org.exoplatform.services.jcr.access.PermissionType;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.webdav.BaseStandaloneTest;
import org.exoplatform.services.jcr.webdav.Depth;
import org.exoplatform.services.jcr.webdav.WebDavConstants.WebDAVMethods;
+import org.exoplatform.services.jcr.webdav.command.acl.ACLProperties;
import org.exoplatform.services.jcr.webdav.command.propfind.PropFindResponseEntity;
import org.exoplatform.services.jcr.webdav.utils.TestUtils;
+import org.exoplatform.services.rest.ext.provider.HierarchicalPropertyEntityProvider;
import org.exoplatform.services.rest.impl.ContainerResponse;
+import org.exoplatform.services.rest.impl.EnvironmentContext;
import org.exoplatform.services.rest.impl.MultivaluedMapImpl;
+import org.exoplatform.services.rest.impl.RequestHandlerImpl;
+import org.exoplatform.services.rest.tools.DummySecurityContext;
+import org.exoplatform.services.rest.tools.ResourceLauncher;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import javax.jcr.Node;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
-
+import javax.ws.rs.core.SecurityContext;
+import javax.xml.namespace.QName;
/**
* Created by The eXo Platform SAS Author : Dmytro Katayev
* work.visor.ck(a)gmail.com Aug 13, 2008
@@ -51,6 +66,12 @@
private final String nt_webdave_file = "webdav:file";
+ private final String USER_ROOT = "root";
+
+ private final String USER_JOHN = "john";
+
+ private final String BASE_URI = "http://localhost";
+
private String propFindXML =
"<?xml version=\"1.0\" encoding=\"utf-8\"
?><D:propfind xmlns:D=\"DAV:\">"
+ "<D:prop
xmlns:webdav=\"http://www.exoplatform.org/jcr/webdav\">"
@@ -239,7 +260,178 @@
assertTrue(find.contains(authorValue));
}
+ /**
+ * Here we check for correct response for PROPFIND request.
+ * Response should not only contain an acl element with its properties
+ * (ace, principle, privelege, grant, etc.) but also be correctly composed and
contain
+ * ACL information about user root.
+ * @throws Exception
+ */
+ public void testPropfindPermissionsOnRoot() throws Exception
+ {
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "0");
+ EnvironmentContext ctx = new EnvironmentContext();
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:propfind xmlns:D=\"DAV:\">" +
"<D:prop>" + "<D:owner/>"
+ + "<D:acl/>" + "</D:prop>" +
"</D:propfind>";
+
+ ContainerResponse response =
+ launcher.service(WebDAVMethods.PROPFIND, getPathWS(), BASE_URI, headers,
request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.MULTISTATUS, response.getStatus());
+ assertNotNull(response.getEntity());
+
+ HierarchicalPropertyEntityProvider provider = new
HierarchicalPropertyEntityProvider();
+ InputStream inputStream = TestUtils.getResponseAsStream(response);
+ HierarchicalProperty multistatus = provider.readFrom(null, null, null, null, null,
inputStream);
+
+ assertEquals(new QName("DAV:", "multistatus"),
multistatus.getName());
+ assertEquals(1, multistatus.getChildren().size());
+
+ HierarchicalProperty resourceProp = multistatus.getChildren().get(0);
+
+ HierarchicalProperty resourceHref = resourceProp.getChild(new
QName("DAV:", "href"));
+ assertNotNull(resourceHref);
+ assertEquals(BASE_URI + getPathWS() + "/", resourceHref.getValue());
+
+ HierarchicalProperty propstatProp = resourceProp.getChild(new
QName("DAV:", "propstat"));
+ HierarchicalProperty propProp = propstatProp.getChild(new QName("DAV:",
"prop"));
+
+ HierarchicalProperty ownerProp = propProp.getChild(new QName("DAV:",
"owner"));
+ HierarchicalProperty ownerHrefProp = ownerProp.getChild(new QName("DAV:",
"href"));
+
+ assertEquals("__system", ownerHrefProp.getValue());
+
+ HierarchicalProperty aclProp = propProp.getChild(ACLProperties.ACL);
+ assertEquals(1, aclProp.getChildren().size());
+
+ HierarchicalProperty aceProp = aclProp.getChild(ACLProperties.ACE);
+ assertEquals(2, aceProp.getChildren().size());
+
+ HierarchicalProperty principalProp = aceProp.getChild(ACLProperties.PRINCIPAL);
+ assertEquals(1, principalProp.getChildren().size());
+
+ HierarchicalProperty allProp = principalProp.getChild(ACLProperties.ALL);
+ assertNotNull(allProp);
+
+ HierarchicalProperty grantProp = aceProp.getChild(ACLProperties.GRANT);
+ assertEquals(2, grantProp.getChildren().size());
+
+ HierarchicalProperty writeProp =
grantProp.getChild(0).getChild(ACLProperties.WRITE);
+ assertNotNull(writeProp);
+ HierarchicalProperty readProp =
grantProp.getChild(1).getChild(ACLProperties.READ);
+ assertNotNull(readProp);
+ }
+
+ /**
+ * Here we check for correct response for PROPFIND request.
+ * Response should contain all available acl information on current node, i.e.
+ * ace for user "__system", "john" etc.
+ * @throws Exception
+ */
+ public void testPropfindPropOwnerAndAclOnNode() throws Exception
+ {
+
+ NodeImpl testNode = (NodeImpl)root.addNode("test_acl_property",
"nt:folder");
+ testNode.addMixin("exo:owneable");
+ testNode.addMixin("exo:privilegeable");
+ session.save();
+
+ Map<String, String[]> permissions = new HashMap<String, String[]>();
+
+ String userName = USER_JOHN;
+ permissions.put(userName, PermissionType.ALL);
+
+ testNode.setPermissions(permissions);
+ testNode.getSession().save();
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.putSingle("Depth", "1");
+ headers.putSingle(HttpHeaders.CONTENT_TYPE, "text/xml;
charset=\"utf-8\"");
+
+ EnvironmentContext ctx = new EnvironmentContext();
+
+ Set<String> adminRoles = new HashSet<String>();
+ adminRoles.add("administrators");
+
+ DummySecurityContext adminSecurityContext = new DummySecurityContext(new
Principal()
+ {
+ public String getName()
+ {
+ return USER_ROOT;
+ }
+ }, adminRoles);
+
+ ctx.put(SecurityContext.class, adminSecurityContext);
+
+ RequestHandlerImpl handler =
(RequestHandlerImpl)container.getComponentInstanceOfType(RequestHandlerImpl.class);
+ ResourceLauncher launcher = new ResourceLauncher(handler);
+
+ String request =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"
?>" + "<D:propfind xmlns:D=\"DAV:\">" +
"<D:prop>" + "<D:owner/>"
+ + "<D:acl/>" + "</D:prop>" +
"</D:propfind>";
+
+ ContainerResponse cres =
+ launcher.service(WebDAVMethods.PROPFIND, getPathWS() + testNode.getPath(),
BASE_URI, headers,
+ request.getBytes(), null, ctx);
+
+ assertEquals(HTTPStatus.MULTISTATUS, cres.getStatus());
+
+ HierarchicalPropertyEntityProvider provider = new
HierarchicalPropertyEntityProvider();
+ InputStream inputStream = TestUtils.getResponseAsStream(cres);
+ HierarchicalProperty multistatus = provider.readFrom(null, null, null, null, null,
inputStream);
+
+ assertEquals(new QName("DAV:", "multistatus"),
multistatus.getName());
+ assertEquals(1, multistatus.getChildren().size());
+
+ HierarchicalProperty resourceProp = multistatus.getChildren().get(0);
+
+ HierarchicalProperty resourceHref = resourceProp.getChild(new
QName("DAV:", "href"));
+ assertNotNull(resourceHref);
+ assertEquals(BASE_URI + getPathWS() + testNode.getPath() + "/",
resourceHref.getValue());
+
+ HierarchicalProperty propstatProp = resourceProp.getChild(new
QName("DAV:", "propstat"));
+ HierarchicalProperty propProp = propstatProp.getChild(new QName("DAV:",
"prop"));
+
+ HierarchicalProperty aclProp = propProp.getChild(ACLProperties.ACL);
+ assertEquals(1, aclProp.getChildren().size());
+
+ HierarchicalProperty aceProp = aclProp.getChild(ACLProperties.ACE);
+ assertEquals(2, aceProp.getChildren().size());
+
+ HierarchicalProperty principalProp = aceProp.getChild(ACLProperties.PRINCIPAL);
+ assertEquals(1, principalProp.getChildren().size());
+
+ assertEquals(userName, principalProp.getChildren().get(0).getValue());
+
+ HierarchicalProperty grantProp = aceProp.getChild(ACLProperties.GRANT);
+ assertEquals(2, grantProp.getChildren().size());
+
+ HierarchicalProperty writeProp =
grantProp.getChild(0).getChild(ACLProperties.WRITE);
+ assertNotNull(writeProp);
+ HierarchicalProperty readProp =
grantProp.getChild(1).getChild(ACLProperties.READ);
+ assertNotNull(readProp);
+
+ }
+
@Override
protected String getRepositoryName()
{
Modified:
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/utils/TestUtils.java
===================================================================
---
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/utils/TestUtils.java 2011-01-21
07:52:30 UTC (rev 3824)
+++
jcr/trunk/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/utils/TestUtils.java 2011-01-21
08:01:45 UTC (rev 3825)
@@ -21,10 +21,13 @@
import org.exoplatform.common.http.client.HTTPConnection;
import org.exoplatform.services.jcr.webdav.WebDavConst;
import org.exoplatform.services.jcr.webdav.WebDavConstants.WebDav;
+import org.exoplatform.services.jcr.webdav.command.propfind.PropFindResponseEntity;
import org.exoplatform.services.jcr.webdav.util.TextUtil;
+import org.exoplatform.services.rest.impl.ContainerResponse;
import org.w3c.dom.Document;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -227,4 +230,16 @@
return content.getMixinNodeTypes();
}
+ public static InputStream getResponseAsStream(ContainerResponse response) throws
IOException
+ {
+ if (response.getEntity() instanceof PropFindResponseEntity)
+ {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ((PropFindResponseEntity)response.getEntity()).write(outputStream);
+ return new ByteArrayInputStream(outputStream.toByteArray());
+ }
+
+ return null;
+ }
+
}