From 890dd9417cf0647f383ec09065fa0b6398683d62 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Tue, 24 Feb 2015 21:38:10 +0000 Subject: [PATCH] RM-1956: Create record capability allows user to edit metadata and copy category/folder /record * fixes issue relating to filing records with only CreateRecord capability git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.3@97945 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../rm-capabilities-record-context.xml | 4 +- .../rm-service-context.xml | 1 + .../impl/EditNonRecordMetadataCapability.java | 63 ++++++++++++++ .../capability/impl/UpdateCapability.java | 38 +-------- .../policy/UpdatePropertiesPolicy.java | 41 +-------- .../record/RecordServiceImpl.java | 49 ++++------- .../util/ServiceBaseImpl.java | 16 +++- .../integration/record/CreateRecordTest.java | 85 ++++++++++++++++++- .../legacy/service/RecordServiceImplTest.java | 3 +- ...tNonRecordsMetadataCapabilityUnitTest.java | 65 ++++++++++++++ .../record/RecordServiceImplUnitTest.java | 70 ++++++++++++++- .../test/AllUnitTestSuite.java | 4 + 12 files changed, 322 insertions(+), 117 deletions(-) create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordMetadataCapability.java create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordsMetadataCapabilityUnitTest.java diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml index afa426d881..8b82723be3 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml @@ -245,7 +245,8 @@ + parent="declarativeCapability" + class="org.alfresco.module.org_alfresco_module_rm.capability.impl.EditNonRecordMetadataCapability"> @@ -263,6 +264,7 @@ + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordMetadataCapability.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordMetadataCapability.java new file mode 100644 index 0000000000..fa1cc976c6 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordMetadataCapability.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2014 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.capability.impl; + +import net.sf.acegisecurity.vote.AccessDecisionVoter; + +import org.alfresco.module.org_alfresco_module_rm.capability.declarative.DeclarativeCapability; +import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl; +import org.alfresco.module.org_alfresco_module_rm.util.TransactionalResourceHelper; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Edit non record metadata capability + * + * @author Roy Wetherall + * @since 2.3 + */ +public class EditNonRecordMetadataCapability extends DeclarativeCapability +{ + /** transaction resource helper */ + private TransactionalResourceHelper transactionalResourceHelper; + + /** + * @param transactionalResourceHelper transaction resource helper + */ + public void setTransactionalResourceHelper(TransactionalResourceHelper transactionalResourceHelper) + { + this.transactionalResourceHelper = transactionalResourceHelper; + } + + @Override + public int evaluate(NodeRef nodeRef) + { + // check if this node is a new record + if (transactionalResourceHelper.getSet(RecordServiceImpl.KEY_NEW_RECORDS).contains(nodeRef)) + { + // since this is a new record created within this transaction, ignore the usual capability check + // under the assumption that the user has CreateRecord + // @see https://issues.alfresco.com/jira/browse/RM-1956 + return AccessDecisionVoter.ACCESS_GRANTED; + } + + return super.evaluate(nodeRef); + } + + +} \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/UpdateCapability.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/UpdateCapability.java index be66403728..701a1da03b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/UpdateCapability.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/UpdateCapability.java @@ -19,16 +19,10 @@ package org.alfresco.module.org_alfresco_module_rm.capability.impl; import java.io.Serializable; -import java.util.Arrays; -import java.util.List; import java.util.Map; -import net.sf.acegisecurity.vote.AccessDecisionVoter; - -import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.declarative.DeclarativeCompositeCapability; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.namespace.QName; /** @@ -48,36 +42,6 @@ public class UpdateCapability extends DeclarativeCompositeCapability */ public int evaluate(NodeRef nodeRef, QName aspectQName, Map properties) { - int result = evaluate(nodeRef); - - if (AccessDecisionVoter.ACCESS_GRANTED != result) - { - if (checkEligablePermissions(nodeRef)) - { - result = AccessDecisionVoter.ACCESS_GRANTED; - } - } - - return result; - } - - private boolean checkEligablePermissions(NodeRef nodeRef) - { - boolean result = false; - List permissions = Arrays.asList( - RMPermissionModel.CREATE_RECORDS - ); - - NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef); - for (String permission : permissions) - { - if (permissionService.hasPermission(filePlan, permission) == AccessStatus.ALLOWED) - { - result = true; - break; - } - } - - return result; + return evaluate(nodeRef); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/policy/UpdatePropertiesPolicy.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/policy/UpdatePropertiesPolicy.java index cb64dc36ef..02f30dbc1b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/policy/UpdatePropertiesPolicy.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/policy/UpdatePropertiesPolicy.java @@ -18,14 +18,7 @@ */ package org.alfresco.module.org_alfresco_module_rm.capability.policy; -import java.util.Arrays; -import java.util.List; - -import net.sf.acegisecurity.vote.AccessDecisionVoter; - -import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.AccessStatus; import org.aopalliance.intercept.MethodInvocation; public class UpdatePropertiesPolicy extends AbstractBasePolicy @@ -37,38 +30,6 @@ public class UpdatePropertiesPolicy extends AbstractBasePolicy ConfigAttributeDefinition cad) { NodeRef nodeRef = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent()); - int result = getCapabilityService().getCapability("UpdateProperties").evaluate(nodeRef); - - if (AccessDecisionVoter.ACCESS_GRANTED != result) - { - if (checkEligablePermissions(nodeRef)) - { - result = AccessDecisionVoter.ACCESS_GRANTED; - } - } - - return result; - } - - private boolean checkEligablePermissions(NodeRef nodeRef) - { - boolean result = false; - List permissions = Arrays.asList( - RMPermissionModel.CREATE_RECORDS, - RMPermissionModel.CREATE_MODIFY_DESTROY_FOLDERS, - RMPermissionModel.CREATE_MODIFY_DESTROY_FILEPLAN_METADATA - ); - - NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef); - for (String permission : permissions) - { - if (permissionService.hasPermission(filePlan, permission) == AccessStatus.ALLOWED) - { - result = true; - break; - } - } - - return result; + return getCapabilityService().getCapability("UpdateProperties").evaluate(nodeRef); } } \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index e5976bd634..a6e54acba8 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -72,7 +72,6 @@ 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.repo.security.permissions.impl.ExtendedPermissionService; -import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; @@ -128,7 +127,9 @@ public class RecordServiceImpl extends BaseBehaviourBean private static Log logger = LogFactory.getLog(RecordServiceImpl.class); /** transation data key */ - private static final String IGNORE_ON_UPDATE = "ignoreOnUpdate"; + private static final String KEY_IGNORE_ON_UPDATE = "ignoreOnUpdate"; + private static final String KEY_PENDING_FILLING = "pendingFilling"; + public static final String KEY_NEW_RECORDS = "newRecords"; /** I18N */ private static final String MSG_NODE_HAS_ASPECT = "rm.service.node-has-aspect"; @@ -413,7 +414,7 @@ public class RecordServiceImpl extends BaseBehaviourBean else { // check whether filling is pending aspect removal - Set pendingFilling = TransactionalResourceHelper.getSet("pendingFilling"); + Set pendingFilling = transactionalResourceHelper.getSet(KEY_PENDING_FILLING); if (pendingFilling.contains(nodeRef)) { file(nodeRef); @@ -504,11 +505,20 @@ public class RecordServiceImpl extends BaseBehaviourBean if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_NO_CONTENT)) { // we need to postpone filling until the NO_CONTENT aspect is removed - Set pendingFilling = TransactionalResourceHelper.getSet("pendingFilling"); + Set pendingFilling = transactionalResourceHelper.getSet(KEY_PENDING_FILLING); pendingFilling.add(nodeRef); } else { + // store information about the 'new' record in the transaction + // @since 2.3 + // @see https://issues.alfresco.com/jira/browse/RM-1956 + if (bNew) + { + Set newRecords = transactionalResourceHelper.getSet(KEY_NEW_RECORDS); + newRecords.add(nodeRef); + } + // create and file the content as a record file(nodeRef); } @@ -567,7 +577,7 @@ public class RecordServiceImpl extends BaseBehaviourBean */ public void disablePropertyEditableCheck(NodeRef nodeRef) { - Set ignoreOnUpdate = TransactionalResourceHelper.getSet(IGNORE_ON_UPDATE); + Set ignoreOnUpdate = transactionalResourceHelper.getSet(KEY_IGNORE_ON_UPDATE); ignoreOnUpdate.add(nodeRef); } @@ -598,7 +608,7 @@ public class RecordServiceImpl extends BaseBehaviourBean !AuthenticationUtil.isRunAsUserTheSystemUser() && nodeService.exists(nodeRef) && isRecord(nodeRef) && - !TransactionalResourceHelper.getSet(IGNORE_ON_UPDATE).contains(nodeRef)) + !transactionalResourceHelper.getSet(KEY_IGNORE_ON_UPDATE).contains(nodeRef)) { for (Map.Entry entry : after.entrySet()) { @@ -637,8 +647,7 @@ public class RecordServiceImpl extends BaseBehaviourBean if (!propertyUnchanged && !(ContentModel.PROP_CONTENT.equals(property) && beforeValue == null) && - !isPropertyEditable(nodeRef, property) && - !checkEligablePermissions(nodeRef)) + !isPropertyEditable(nodeRef, property)) { // the user can't edit the record property throw new ModelAccessDeniedException( @@ -650,28 +659,6 @@ public class RecordServiceImpl extends BaseBehaviourBean } } - private boolean checkEligablePermissions(NodeRef nodeRef) - { - boolean result = false; - List permissions = Arrays.asList( - RMPermissionModel.CREATE_RECORDS, - RMPermissionModel.CREATE_MODIFY_DESTROY_FOLDERS, - RMPermissionModel.CREATE_MODIFY_DESTROY_FILEPLAN_METADATA - ); - - NodeRef filePlan = getFilePlan(nodeRef); - for (String permission : permissions) - { - if (permissionService.hasPermission(filePlan, permission) == AccessStatus.ALLOWED) - { - result = true; - break; - } - } - - return result; - } - /** * Get map containing record metadata aspects. * @@ -1711,7 +1698,7 @@ public class RecordServiceImpl extends BaseBehaviourBean // we can not link a record to the same location more than once throw new AlfrescoRuntimeException("Can not link a record to the same record folder more than once"); } - } + } // get the current name of the record String name = nodeService.getProperty(record, ContentModel.PROP_NAME).toString(); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java index 4f5c6f9b9c..84ae926006 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java @@ -26,7 +26,6 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.rendition.RenditionService; import org.alfresco.service.cmr.repository.ChildAssociationRef; @@ -63,6 +62,9 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte /** authentication helper */ protected AuthenticationUtil authenticationUtil; + + /** transactional resource helper */ + protected TransactionalResourceHelper transactionalResourceHelper; /** * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) @@ -104,6 +106,14 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte { this.authenticationUtil = authenticationUtil; } + + /** + * @param transactionalResourceHelper transactional resource helper + */ + public void setTransactionalResourceHelper(TransactionalResourceHelper transactionalResourceHelper) + { + this.transactionalResourceHelper = transactionalResourceHelper; + } /** * Helper to get internal node service. @@ -129,7 +139,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte { FilePlanComponentKind result = null; - Map map = TransactionalResourceHelper.getMap("rm.transaction.filePlanComponentByNodeRef"); + Map map = transactionalResourceHelper.getMap("rm.transaction.filePlanComponentByNodeRef"); if (map.containsKey(nodeRef)) { result = map.get(nodeRef); @@ -387,7 +397,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte NodeRef result = null; if (nodeRef != null) { - Map transactionCache = TransactionalResourceHelper.getMap("rm.servicebase.getFilePlan"); + Map transactionCache = transactionalResourceHelper.getMap("rm.servicebase.getFilePlan"); if (transactionCache.containsKey(nodeRef)) { result = transactionCache.get(nodeRef); diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateRecordTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateRecordTest.java index 1f410afb6a..fa9162ea48 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateRecordTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateRecordTest.java @@ -28,6 +28,8 @@ import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.repo.content.MimetypeMap; 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.ContentData; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.util.GUID; @@ -92,7 +94,7 @@ public class CreateRecordTest extends BaseRMTestCase } /** - * @see + * */ public void testCreateRecordCapabilityOnlyFromFileFolderService() throws Exception { @@ -201,4 +203,85 @@ public class CreateRecordTest extends BaseRMTestCase } }); } + + /** + * Given I have ViewRecord and CreateRecord capabilities + * And I have filling on a record folder + * When I create content via ScriptNode (simulated) + * Then the record is successfully created + * + * @see https://issues.alfresco.com/jira/browse/RM-1956 + */ + public void testCreateRecordViaCoreServices() throws Exception + { + doBehaviourDrivenTest(new BehaviourDrivenTest() + { + /** test data */ + String roleName = GUID.generate(); + String user = GUID.generate(); + NodeRef recordFolder; + NodeRef record; + + public void given() + { + // create a role with view and create capabilities + Set capabilities = new HashSet(2); + capabilities.add(capabilityService.getCapability("ViewRecords")); + capabilities.add(capabilityService.getCapability("CreateRecords")); + filePlanRoleService.createRole(filePlan, roleName, roleName, capabilities); + + // create user and assign to role + createPerson(user, true); + filePlanRoleService.assignRoleToAuthority(filePlan, roleName, user); + + // create file plan structure + NodeRef rc = filePlanService.createRecordCategory(filePlan, GUID.generate()); + recordFolder = recordFolderService.createRecordFolder(rc, GUID.generate()); + } + + public void when() + { + // give read and file permissions to user + filePlanPermissionService.setPermission(recordFolder, user, RMPermissionModel.FILING); + + record = AuthenticationUtil.runAs(new RunAsWork() + { + public NodeRef doWork() throws Exception + { + NodeRef record = fileFolderService.create(recordFolder, "testRecord.txt", ContentModel.TYPE_CONTENT).getNodeRef(); + ContentData content = (ContentData)nodeService.getProperty(record, PROP_CONTENT); + nodeService.setProperty(record, PROP_CONTENT, ContentData.setMimetype(content, MimetypeMap.MIMETYPE_TEXT_PLAIN)); + return record; + } + }, user); + } + + public void then() + { + // check the details of the record + assertTrue(recordService.isRecord(record)); + + AuthenticationUtil.runAs(new RunAsWork() + { + public Void doWork() throws Exception + { + // we are expecting an expception here + try + { + ContentData content = (ContentData)nodeService.getProperty(record, PROP_CONTENT); + nodeService.setProperty(record, PROP_CONTENT, ContentData.setMimetype(content, MimetypeMap.MIMETYPE_TEXT_PLAIN)); + fail("Expecting access denied exception"); + } + catch (AccessDeniedException exception) + { + // expceted + } + + return null; + } + }, user); + } + + }); + } } diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java index 3353cc3763..14f5ffa379 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java @@ -746,8 +746,7 @@ public class RecordServiceImplTest extends BaseRMTestCase // test rmadmin canEditProperty(recordOne, ContentModel.PROP_DESCRIPTION, ADMIN_USER); canEditProperty(recordOne, RecordsManagementModel.PROP_LOCATION, ADMIN_USER); - // FIXME: Why can a admin user edit the location property of a declared record but not the desc? - //cantEditProperty(recordDeclaredOne, ContentModel.PROP_DESCRIPTION, ADMIN_USER); + cantEditProperty(recordDeclaredOne, ContentModel.PROP_DESCRIPTION, ADMIN_USER); canEditProperty(recordDeclaredOne, RecordsManagementModel.PROP_LOCATION, ADMIN_USER); // test normal user diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordsMetadataCapabilityUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordsMetadataCapabilityUnitTest.java new file mode 100644 index 0000000000..e622588d5c --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/EditNonRecordsMetadataCapabilityUnitTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2014 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.capability.impl; + +import static org.mockito.Mockito.when; + +import java.util.Set; + +import net.sf.acegisecurity.vote.AccessDecisionVoter; + +import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; +import org.alfresco.service.cmr.repository.NodeRef; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +/** + * Edit non records metadata capability unit test + * + * @author Roy Wetherall + * @since 2.3 + */ +public class EditNonRecordsMetadataCapabilityUnitTest extends BaseUnitTest +{ + /** mocked set */ + @Mock private Set mockedSet; + + /** test capability */ + @InjectMocks private EditNonRecordMetadataCapability capability; + + /** + * Given that the evaluated node is held in the transaction cache as new + * When evaluated + * Then access is granted + */ + @Test + public void newRecord() + { + NodeRef nodeRef = generateNodeRef(); + when(mockedTransactionalResourceHelper.getSet(RecordServiceImpl.KEY_NEW_RECORDS)) + .thenReturn(mockedSet); + when(mockedSet.contains(nodeRef)) + .thenReturn(true); + + Assert.assertEquals(AccessDecisionVoter.ACCESS_GRANTED, capability.evaluate(nodeRef)); + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java index 4dd0670268..3a77194016 100755 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java @@ -21,17 +21,22 @@ package org.alfresco.module.org_alfresco_module_rm.record; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.HashSet; import java.util.Map; import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -39,6 +44,7 @@ import org.apache.commons.collections.CollectionUtils; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; +import org.mockito.Spy; /** * Unit test for RecordServiceImpl @@ -54,7 +60,7 @@ public class RecordServiceImplUnitTest extends BaseUnitTest private static QName TYPE_MY_FILE_PLAN = generateQName(); private static QName ASPECT_FOR_FILE_PLAN = generateQName(); - @InjectMocks private RecordServiceImpl recordService; + @Spy @InjectMocks private RecordServiceImpl recordService; @SuppressWarnings("unchecked") @Before @@ -239,5 +245,65 @@ public class RecordServiceImplUnitTest extends BaseUnitTest // verify link was created verify(mockedNodeService, times(1)).removeChild(recordFolder, record); - } + } + + /** + * Given that a new record is being created + * When the behaviour is triggered + * Then the record is stored for later reference in the transaction + */ + @SuppressWarnings("unchecked") + @Test + public void onCreateChildAssociationNewRecord() + { + // standard content node + NodeRef nodeRef = generateCmContent("test.txt"); + ChildAssociationRef assoc = generateChildAssociationRef(generateNodeRef(), nodeRef); + + doNothing().when(recordService).file(nodeRef); + + // doesn't have no content aspect + when(mockedNodeService.hasAspect(nodeRef, ContentModel.ASPECT_NO_CONTENT)) + .thenReturn(false); + + Set values = mock(HashSet.class); + when(mockedTransactionalResourceHelper.getSet(RecordServiceImpl.KEY_NEW_RECORDS)) + .thenReturn(values); + + // trigger behaviour + recordService.onCreateChildAssociation(assoc, true); + + // verify + verify(values, times(1)).add(nodeRef); + } + + /** + * Given that an existing record is linked + * When the behaviour is triggered + * Then the record is not stored for later reference in the transaction + */ + @SuppressWarnings("unchecked") + @Test + public void onCreateChildAssociationExistingRecord() + { + // standard content node + NodeRef nodeRef = generateCmContent("test.txt"); + ChildAssociationRef assoc = generateChildAssociationRef(generateNodeRef(), nodeRef); + + doNothing().when(recordService).file(nodeRef); + + // doesn't have no content aspect + when(mockedNodeService.hasAspect(nodeRef, ContentModel.ASPECT_NO_CONTENT)) + .thenReturn(false); + + Set values = mock(HashSet.class); + when(mockedTransactionalResourceHelper.getSet(RecordServiceImpl.KEY_NEW_RECORDS)) + .thenReturn(values); + + // trigger behaviour + recordService.onCreateChildAssociation(assoc, false); + + // verify + verify(values, never()).add(nodeRef); + } } diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java index 02090856a2..70d5e7247c 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java @@ -25,6 +25,7 @@ import org.alfresco.module.org_alfresco_module_rm.bootstrap.BootstrapImporterMod import org.alfresco.module.org_alfresco_module_rm.bootstrap.RecordContributorsGroupBootstrapComponentUnitTest; import org.alfresco.module.org_alfresco_module_rm.capability.RMEntryVoterUnitTest; import org.alfresco.module.org_alfresco_module_rm.capability.declarative.condition.CapabilityDeclarativeConditionSuite; +import org.alfresco.module.org_alfresco_module_rm.capability.impl.EditNonRecordsMetadataCapabilityUnitTest; import org.alfresco.module.org_alfresco_module_rm.forms.RecordsManagementTypeFormFilterUnitTest; import org.alfresco.module.org_alfresco_module_rm.hold.HoldServiceImplUnitTest; import org.alfresco.module.org_alfresco_module_rm.job.DispositionLifecycleJobExecuterUnitTest; @@ -70,6 +71,9 @@ import org.junit.runners.Suite.SuiteClasses; // evaluators TransferEvaluatorUnitTest.class, FrozenEvaluatorUnitTest.class, + + // capabilities + EditNonRecordsMetadataCapabilityUnitTest.class, // web scripts HoldsGetUnitTest.class,