From 4fd84a959517f135cc5b217138e2281b0aa7ba31 Mon Sep 17 00:00:00 2001 From: David Caruana Date: Fri, 13 Jan 2006 15:22:15 +0000 Subject: [PATCH] Import permissions and permission inheritance. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2108 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/core-services-context.xml | 3 + .../alfresco/repo/importer/ImportNode.java | 12 ++ .../repo/importer/ImporterBootstrap.java | 13 +- .../repo/importer/ImporterComponent.java | 59 ++++++-- .../repo/importer/ImporterComponentTest.java | 6 + .../repo/importer/view/NodeContext.java | 95 ++++++++++++ .../repo/importer/view/ViewParser.java | 136 +++++++++++++++++- .../service/cmr/view/ImporterProgress.java | 9 ++ source/java/org/alfresco/tools/Import.java | 8 ++ 9 files changed, 331 insertions(+), 10 deletions(-) diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index 2a5bcbf55d..42692b4efe 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -658,6 +658,9 @@ + + + diff --git a/source/java/org/alfresco/repo/importer/ImportNode.java b/source/java/org/alfresco/repo/importer/ImportNode.java index a5c65b5c39..01e671dcf4 100644 --- a/source/java/org/alfresco/repo/importer/ImportNode.java +++ b/source/java/org/alfresco/repo/importer/ImportNode.java @@ -17,12 +17,14 @@ package org.alfresco.repo.importer; import java.io.Serializable; +import java.util.List; import java.util.Map; import java.util.Set; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.namespace.QName; @@ -78,4 +80,14 @@ public interface ImportNode */ public Set getNodeAspects(); + /** + * @return true => the node inherits permissions from its parent + */ + public boolean getInheritPermissions(); + + /** + * @return the permissions applied to this node + */ + public List getAccessControlEntries(); + } diff --git a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java index adc0f1738d..78eec9c2e9 100644 --- a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java +++ b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java @@ -36,6 +36,7 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.view.ImporterBinding; import org.alfresco.service.cmr.view.ImporterException; import org.alfresco.service.cmr.view.ImporterProgress; @@ -477,6 +478,17 @@ public class ImporterBootstrap logger.debug("Property " + property + " set to value " + value + " on node " + nodeRef); } + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.ImporterProgress#permissionSet(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.security.AccessPermission) + */ + public void permissionSet(NodeRef nodeRef, AccessPermission permission) + { + if (logger.isDebugEnabled()) + logger.debug("Permission " + permission.getPermission() + " set on node " + nodeRef + " (authority=" + permission.getAuthority() + + ", accessStatus=" + permission.getAccessStatus() + ")"); + } + /* (non-Javadoc) * @see org.alfresco.repo.importer.Progress#aspectAdded(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) */ @@ -485,7 +497,6 @@ public class ImporterBootstrap if (logger.isDebugEnabled()) logger.debug("Added aspect " + aspect + " to node " + nodeRef); } - } /** diff --git a/source/java/org/alfresco/repo/importer/ImporterComponent.java b/source/java/org/alfresco/repo/importer/ImporterComponent.java index a0d873e818..eefa2a056f 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponent.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponent.java @@ -51,6 +51,9 @@ import org.alfresco.service.cmr.rule.RuleService; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.view.ImportPackageHandler; import org.alfresco.service.cmr.view.ImporterBinding; import org.alfresco.service.cmr.view.ImporterException; @@ -88,6 +91,7 @@ public class ImporterComponent private SearchService searchService; private ContentService contentService; private RuleService ruleService; + private PermissionService permissionService; // binding markers private static final String START_BINDING_MARKER = "${"; @@ -159,6 +163,15 @@ public class ImporterComponent { this.ruleService = ruleService; } + + /** + * @param permissionService permissionService + */ + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ImporterService#importView(java.io.InputStreamReader, org.alfresco.service.cmr.view.Location, java.util.Properties, org.alfresco.service.cmr.view.ImporterProgress) @@ -875,6 +888,23 @@ public class ImporterComponent } } } + + /** + * Helper to report permission set progress + * + * @param nodeRef + * @param permissions + */ + private void reportPermissionSet(NodeRef nodeRef, List permissions) + { + if (progress != null) + { + for (AccessPermission permission : permissions) + { + progress.permissionSet(nodeRef, permission); + } + } + } /** * Import strategy where imported nodes are always created regardless of whether a @@ -950,24 +980,37 @@ public class ImporterComponent // Create Node ChildAssociationRef assocRef = nodeService.createNode(parentRef, assocType, childQName, nodeType.getName(), initialProperties); + NodeRef nodeRef = assocRef.getChildRef(); + + // Apply permissions + boolean inheritPermissions = node.getInheritPermissions(); + if (!inheritPermissions) + { + permissionService.setInheritParentPermissions(nodeRef, false); + } + List permissions = node.getAccessControlEntries(); + for (AccessPermission permission : permissions) + { + permissionService.setPermission(nodeRef, permission.getAuthority(), permission.getPermission(), permission.getAccessStatus().equals(AccessStatus.ALLOWED)); + } + + // Disable behaviour for the node until the complete node (and its children have been imported) for (QName disabledBehaviour : disabledBehaviours) { behaviourFilter.enableBehaviour(disabledBehaviour); } - - // Report creation - NodeRef nodeRef = assocRef.getChildRef(); - reportNodeCreated(assocRef); - reportPropertySet(nodeRef, initialProperties); - - // Disable behaviour for the node until the complete node (and its children have been imported) for (QName disabledBehaviour : disabledBehaviours) { behaviourFilter.disableBehaviour(nodeRef, disabledBehaviour); } // TODO: Replace this with appropriate rule/action import handling ruleService.disableRules(nodeRef); - + + // Report creation + reportNodeCreated(assocRef); + reportPropertySet(nodeRef, initialProperties); + reportPermissionSet(nodeRef, permissions); + // return newly created node reference return nodeRef; } diff --git a/source/java/org/alfresco/repo/importer/ImporterComponentTest.java b/source/java/org/alfresco/repo/importer/ImporterComponentTest.java index 0091ac0a2f..619d626c1a 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponentTest.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponentTest.java @@ -25,6 +25,7 @@ import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.view.ImporterProgress; import org.alfresco.service.cmr.view.ImporterService; import org.alfresco.service.cmr.view.Location; @@ -111,6 +112,11 @@ public class ImporterComponentTest extends BaseSpringTest { System.out.println("TestProgress: added aspect " + aspect + " to node "); } + + public void permissionSet(NodeRef nodeRef, AccessPermission permission) + { + System.out.println("TestProgress: added permission " + permission.getPermission() + " to node "); + } } diff --git a/source/java/org/alfresco/repo/importer/view/NodeContext.java b/source/java/org/alfresco/repo/importer/view/NodeContext.java index 2ab5abf71f..37ce1100e8 100644 --- a/source/java/org/alfresco/repo/importer/view/NodeContext.java +++ b/source/java/org/alfresco/repo/importer/view/NodeContext.java @@ -35,6 +35,9 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.namespace.QName; @@ -57,6 +60,10 @@ public class NodeContext extends ElementContext private Map nodeProperties = new HashMap(); private Map propertyDatatypes = new HashMap(); + // permissions + private boolean inherit = true; + private List accessControlEntries = new ArrayList(); + /** * Construct @@ -148,6 +155,22 @@ public class NodeContext extends ElementContext this.childName = childName; } + /* + * @param inherit determines if node inherits permissions from parent + */ + public void setInheritPermissions(boolean inherit) + { + this.inherit = inherit; + } + + /** + * @return true => node inherits permissions from parent + */ + public boolean getInheritPermissions() + { + return this.inherit; + } + /** * Adds a collection property to the node * @@ -272,6 +295,32 @@ public class NodeContext extends ElementContext return nodeAspects.keySet(); } + /** + * Adds an Access Control Entry + * + * @param accessStatus + * @param authority + * @param permission + */ + public void addAccessControlEntry(AccessStatus accessStatus, String authority, String permission) + { + ACE ace = new ACE(); + ace.accessStatus = accessStatus; + ace.authority = authority; + ace.permission = permission; + accessControlEntries.add(ace); + } + + /** + * Gets the Access Control Entries + * + * @return access control entries + */ + public List getAccessControlEntries() + { + return accessControlEntries; + } + /** * Determine the type of definition (aspect, property, association) from the * specified name @@ -377,5 +426,51 @@ public class NodeContext extends ElementContext return "NodeContext[childName=" + getChildName() + ",type=" + (typeDef == null ? "null" : typeDef.getName()) + ",nodeRef=" + nodeRef + ",aspects=" + nodeAspects.values() + ",parentContext=" + parentContext.toString() + "]"; } + + /** + * Access Control Entry + */ + private class ACE implements AccessPermission + { + private AccessStatus accessStatus; + private String authority; + private String permission; + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.security.AccessPermission#getPermission() + */ + public String getPermission() + { + return permission; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.security.AccessPermission#getAccessStatus() + */ + public AccessStatus getAccessStatus() + { + return accessStatus; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.security.AccessPermission#getAuthority() + */ + public String getAuthority() + { + return authority; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.security.AccessPermission#getAuthorityType() + */ + public AuthorityType getAuthorityType() + { + return null; + } + } } diff --git a/source/java/org/alfresco/repo/importer/view/ViewParser.java b/source/java/org/alfresco/repo/importer/view/ViewParser.java index d9b1eaa64f..4da7c2072d 100644 --- a/source/java/org/alfresco/repo/importer/view/ViewParser.java +++ b/source/java/org/alfresco/repo/importer/view/ViewParser.java @@ -29,6 +29,7 @@ import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.view.ImporterException; +import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; @@ -52,12 +53,19 @@ public class ViewParser implements Parser private static final String VIEW_CHILD_NAME_ATTR = "childName"; private static final String VIEW_DATATYPE_ATTR = "datatype"; private static final String VIEW_ISNULL_ATTR = "isNull"; + private static final String VIEW_INHERIT_PERMISSIONS_ATTR = "inherit"; + private static final String VIEW_ACCESS_STATUS_ATTR = "access"; private static final QName VIEW_METADATA = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "metadata"); private static final QName VIEW_VALUE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "value"); private static final QName VIEW_VALUES_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "values"); private static final QName VIEW_ASPECTS = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "aspects"); private static final QName VIEW_PROPERTIES = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "properties"); private static final QName VIEW_ASSOCIATIONS = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "associations"); + private static final QName VIEW_ACL = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "acl"); + private static final QName VIEW_ACE = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "ace"); + private static final QName VIEW_AUTHORITY = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "authority"); + private static final QName VIEW_PERMISSION = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "permission"); + // XML Pull Parser Factory private XmlPullParserFactory factory; @@ -170,7 +178,7 @@ public class ViewParser implements Parser { contextStack.push(new MetaDataContext(defName, (ElementContext)context)); } - else if (defName.equals(VIEW_ASPECTS) || defName.equals(VIEW_PROPERTIES) || defName.equals(VIEW_ASSOCIATIONS)) + else if (defName.equals(VIEW_ASPECTS) || defName.equals(VIEW_PROPERTIES) || defName.equals(VIEW_ASSOCIATIONS) || defName.equals(VIEW_ACL)) { if (context instanceof NodeItemContext) { @@ -182,6 +190,12 @@ public class ViewParser implements Parser } NodeContext nodeContext = (NodeContext)context; contextStack.push(new NodeItemContext(defName, nodeContext)); + + // process ACL specific attributes + if (defName.equals(VIEW_ACL)) + { + processACL(xpp, contextStack); + } } else { @@ -259,6 +273,10 @@ public class ViewParser implements Parser } processStartChildAssoc(xpp, def, contextStack); } + else if (itemName.equals(VIEW_ACL)) + { + processAccessControlEntry(xpp, contextStack); + } } } } @@ -369,6 +387,122 @@ public class ViewParser implements Parser logger.debug(indentLog("Processed aspect " + aspectDef.getName(), contextStack.size())); } + /** + * Process ACL definition + * + * @param xpp + * @param contextStack + */ + private void processACL(XmlPullParser xpp, Stack contextStack) + { + NodeContext context = peekNodeContext(contextStack); + + String strInherit = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_INHERIT_PERMISSIONS_ATTR); + if (strInherit != null) + { + Boolean inherit = Boolean.valueOf(strInherit); + if (!inherit) + { + context.setInheritPermissions(false); + } + } + } + + /** + * Process ACE definition + * + * @param xpp + * @param contextStack + * @throws XmlPullParserException + * @throws IOException + */ + private void processAccessControlEntry(XmlPullParser xpp, Stack contextStack) + throws XmlPullParserException, IOException + { + NodeContext context = peekNodeContext(contextStack); + + QName defName = getName(xpp); + if (!defName.equals(VIEW_ACE)) + { + throw new ImporterException("Expected start element " + VIEW_ACE); + } + + // extract Access Status + String access = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_ACCESS_STATUS_ATTR); + AccessStatus accessStatus = (access == null) ? AccessStatus.ALLOWED : AccessStatus.valueOf(AccessStatus.class, access); + if (accessStatus == null) + { + throw new ImporterException("Permission access status '" + access + "' is not recognised."); + } + + // extract authority and permission + String authority = null; + String permission = null; + int eventType = xpp.next(); + while (eventType != XmlPullParser.END_TAG) + { + if (eventType == XmlPullParser.START_TAG) + { + defName = getName(xpp); + if (defName.equals(VIEW_AUTHORITY)) + { + eventType = xpp.next(); + if (eventType != XmlPullParser.TEXT) + { + throw new ImporterException("Element " + VIEW_AUTHORITY + " must have a value"); + } + authority = xpp.getText(); + } + else if (defName.equals(VIEW_PERMISSION)) + { + eventType = xpp.next(); + if (eventType != XmlPullParser.TEXT) + { + throw new ImporterException("Element " + VIEW_PERMISSION + " must have a value"); + } + permission = xpp.getText(); + } + else + { + throw new ImporterException("Expected start element " + VIEW_AUTHORITY + " or " + VIEW_PERMISSION); + } + + eventType = xpp.next(); + if (eventType != XmlPullParser.END_TAG) + { + throw new ImporterException("Expected end element " + defName); + } + QName endDefName = getName(xpp); + if (!defName.equals(endDefName)) + { + throw new ImporterException("Expected end element " + defName); + } + } + + eventType = xpp.next(); + } + + // validate authority and permission + if (authority == null || authority.length() == 0) + { + throw new ImporterException("Authority must be specified"); + } + if (permission == null || permission.length() == 0) + { + throw new ImporterException("Permisssion must be specified"); + } + + // extract end of ace + defName = getName(xpp); + if (!defName.equals(VIEW_ACE)) + { + throw new ImporterException("Expected end element " + VIEW_ACE); + } + + // update node context + context.addAccessControlEntry(accessStatus, authority, permission); + } + /** * Process property definition * diff --git a/source/java/org/alfresco/service/cmr/view/ImporterProgress.java b/source/java/org/alfresco/service/cmr/view/ImporterProgress.java index e3fd91dd24..8af53bf3ad 100644 --- a/source/java/org/alfresco/service/cmr/view/ImporterProgress.java +++ b/source/java/org/alfresco/service/cmr/view/ImporterProgress.java @@ -19,6 +19,7 @@ package org.alfresco.service.cmr.view; import java.io.Serializable; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.namespace.QName; @@ -57,6 +58,14 @@ public interface ImporterProgress */ public void propertySet(NodeRef nodeRef, QName property, Serializable value); + /** + * Report setting of a permission + * + * @param nodeRef the node ref + * @param permission the permission + */ + public void permissionSet(NodeRef nodeRef, AccessPermission permission); + /** * Report addition of an aspect * diff --git a/source/java/org/alfresco/tools/Import.java b/source/java/org/alfresco/tools/Import.java index a226acb684..58aeb4ac7d 100644 --- a/source/java/org/alfresco/tools/Import.java +++ b/source/java/org/alfresco/tools/Import.java @@ -24,6 +24,7 @@ import org.alfresco.repo.importer.ACPImportPackageHandler; import org.alfresco.repo.importer.FileImportPackageHandler; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.view.ImportPackageHandler; import org.alfresco.service.cmr.view.ImporterException; import org.alfresco.service.cmr.view.ImporterProgress; @@ -299,6 +300,13 @@ public class Import extends Tool { } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.view.ImporterProgress#permissionSet(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.security.AccessPermission) + */ + public void permissionSet(NodeRef nodeRef, AccessPermission permission) + { + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ImporterProgress#aspectAdded(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) */