diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
index f1bd9ed043..f7dc62dc12 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
@@ -63,6 +63,7 @@
parent="org_alfresco_module_rm_BaseBehaviour">
+
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java
index a0b5a1077a..703babff3c 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService;
import org.alfresco.repo.node.NodeServicePolicies;
@@ -29,11 +30,13 @@ import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.AccessStatus;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility;
@@ -47,27 +50,32 @@ import org.alfresco.util.PropertyMap;
*/
public class RmSiteType implements RecordsManagementModel,
NodeServicePolicies.OnCreateNodePolicy,
- NodeServicePolicies.OnUpdatePropertiesPolicy
+ NodeServicePolicies.OnUpdatePropertiesPolicy,
+ NodeServicePolicies.BeforeDeleteNodePolicy
{
/** Constant values */
public static final String COMPONENT_DOCUMENT_LIBRARY = "documentLibrary";
public static final String DEFAULT_SITE_NAME = "rm";
/** Policy component */
- private PolicyComponent policyComponent;
+ protected PolicyComponent policyComponent;
/** Site service */
- private SiteService siteService;
+ protected SiteService siteService;
/** Node service */
- private NodeService nodeService;
+ protected NodeService nodeService;
/** Record Management Search Service */
- private RecordsManagementSearchService recordsManagementSearchService;
+ protected RecordsManagementSearchService recordsManagementSearchService;
+
+ /** Capability service */
+ protected CapabilityService capabilityService;
/** Behaviour */
JavaBehaviour onCreateNode = new JavaBehaviour(this, "onCreateNode", NotificationFrequency.FIRST_EVENT);
JavaBehaviour onUpdateProperties = new JavaBehaviour(this, "onUpdateProperties", NotificationFrequency.FIRST_EVENT);
+ JavaBehaviour beforeDelete = new JavaBehaviour(this, "beforeDeleteNode", NotificationFrequency.FIRST_EVENT);
/**
* Set the policy component
@@ -104,6 +112,14 @@ public class RmSiteType implements RecordsManagementModel,
this.recordsManagementSearchService = recordsManagementSearchService;
}
+ /**
+ * @param capabilityService capability service
+ */
+ public void setCapabilityService(CapabilityService capabilityService)
+ {
+ this.capabilityService = capabilityService;
+ }
+
/**
* Bean initialisation method
*/
@@ -116,6 +132,10 @@ public class RmSiteType implements RecordsManagementModel,
policyComponent.bindClassBehaviour(NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME,
TYPE_RM_SITE,
onUpdateProperties);
+
+ policyComponent.bindClassBehaviour(NodeServicePolicies.BeforeDeleteNodePolicy.QNAME,
+ TYPE_RM_SITE,
+ beforeDelete);
}
/**
@@ -184,4 +204,36 @@ public class RmSiteType implements RecordsManagementModel,
}
}
}
+
+ /**
+ * @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ public void beforeDeleteNode(NodeRef nodeRef)
+ {
+ final SiteInfo siteInfo = siteService.getSite(nodeRef);
+ if (siteInfo != null)
+ {
+ // grab the file plan for the RM site
+ NodeRef filePlan = AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ @Override
+ public NodeRef doWork() throws Exception
+ {
+ return siteService.getContainer(siteInfo.getShortName(), COMPONENT_DOCUMENT_LIBRARY);
+ }
+
+ });
+
+ if (filePlan != null)
+ {
+ // determine whether the current user has delete capability on the file plan node
+ AccessStatus accessStatus = capabilityService.getCapabilityAccessState(filePlan, "Delete");
+ if (AccessStatus.DENIED.equals(accessStatus) == true)
+ {
+ throw new AlfrescoRuntimeException("The records management site can not be deleted, because the user doesn't have sufficient privillages to delete the file plan.");
+ }
+ }
+ }
+ }
}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/IssueTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/IssueTestSuite.java
index 30daf78cff..8da2f5b7e5 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/IssueTestSuite.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/IssueTestSuite.java
@@ -23,6 +23,7 @@ import org.alfresco.module.org_alfresco_module_rm.test.issue.RM1027Test;
import org.alfresco.module.org_alfresco_module_rm.test.issue.RM1030Test;
import org.alfresco.module.org_alfresco_module_rm.test.issue.RM1039Test;
import org.alfresco.module.org_alfresco_module_rm.test.issue.RM452Test;
+import org.alfresco.module.org_alfresco_module_rm.test.issue.RM804Test;
import org.alfresco.module.org_alfresco_module_rm.test.issue.RM994Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -42,7 +43,8 @@ import org.junit.runners.Suite.SuiteClasses;
RM1008Test.class,
RM1030Test.class,
RM1027Test.class,
- RM1039Test.class
+ RM1039Test.class,
+ RM804Test.class
})
public class IssueTestSuite
{
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM804Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM804Test.java
new file mode 100644
index 0000000000..7105d692ce
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM804Test.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2005-2013 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.issue;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.service.cmr.security.AccessStatus;
+import org.alfresco.service.cmr.site.SiteRole;
+
+
+/**
+ * Unit test for RM-804 .. site managers are able to delete file plans
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+public class RM804Test extends BaseRMTestCase
+{
+ @Override
+ protected void initServices()
+ {
+ super.initServices();
+ }
+
+ @Override
+ protected boolean isCollaborationSiteTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isUserTest()
+ {
+ return true;
+ }
+
+ public void testUsersHaveDeletePermissionsOnFilePlan() throws Exception
+ {
+ // as rmuser
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ assertEquals(AccessStatus.ALLOWED, capabilityService.getCapabilityAccessState(filePlan, "Delete"));
+
+ return null;
+ }
+ }, "rmadmin");
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ assertEquals(AccessStatus.ALLOWED, capabilityService.getCapabilityAccessState(filePlan, "Delete"));
+
+ return null;
+ }
+ }, "admin");
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ assertEquals(AccessStatus.ALLOWED, capabilityService.getCapabilityAccessState(filePlan, "Delete"));
+
+ return null;
+ }
+ }, rmAdminName);
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ assertEquals(AccessStatus.DENIED, capabilityService.getCapabilityAccessState(filePlan, "Delete"));
+
+ return null;
+ }
+ }, rmUserName);
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ assertEquals(AccessStatus.DENIED, capabilityService.getCapabilityAccessState(filePlan, "Delete"));
+
+ return null;
+ }
+ }, userName);
+ }
+
+ public void testTryAndDeleteSiteAsSiteManagerOnly()
+ {
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ siteService.setMembership(siteId, userName, SiteRole.SiteManager.toString());
+
+ return null;
+ }
+ }, "admin");
+
+ doTestInTransaction(new FailureTest
+ (
+ "Should not be able to delete site as a site manager only.",
+ AlfrescoRuntimeException.class
+ )
+ {
+ @Override
+ public void run() throws Exception
+ {
+ siteService.deleteSite(siteId);
+
+ }
+ }, userName);
+
+ // give the user a RM role (but not sufficient to delete the file plan node ref)
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_USER, userName);
+
+ return null;
+ }
+ }, "admin");
+
+ doTestInTransaction(new FailureTest
+ (
+ "Should not be able to delete site as a site manager with an RM role that doesn't have the capability.",
+ AlfrescoRuntimeException.class
+ )
+ {
+ @Override
+ public void run() throws Exception
+ {
+ siteService.deleteSite(siteId);
+
+ }
+ }, userName);
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_ADMINISTRATOR, userName);
+
+ return null;
+ }
+ }, "admin");
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ siteService.deleteSite(siteId);
+
+ return null;
+ }
+ }, userName);
+
+ }
+
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
index 9f6ff57ae4..520b9b7d94 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
@@ -406,20 +406,29 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
filter.disableBehaviour();
try
{
- Set holds = freezeService.getHolds(filePlan);
- for (NodeRef hold : holds)
+ if (nodeService.exists(filePlan) == true)
{
- freezeService.relinquish(hold);
+ Set holds = freezeService.getHolds(filePlan);
+ for (NodeRef hold : holds)
+ {
+ freezeService.relinquish(hold);
+ }
}
- // Delete the folder
- nodeService.deleteNode(folder);
-
- // Delete the site
- siteService.deleteSite(siteId);
+ if (nodeService.exists(folder) == true)
+ {
+ // Delete the folder
+ nodeService.deleteNode(folder);
+ }
+
+ if (siteService.getSite(siteId) != null)
+ {
+ // Delete the site
+ siteService.deleteSite(siteId);
+ }
// delete the collaboration site (if required)
- if (isCollaborationSiteTest() == true)
+ if (isCollaborationSiteTest() == true && siteService.getSite(COLLABORATION_SITE_ID) != null)
{
siteService.deleteSite(COLLABORATION_SITE_ID);
}