diff --git a/repository/src/main/java/org/alfresco/opencmis/ActivityPosterImpl.java b/repository/src/main/java/org/alfresco/opencmis/ActivityPosterImpl.java index cf04bd259c..59c1123a1a 100644 --- a/repository/src/main/java/org/alfresco/opencmis/ActivityPosterImpl.java +++ b/repository/src/main/java/org/alfresco/opencmis/ActivityPosterImpl.java @@ -32,6 +32,8 @@ import org.alfresco.sync.repo.Client; import org.alfresco.sync.repo.Client.ClientType; import org.alfresco.repo.activities.ActivityType; import org.alfresco.repo.model.filefolder.HiddenAspect; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.activities.ActivityInfo; import org.alfresco.service.cmr.activities.ActivityPoster; @@ -228,7 +230,7 @@ public class ActivityPosterImpl implements CmisActivityPoster, InitializingBean { if(activitiesEnabled && !hiddenAspect.hasHiddenAspect(nodeRef)) { - SiteInfo siteInfo = siteService.getSite(nodeRef); + SiteInfo siteInfo = getSiteAsSystem(nodeRef); String siteId = (siteInfo != null ? siteInfo.getShortName() : null); if(siteId != null && !siteId.equals("")) { @@ -290,5 +292,16 @@ public class ActivityPosterImpl implements CmisActivityPoster, InitializingBean return null; } } - + + private SiteInfo getSiteAsSystem(NodeRef nodeRef) + { + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public SiteInfo doWork() throws Exception + { + return siteService.getSite(nodeRef); + } + }); + } } \ No newline at end of file diff --git a/repository/src/main/resources/alfresco/opencmis-context.xml b/repository/src/main/resources/alfresco/opencmis-context.xml index 8d07ac0952..f1882ef9c4 100644 --- a/repository/src/main/resources/alfresco/opencmis-context.xml +++ b/repository/src/main/resources/alfresco/opencmis-context.xml @@ -265,4 +265,4 @@ - \ No newline at end of file + diff --git a/repository/src/test/java/org/alfresco/opencmis/CMISTest.java b/repository/src/test/java/org/alfresco/opencmis/CMISTest.java index aafb028545..161d5faff5 100644 --- a/repository/src/test/java/org/alfresco/opencmis/CMISTest.java +++ b/repository/src/test/java/org/alfresco/opencmis/CMISTest.java @@ -78,6 +78,7 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationContext; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.tenant.TenantUtil; @@ -107,7 +108,13 @@ import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; +import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.security.PersonService.PersonInfo; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.cmr.tagging.TaggingService; import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.VersionService; @@ -211,6 +218,9 @@ public class CMISTest private SearchService searchService; private java.util.Properties globalProperties; private AuditComponentImpl auditComponent; + private PersonService personService; + private SiteService siteService; + private MutableAuthenticationService authenticationService; private AlfrescoCmisServiceFactory factory; @@ -336,6 +346,9 @@ public class CMISTest this.tenantService = (TenantService) ctx.getBean("tenantService"); this.searchService = (SearchService) ctx.getBean("SearchService"); this.auditComponent = (AuditComponentImpl) ctx.getBean("auditComponent"); + this.personService = (PersonService) ctx.getBean("personService"); + this.siteService = (SiteService) ctx.getBean("siteService"); + this.authenticationService = (MutableAuthenticationService) ctx.getBean("AuthenticationService"); this.globalProperties = (java.util.Properties) ctx.getBean("global-properties"); this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "true"); @@ -717,12 +730,17 @@ public class CMISTest } private T withCmisService(CmisServiceCallback callback, CmisVersion cmisVersion) + { + return withCmisService("admin", "admin", callback, cmisVersion); + } + + private T withCmisService(String username, String password, CmisServiceCallback callback, CmisVersion cmisVersion) { CmisService cmisService = null; try { - CallContext context = new SimpleCallContext("admin", "admin", cmisVersion); + CallContext context = new SimpleCallContext(username, password, cmisVersion); cmisService = factory.getService(context); T ret = callback.execute(cmisService); return ret; @@ -4097,6 +4115,108 @@ public class CMISTest } } + /** + * This test ensures that a non member user of a private site, can edit metadata on a document (where the non member user + * has "SiteCollaborator" role) placed on the site. + * + * @throws Exception + */ + @Test + public void testMNT20006() throws Exception + { + AuthenticationUtil.pushAuthentication(); + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + final String nonMemberUsername = "user" + System.currentTimeMillis(); + final String nonMemberPassword = "pass" + System.currentTimeMillis(); + final String siteId = "site" + System.currentTimeMillis(); + final String originalDescription = "my description"; + + NodeRef fileNode; + + try + { + fileNode = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + // Create user + authenticationService.createAuthentication(nonMemberUsername, nonMemberPassword.toCharArray()); + Map props = new HashMap(); + String email = nonMemberUsername + "@testcmis.com"; + props.put(ContentModel.PROP_USERNAME, nonMemberUsername); + props.put(ContentModel.PROP_FIRSTNAME, nonMemberUsername); + props.put(ContentModel.PROP_LASTNAME, nonMemberUsername); + props.put(ContentModel.PROP_EMAIL, email); + PersonInfo personInfo = personService.getPerson(personService.createPerson(props)); + assertNotNull("Null person info", personInfo); + + // Create site + SiteInfo siteInfo = siteService.createSite("myPreset", siteId, "myTitle", "myDescription", SiteVisibility.PRIVATE); + assertNotNull("Null site info", siteInfo); + NodeRef siteDocLib = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null); + assertNotNull("Null site doclib", siteDocLib); + + // Create node in site + String nodeName = "node" + System.currentTimeMillis() + ".txt"; + NodeRef fileNode = nodeService.createNode(siteDocLib, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS, ContentModel.TYPE_CONTENT).getChildRef(); + ContentWriter writer = contentService.getWriter(fileNode, ContentModel.PROP_CONTENT, true); + writer.putContent("my node content"); + nodeService.setProperty(fileNode, ContentModel.PROP_TITLE, nodeName); + nodeService.setProperty(fileNode, ContentModel.PROP_DESCRIPTION, originalDescription); + assertNotNull("Null file node", fileNode); + assertTrue(nodeService.exists(fileNode)); + + // Sets node permissions to the user who is not member of the site and get site activities + permissionService.setPermission(fileNode, nonMemberUsername, SiteModel.SITE_COLLABORATOR, true); + + return fileNode; + } + }); + } + finally + { + AuthenticationUtil.popAuthentication(); + } + + // Edit metadata + final String newDescription = "new node description"; + + Boolean updated = withCmisService(nonMemberUsername, nonMemberPassword, new CmisServiceCallback() + { + @Override + public Boolean execute(CmisService cmisService) + { + Boolean updated = true; + + try + { + // Obtain repository id + List repositories = cmisService.getRepositoryInfos(null); + assertTrue(repositories.size() > 0); + RepositoryInfo repo = repositories.get(0); + String repositoryId = repo.getId(); + + // Id holder + Holder objectIdHolder = new Holder(fileNode.toString()); + + // New Properties + PropertiesImpl newProperties = new PropertiesImpl(); + newProperties.addProperty(new PropertyStringImpl(PropertyIds.DESCRIPTION, newDescription)); + cmisService.updateProperties(repositoryId, objectIdHolder, null, newProperties, null); + } + catch (Exception e) + { + updated = false; + } + + return updated; + }; + }, CmisVersion.CMIS_1_1); + + assertTrue("Document metadata not updated", updated); + } + private NodeRef createFolder(NodeRef parentNodeRef, String folderName, QName folderType) throws IOException { Map properties = new HashMap(); diff --git a/scripts/travis/trigger_travis.sh b/scripts/travis/trigger_travis.sh index f180f412dd..a0fc6b83cb 100755 --- a/scripts/travis/trigger_travis.sh +++ b/scripts/travis/trigger_travis.sh @@ -28,7 +28,7 @@ curl -s -X POST \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -H "Travis-API-Version: 3" \ - -H "Authorization: token ${TRAVIS_ACCESS_TOKEN_TEMP}" \ + -H "Authorization: token ${TRAVIS_ACCESS_TOKEN}" \ -d "${BODY}" \ "${URL}" \ | tee /tmp/travis-request-output.txt