RM-430: It's possible to delete folder with frozen records

* protected in place so items with frozen children (record folders or record categories) can not be deleted
  * consolidated behaviour into a freeze service
  * commented out the methods that would appear in a freeze service, but out of 2.0 scope to refactor this now



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.0@39050 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2012-07-11 06:12:52 +00:00
parent 82976695e3
commit 9edc96ce36
4 changed files with 286 additions and 13 deletions

View File

@@ -708,6 +708,14 @@
</property>
</bean>
<!-- Freeze Service -->
<bean id="freezeService" class="org.alfresco.module.org_alfresco_module_rm.freeze.FreezeServiceImpl" init-method="init">
<property name="policyComponent" ref="policyComponent" />
<property name="recordsManagementService" ref="RecordsManagementService" />
<property name="nodeService" ref="nodeService" />
</bean>
<!-- Records Management Audit Service -->
<bean id="recordsManagementAuditService" class="org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl" init-method="init">

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2005-2012 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.freeze;
/**
* Freeze Service Interface
*
* TODO Fill the implementation of this service out and consolidate existing freeze code. For now consider this a guide for a future service implementation.
* Implementation used to consolidate freeze behaviours in 2.0.
* When implementing consider application of freeze to 'any' node references, not just records and record folders. (Consider implecations for security and
* capabilities)
*
* @author Roy Wetherall
* @since 2.0
*/
public interface FreezeService
{
/**
* Indicates whether the passed node reference is a hold. A hold is a container for a group of frozen object and contains the freeze
* reason.
*
* @param nodeRef hold node reference
* @return boolean true if hold, false otherwise
*/
// TODO boolean isHold(NodeRef nodeRef);
/**
* Indicates whether the passed node reference is frozen.
*
* @param nodeRef node reference
* @return boolean true if frozen, false otherwise
*/
// TODO boolean isFrozen(NodeRef nodeRef);
/**
* Get the 'root' frozen node references in a hold.
*
* @param hold hold node reference
* @return Set<NodeRef> frozen node references
*/
// TODO Set<NodeRef> getFrozen(NodeRef hold);
/**
* Freezes a node with the provided reason, creating a hold node reference.
*
* @param reason freeze reason
* @param nodeRef node reference
* @return NodeRef hold node reference
*/
// TODO NodeRef freeze(String reason, NodeRef nodeRef);
/**
* Freezes a node, adding it an existing hold.
*
* @param hold hold node reference
* @param nodeRef node reference
*/
// TODO void freeze(NodeRef hold, NodeRef nodeRef);
/**
* Freezes a collection of nodes with the given reason, creating a hold.
*
* @param reason freeze reason
* @param Set<NodeRef> set of nodes to freeze
* @return NodeRef hold node reference
*/
// TODO NodeRef freeze(String reason, Set<NodeRef> nodeRef);
/**
* Freeze a collection of nodes, adding them to an existing hold.
*
* @param hold hold node reference
* @param nodeRef set of nodes to freeze
*/
// TODO void freeze(NodeRef hold, Set<NodeRef> nodeRef);
/**
* Unfreeze a frozen node.
* <p>
* The unfrozen node is automatically removed from the hold(s) it is in. If the hold is
* subsequently empty, the hold is automatically deleted.
*
* @param nodeRef node reference
*/
// TODO void unFreeze(NodeRef nodeRef);
/**
* Unfreeze a collection of nodes.
* <p>
* The unfrozen nodes are automatically removed from the hold(s) the are in. If the hold(s) is
* subsequently empty, the hold is automatically deleted.
*
* @param Set<NodeRef> set of nodes to unfreeze
*/
// TODO void unFreeze(Set<NodeRef> nodeRef);
/**
* Unfreezes all nodes within a hold and deletes the hold.
*
* @param hold hold node reference
*/
// TODO void relinquish(NodeRef hold);
/**
* Gets the freeze reason for a hold.
*
* @param hold hold node reference
* @return String freeze reason
*/
// TODO String getReason(NodeRef hold);
/**
* Updates the freeze reason for a given hold.
*
* @param hold hold node reference
* @param reason updated reason
*/
// TODO void updateReason(NodeRef hold, String reason);
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2005-2012 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.freeze;
import java.util.List;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
/**
* Freeze Service Implementation
*
* @author Roy Wetherall
*/
public class FreezeServiceImpl implements FreezeService,
RecordsManagementModel,
NodeServicePolicies.BeforeDeleteNodePolicy
{
/** Policy Component */
private PolicyComponent policyComponent;
/** Node Service */
private NodeService nodeService;
/** Records Management Service */
private RecordsManagementService recordsManagementService;
/**
* @param policyComponent policy component
*/
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
}
/**
* @param nodeService node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param recordsManagementService records management service
*/
public void setRecordsManagementService(RecordsManagementService recordsManagementService)
{
this.recordsManagementService = recordsManagementService;
}
/**
* Init service
*/
public void init()
{
policyComponent.bindClassBehaviour(
NodeServicePolicies.BeforeDeleteNodePolicy.QNAME,
this,
new JavaBehaviour(this, "beforeDeleteNode", NotificationFrequency.FIRST_EVENT));
}
/**
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void beforeDeleteNode(final NodeRef nodeRef)
{
AuthenticationUtil.runAsSystem(new RunAsWork<Void>(){
@Override
public Void doWork() throws Exception
{
if (nodeService.exists(nodeRef) == true &&
recordsManagementService.isFilePlanComponent(nodeRef) == true)
{
if (recordsManagementService.isFrozen(nodeRef) == true)
{
// never allowed to delete a frozen node
throw new AccessDeniedException("Frozen nodes can not be deleted.");
}
// check children
checkChildren(nodeService.getChildAssocs(nodeRef));
}
return null;
}});
}
/**
* Checks the children for frozen nodes. Throws security error if any are found.
*
* @param assocs
*/
private void checkChildren(List<ChildAssociationRef> assocs)
{
for (ChildAssociationRef assoc : assocs)
{
// we only care about primary children
if (assoc.isPrimary() == true)
{
NodeRef nodeRef = assoc.getChildRef();
if (recordsManagementService.isFrozen(nodeRef) == true)
{
// never allowed to delete a node with a frozen child
throw new AccessDeniedException("Can not delete node, because it contains a frozen child node.");
}
// check children
checkChildren(nodeService.getChildAssocs(nodeRef));
}
}
}
}

View File

@@ -185,19 +185,6 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe
NodeServicePolicies.OnCreateNodePolicy.QNAME,
TYPE_RECORD_FOLDER,
new JavaBehaviour(this, "onCreateRecordFolder", NotificationFrequency.TRANSACTION_COMMIT));
policyComponent.bindClassBehaviour(
NodeServicePolicies.BeforeDeleteNodePolicy.QNAME,
ASPECT_FROZEN,
new JavaBehaviour(this, "beforeDeleteFrozenNode", NotificationFrequency.TRANSACTION_COMMIT));
}
public void beforeDeleteFrozenNode(NodeRef nodeRef)
{
if (nodeService.exists(nodeRef) && recordsManagementService.isFrozen(nodeRef) == true)
{
// Never allowed to delete a frozen node
throw new AccessDeniedException("Frozen nodes can not be deleted");
}
}
/**