diff --git a/config/alfresco/audit/alfresco-audit-cmis.xml b/config/alfresco/audit/alfresco-audit-cmis.xml
index 030aa697fb..2cbeec1124 100644
--- a/config/alfresco/audit/alfresco-audit-cmis.xml
+++ b/config/alfresco/audit/alfresco-audit-cmis.xml
@@ -23,6 +23,8 @@
+
+
@@ -37,9 +39,15 @@
-
+
-
+
+
+
+
+
+
+
diff --git a/source/test-java/org/alfresco/opencmis/CMISTest.java b/source/test-java/org/alfresco/opencmis/CMISTest.java
index 31d3001502..bd17dc739d 100644
--- a/source/test-java/org/alfresco/opencmis/CMISTest.java
+++ b/source/test-java/org/alfresco/opencmis/CMISTest.java
@@ -48,6 +48,10 @@ import org.alfresco.opencmis.search.CMISQueryOptions;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
+import org.alfresco.repo.audit.AuditComponent;
+import org.alfresco.repo.audit.AuditServiceImpl;
+import org.alfresco.repo.audit.UserAuditFilter;
+import org.alfresco.repo.audit.model.AuditModelRegistryImpl;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.M2Model;
@@ -68,6 +72,7 @@ import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
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.rule.Rule;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.rule.RuleType;
@@ -97,6 +102,7 @@ import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.Action;
+import org.apache.chemistry.opencmis.commons.enums.ChangeType;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
@@ -144,6 +150,7 @@ public class CMISTest
private TaggingService taggingService;
private NamespaceService namespaceService;
private AuthorityService authorityService;
+ private AuditModelRegistryImpl auditSubsystem;
private PermissionService permissionService;
private DictionaryDAO dictionaryDAO;
private CMISDictionaryService cmisDictionaryService;
@@ -314,6 +321,7 @@ public class CMISTest
this.cmisConnector = (CMISConnector) ctx.getBean("CMISConnector");
this.nodeDAO = (NodeDAO) ctx.getBean("nodeDAO");
this.authorityService = (AuthorityService)ctx.getBean("AuthorityService");
+ this.auditSubsystem = (AuditModelRegistryImpl) ctx.getBean("Audit");
this.permissionService = (PermissionService) ctx.getBean("permissionService");
this.dictionaryDAO = (DictionaryDAO)ctx.getBean("dictionaryDAO");
this.cmisDictionaryService = (CMISDictionaryService)ctx.getBean("OpenCMISDictionaryService1.1");
@@ -2300,6 +2308,216 @@ public class CMISTest
}, "user2", "tenant2");
}
+ /**
+ * MNT-11726: Test that {@link CMISChangeEvent} contains objectId of node in short form (without StoreRef).
+ */
+ @Test
+ public void testCMISChangeLogObjectIds() throws Exception
+ {
+ // setUp audit subsystem
+ setupAudit();
+
+ AuthenticationUtil.pushAuthentication();
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+
+ try
+ {
+ final String changeToken = withCmisService(new CmisServiceCallback()
+ {
+ @Override
+ public String execute(CmisService cmisService)
+ {
+ List repositories = cmisService.getRepositoryInfos(null);
+ assertNotNull(repositories);
+ assertTrue(repositories.size() > 0);
+ RepositoryInfo repo = repositories.iterator().next();
+
+ return repo.getLatestChangeLogToken();
+ }
+ }, CmisVersion.CMIS_1_1);
+
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
+
+ // perform CREATED, UPDATED, SECURITY, DELETED CMIS change type actions
+ String folder = GUID.generate();
+ FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folder, ContentModel.TYPE_FOLDER);
+ nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folder);
+ assertNotNull(folderInfo);
+
+ String content = GUID.generate();
+ FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), content, ContentModel.TYPE_CONTENT);
+ assertNotNull(document);
+ nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, content);
+
+ permissionService.setPermission(document.getNodeRef(), "SomeAuthority", PermissionService.EXECUTE_CONTENT, true);
+
+ fileFolderService.delete(document.getNodeRef());
+ fileFolderService.delete(folderInfo.getNodeRef());
+
+ return null;
+ }
+ });
+
+ withCmisService(new CmisServiceCallback()
+ {
+ @Override
+ public Void execute(CmisService cmisService)
+ {
+ List repositories = cmisService.getRepositoryInfos(null);
+ assertNotNull(repositories);
+ assertTrue(repositories.size() > 0);
+ String repositoryId = repositories.iterator().next().getId();
+
+ ObjectList changes = cmisService.getContentChanges(repositoryId, new Holder(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, BigInteger.valueOf(1000), null);
+
+ for (ObjectData od : changes.getObjects())
+ {
+ ChangeType changeType = od.getChangeEventInfo().getChangeType();
+ Object objectId = od.getProperties().getProperties().get("cmis:objectId").getValues().get(0);
+
+ assertFalse("CMISChangeEvent " + changeType + " should store short form of objectId " + objectId,
+ objectId.toString().contains(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.toString()));
+ }
+
+ return null;
+ }
+ }, CmisVersion.CMIS_1_1);
+ }
+ finally
+ {
+ auditSubsystem.destroy();
+ AuthenticationUtil.popAuthentication();
+ }
+ }
+
+ private void setupAudit()
+ {
+ UserAuditFilter userAuditFilter = new UserAuditFilter();
+ userAuditFilter.setUserFilterPattern("System;.*");
+ userAuditFilter.afterPropertiesSet();
+ AuditComponent auditComponent = (AuditComponent) ctx.getBean("auditComponent");
+ auditComponent.setUserAuditFilter(userAuditFilter);
+ AuditServiceImpl auditServiceImpl = (AuditServiceImpl) ctx.getBean("auditService");
+ auditServiceImpl.setAuditComponent(auditComponent);
+
+ RetryingTransactionCallback initAudit = new RetryingTransactionCallback()
+ {
+ public Void execute() throws Exception
+ {
+ auditSubsystem.stop();
+ auditSubsystem.setProperty("audit.enabled", "true");
+ auditSubsystem.setProperty("audit.cmischangelog.enabled", "true");
+ auditSubsystem.start();
+ return null;
+ }
+ };
+ transactionService.getRetryingTransactionHelper().doInTransaction(initAudit, false, true);
+ }
+
+ /**
+ * MNT-11727: move and rename operations should be shown as an UPDATE in the CMIS change log
+ */
+ @Test
+ public void testMoveRenameWithCMISshouldBeAuditedAsUPDATE() throws Exception
+ {
+ // setUp audit subsystem
+ setupAudit();
+
+ AuthenticationUtil.pushAuthentication();
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+
+ try
+ {
+ assertTrue("Audit is not enabled", auditSubsystem.isAuditEnabled());
+ assertNotNull("CMIS audit is not enabled", auditSubsystem.getAuditApplicationByName("CMISChangeLog"));
+
+ NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
+
+ String folder = GUID.generate();
+ FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folder, ContentModel.TYPE_FOLDER);
+
+ final String actualToken = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ public String execute() throws Exception
+ {
+ return cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken();
+ }
+ }, true, false);
+
+ String content = GUID.generate();
+ FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), content, ContentModel.TYPE_CONTENT);
+ assertNotNull(document);
+ nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, content);
+
+ Holder changeLogToken = new Holder();
+ changeLogToken.setValue(actualToken);
+ ObjectList changeLog = CMISTest.this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("0"));
+ List events = changeLog.getObjects();
+ int count = events.size();
+ // it should be 3 entries: 1 for previous folder create, 1 new CREATE (for document create)
+ // and 1 NEW UPDATE
+ assertEquals(3, count);
+
+ assertEquals(events.get(0).getProperties().getPropertyList().get(0).getValues().get(0), folderInfo.getNodeRef().getId());
+ assertEquals(events.get(0).getChangeEventInfo().getChangeType(), ChangeType.CREATED);
+
+ assertTrue(((String) events.get(1).getProperties().getPropertyList().get(0).getValues().get(0)).contains(document.getNodeRef().getId()));
+ assertEquals(events.get(1).getChangeEventInfo().getChangeType(), ChangeType.CREATED);
+
+ assertTrue(((String) events.get(2).getProperties().getPropertyList().get(0).getValues().get(0)).contains(document.getNodeRef().getId()));
+ assertEquals(events.get(2).getChangeEventInfo().getChangeType(), ChangeType.UPDATED);
+
+ // test rename
+ final String actualToken2 = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ public String execute() throws Exception
+ {
+ return cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken();
+ }
+ }, true, false);
+ nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, content + "-updated");
+
+ changeLogToken = new Holder();
+ changeLogToken.setValue(actualToken2);
+ changeLog = CMISTest.this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("0"));
+ events = changeLog.getObjects();
+ count = events.size();
+ assertEquals(2, count);
+ assertEquals("Rename operation should be shown as an UPDATE in the CMIS change log", events.get(1).getChangeEventInfo().getChangeType(), ChangeType.UPDATED);
+
+ // test move
+ String targetFolder = GUID.generate();
+ FileInfo targetFolderInfo = fileFolderService.create(companyHomeNodeRef, targetFolder, ContentModel.TYPE_FOLDER);
+
+ final String actualToken3 = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ public String execute() throws Exception
+ {
+ return cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken();
+ }
+ }, true, false);
+ nodeService.moveNode(document.getNodeRef(), targetFolderInfo.getNodeRef(), ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS);
+
+ changeLogToken = new Holder();
+ changeLogToken.setValue(actualToken3);
+ changeLog = CMISTest.this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("0"));
+ events = changeLog.getObjects();
+ count = events.size();
+ assertEquals(2, count);
+ assertEquals("Move operation should be shown as an UPDATE in the CMIS change log", events.get(1).getChangeEventInfo().getChangeType(), ChangeType.UPDATED);
+ }
+ finally
+ {
+ auditSubsystem.destroy();
+ AuthenticationUtil.popAuthentication();
+ }
+ }
+
/**
* MNT-11304: Test that Alfresco has no default boundaries for decimals
* @throws Exception