diff --git a/source/java/org/alfresco/repo/web/scripts/site/SiteExportGet.java b/source/java/org/alfresco/repo/web/scripts/site/SiteExportGet.java index 93cd0f4860..1daae24e90 100644 --- a/source/java/org/alfresco/repo/web/scripts/site/SiteExportGet.java +++ b/source/java/org/alfresco/repo/web/scripts/site/SiteExportGet.java @@ -103,7 +103,7 @@ public class SiteExportGet extends AbstractWebScript mainZip.putNextEntry(new ZipEntry("Contents.acp")); doSiteACPExport(site, outputForNesting); - // Export the users who are members of the site's groups + // Export the person details for the users who are members of the site's groups // Also includes the list of their site related groups // // If there are no users in this site (other than the built-ins like admin, guest) @@ -126,7 +126,7 @@ public class SiteExportGet extends AbstractWebScript mainZip.putNextEntry(new ZipEntry("Groups.txt")); doGroupExport(site, outputForNesting); - // Export the User (authentication) details of those people + // Export the User (authentication) details for the site users that have user(authenticator) nodes associated // Only does this if the repository based authenticator is enabled RepositoryAuthenticationDao authenticationDao = null; for(String contextName : authenticationContextManager.getInstanceIds()) @@ -138,6 +138,8 @@ public class SiteExportGet extends AbstractWebScript ctx.getBean(RepositoryAuthenticationDao.class); } catch(NoSuchBeanDefinitionException e) {} } + List userNodes = getUserNodesInSiteGroup(site, authenticationDao); + //authenticationDao is initialized only when using a repository-based authentication subsystem if (authenticationDao == null) { mainZip.putNextEntry(new ZipEntry("Users_Skipped_As_Wrong_Authentication.txt")); @@ -145,7 +147,7 @@ public class SiteExportGet extends AbstractWebScript "Subsystem you are using is not repository based"; outputForNesting.write(text.getBytes("ASCII")); } - else if (peopleNodes.isEmpty()) + else if (userNodes.isEmpty()) { mainZip.putNextEntry(new ZipEntry("No_Users_In_Site.txt")); String text = "User nodes were not exported because the site does not contain\n"+ @@ -155,7 +157,7 @@ public class SiteExportGet extends AbstractWebScript else { mainZip.putNextEntry(new ZipEntry("Users.acp")); - doUserACPExport(site, outputForNesting, authenticationDao); + doUserACPExport(userNodes, site, outputForNesting); } // Finish up @@ -230,6 +232,42 @@ public class SiteExportGet extends AbstractWebScript return peopleNodes; } + /** + * Returns the user nodes (authentication nodes) if the authenticationDao exists + * @param site + * @param authenticationDao + * @return + */ + private List getUserNodesInSiteGroup(SiteInfo site, RepositoryAuthenticationDao authenticationDao) { + List userNodes = new ArrayList(); + if(authenticationDao == null) + { + return userNodes; + } + + // Identify all the users + String siteGroup = AbstractSiteWebScript.buildSiteGroup(site); + Set siteUsers = authorityService.getContainedAuthorities( + AuthorityType.USER, siteGroup, false); + + for (String user : siteUsers) + { + if (USERS_NOT_TO_EXPORT.contains(user)) + { + // Don't export these core users like admin + } + else + { + NodeRef userNodeRef = authenticationDao.getUserOrNull(user); + if(userNodeRef != null) + { + userNodes.add(userNodeRef); + } + } + } + return userNodes; + } + protected void doGroupExport(SiteInfo site, CloseIgnoringOutputStream writeTo) throws IOException { // Find the root group @@ -287,34 +325,12 @@ public class SiteExportGet extends AbstractWebScript out.close(); } - protected void doUserACPExport(SiteInfo site, CloseIgnoringOutputStream writeTo, - RepositoryAuthenticationDao authenticationDao) throws IOException + protected void doUserACPExport(List userNodes, SiteInfo site, + CloseIgnoringOutputStream writeTo) throws IOException { - List exportNodes = new ArrayList(); - - // Identify all the users - String siteGroup = AbstractSiteWebScript.buildSiteGroup(site); - Set siteUsers = authorityService.getContainedAuthorities( - AuthorityType.USER, siteGroup, false); - - // Now export them, and only them - for (String user : siteUsers) - { - if (USERS_NOT_TO_EXPORT.contains(user)) - { - // Don't export these core users like admin - } - else - { - //NodeRef personNodeRef = authorityService.getAuthorityNodeRef(user); - NodeRef userNodeRef = authenticationDao.getUserOrNull(user); - exportNodes.add(userNodeRef); - } - } - // Build the parameters ExporterCrawlerParameters parameters = new ExporterCrawlerParameters(); - parameters.setExportFrom(new Location(exportNodes.toArray(new NodeRef[exportNodes.size()]))); + parameters.setExportFrom(new Location(userNodes.toArray(new NodeRef[userNodes.size()]))); parameters.setCrawlChildNodes(true); parameters.setCrawlSelf(true); parameters.setCrawlContent(true); diff --git a/source/test-java/org/alfresco/repo/web/scripts/site/AbstractSiteServiceTest.java b/source/test-java/org/alfresco/repo/web/scripts/site/AbstractSiteServiceTest.java new file mode 100644 index 0000000000..899896481c --- /dev/null +++ b/source/test-java/org/alfresco/repo/web/scripts/site/AbstractSiteServiceTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2005-2016 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.repo.web.scripts.site; + +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.PropertyMap; +import org.json.JSONObject; +import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +import com.google.common.collect.Lists; + +/** + * Unit test for the Export Web Script API of the Site Object. + */ +public class AbstractSiteServiceTest extends BaseWebScriptTest +{ + protected MutableAuthenticationService authenticationService; + protected AuthenticationComponent authenticationComponent; + protected PersonService personService; + + private static final String URL_SITES = "/api/sites"; + private static final String URL_MEMBERSHIPS = "/memberships"; + + protected List createdSites = Lists.newArrayList(); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + this.authenticationComponent = (AuthenticationComponent) getServer() + .getApplicationContext().getBean("authenticationComponent"); + this.authenticationService = (MutableAuthenticationService) getServer() + .getApplicationContext().getBean("AuthenticationService"); + this.personService = (PersonService) getServer().getApplicationContext().getBean( + "PersonService"); + + // sets the testMode property to true via spring injection. This will + // prevent emails + // from being sent from within this test case. + this.authenticationComponent.setSystemUserAsCurrentUser(); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); + + // Tidy-up any sites create during the execution of the test + for (String shortName : this.createdSites) + { + sendRequest(new DeleteRequest(URL_SITES + "/" + shortName), 0); + } + + // Clear the list + this.createdSites.clear(); + } + + protected void createUser(String userName) + { + if (this.authenticationService.authenticationExists(userName) == false) + { + this.authenticationService.createAuthentication(userName, "PWD".toCharArray()); + createPerson(userName); + } + } + + protected void createPerson(String userName) + { + PropertyMap ppOne = new PropertyMap(4); + ppOne.put(ContentModel.PROP_USERNAME, userName); + ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); + ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); + ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); + ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); + + this.personService.createPerson(ppOne); + } + + protected void deleteUser(String username) + { + this.personService.deletePerson(username); + if (this.authenticationService.authenticationExists(username)) + { + this.authenticationService.deleteAuthentication(username); + } + } + + protected JSONObject createSite(String sitePreset, String shortName, String title, + String description, SiteVisibility visibility, int expectedStatus) throws Exception + { + JSONObject site = new JSONObject(); + site.put("sitePreset", sitePreset); + site.put("shortName", shortName); + site.put("title", title); + site.put("description", description); + site.put("visibility", visibility.toString()); + Response response = sendRequest(new PostRequest(URL_SITES, site.toString(), + "application/json"), expectedStatus); + this.createdSites.add(shortName); + return new JSONObject(response.getContentAsString()); + } + + protected void addSiteMember(String userName, String site) throws Exception + { + JSONObject membership = new JSONObject(); + membership.put("role", SiteModel.SITE_CONSUMER); + JSONObject person = new JSONObject(); + person.put("userName", userName); + membership.put("person", person); + + sendRequest(new PostRequest(URL_SITES + "/" + site + URL_MEMBERSHIPS, + membership.toString(), "application/json"), 200); + } +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/site/AllSiteTests.java b/source/test-java/org/alfresco/repo/web/scripts/site/AllSiteTests.java index c5701d2c11..1b7eeb6f4a 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/site/AllSiteTests.java +++ b/source/test-java/org/alfresco/repo/web/scripts/site/AllSiteTests.java @@ -39,6 +39,7 @@ import org.junit.runners.Suite; SiteServiceImplTest.class, SiteServiceImplMoreTest.class, SiteServiceTest.class, + SiteExportServiceTest.class, SiteActivityTestCaseSensitivity.class, SiteActivityTestCaseInsensitivity.class }) diff --git a/source/test-java/org/alfresco/repo/web/scripts/site/SiteExportServiceTest.java b/source/test-java/org/alfresco/repo/web/scripts/site/SiteExportServiceTest.java new file mode 100644 index 0000000000..765e5af436 --- /dev/null +++ b/source/test-java/org/alfresco/repo/web/scripts/site/SiteExportServiceTest.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2005-2016 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.repo.web.scripts.site; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipInputStream; + +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.junit.Ignore; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +import com.google.common.collect.Lists; + +/** + * Unit test for the Export Web Script API of the Site Object. + */ +public class SiteExportServiceTest extends AbstractSiteServiceTest +{ + private static final String USER_FROM_LDAP = "SiteUserLdap"; + private static final String USER_ONE = "SiteUser"; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + // Create users + createUser(USER_ONE); + createPerson(USER_FROM_LDAP); + + // Do tests as admin + this.authenticationComponent.setCurrentUser("admin"); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + + // Clear the users + deleteUser(USER_ONE); + deleteUser(USER_FROM_LDAP); + } + + public void testExportSiteWithMutipleUsers() throws Exception + { + // Create a site + String shortName = GUID.generate(); + createSite("myPreset", shortName, "myTitle", "myDescription", SiteVisibility.PUBLIC, 200); + + // add a user and a person as members + addSiteMember(USER_FROM_LDAP, shortName); + addSiteMember(USER_ONE, shortName); + + // Export site + Response response = sendRequest(new GetRequest(getExportUrl(shortName)), 200); + + // check exported files + List entries = getEntries(new ZipInputStream(new ByteArrayInputStream( + response.getContentAsByteArray()))); + assertFalse(entries.contains("No_Users_In_Site.txt")); + assertFalse(entries.contains("No_Persons_In_Site.txt")); + assertTrue(entries.contains("People.acp")); + assertTrue(entries.contains(shortName + "-people.xml")); + assertTrue(entries.contains("Users.acp")); + assertTrue(entries.contains(shortName + "-users.xml")); + } + + public void testExportSiteWithOneLDAPUser() throws Exception + { + // Create a site + String shortName = GUID.generate(); + createSite("myPreset", shortName, "myTitle", "myDescription", SiteVisibility.PUBLIC, 200); + + // add a user synced from LDAP(authenticator node not present) + addSiteMember(USER_FROM_LDAP, shortName); + + // Export site + Response response = sendRequest(new GetRequest(getExportUrl(shortName)), 200); + + // check No_Users_In_Site.txt present + // because there is no user associated with the single member of the + // site + List entries = getEntries(new ZipInputStream(new ByteArrayInputStream( + response.getContentAsByteArray()))); + assertFalse(entries.contains("Users.acp")); + assertTrue(entries.contains("No_Users_In_Site.txt")); + assertTrue(entries.contains("People.acp")); + assertTrue(entries.contains(shortName + "-people.xml")); + } + + public void testExportSiteWithNoUsers() throws Exception + { + // Create a site + String shortName = GUID.generate(); + createSite("myPreset", shortName, "myTitle", "myDescription", SiteVisibility.PUBLIC, 200); + + // Export site + Response response = sendRequest(new GetRequest(getExportUrl(shortName)), 200); + + // check No_Users_In_Site.txt and No_Persons_In_Site.txt present + List entries = getEntries(new ZipInputStream(new ByteArrayInputStream( + response.getContentAsByteArray()))); + assertTrue(entries.contains("No_Users_In_Site.txt")); + assertTrue(entries.contains("No_Persons_In_Site.txt")); + assertFalse(entries.contains("Users.acp")); + assertFalse(entries.contains("People.acp")); + } + + private List getEntries(ZipInputStream zipStream) throws Exception + { + ZipEntry entry = null; + List entries = Lists.newArrayList(); + while ((entry = zipStream.getNextEntry()) != null) + { + if (entry.getName().endsWith("acp")) + { + entries.addAll(getAcpEntries(zipStream)); + } + entries.add(entry.getName()); + zipStream.closeEntry(); + } + zipStream.close(); + return entries; + } + + private List getAcpEntries(InputStream inputStream) throws Exception + { + List entries = Lists.newArrayList(); + ZipInputStream zipInputStream = new ZipInputStream(inputStream); + ZipEntry entry = null; + try + { + while ((entry = zipInputStream.getNextEntry()) != null) + { + entries.add(entry.getName()); + } + } + catch (ZipException e) + { + // ignore + } + return entries; + } + + private String getExportUrl(String shortName) + { + return "/api/sites/" + shortName + "/export"; + } + +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java b/source/test-java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java index 3df1f59fc4..5cc126c325 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java @@ -19,23 +19,17 @@ package org.alfresco.repo.web.scripts.site; import java.io.Serializable; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.AssertionFailedError; import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -43,16 +37,13 @@ import org.alfresco.service.cmr.repository.StoreRef; 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.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; -import org.alfresco.util.PropertyMap; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -68,16 +59,12 @@ import org.springframework.extensions.webscripts.TestWebScriptServer.Response; * * @author Roy Wetherall */ -public class SiteServiceTest extends BaseWebScriptTest +public class SiteServiceTest extends AbstractSiteServiceTest { - private MutableAuthenticationService authenticationService; - private AuthenticationComponent authenticationComponent; - private PersonService personService; private SiteService siteService; private NodeService nodeService; private PermissionService permissionService; private AuthorityService authorityService; - private FileFolderService fileFolderService; private static final String USER_ONE = "SiteTestOne"; private static final String USER_TWO = "SiteTestTwo"; @@ -90,25 +77,15 @@ public class SiteServiceTest extends BaseWebScriptTest private static final String URL_MEMBERSHIPS = "/memberships"; private static final String URL_SITES_ADMIN = "/api/admin-sites"; - private List createdSites = new ArrayList(5); - @Override protected void setUp() throws Exception { super.setUp(); - this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); - this.authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); - this.personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); this.siteService = (SiteService)getServer().getApplicationContext().getBean("SiteService"); this.nodeService = (NodeService)getServer().getApplicationContext().getBean("NodeService"); this.permissionService = (PermissionService)getServer().getApplicationContext().getBean("PermissionService"); this.authorityService = (AuthorityService)getServer().getApplicationContext().getBean("AuthorityService"); - this.fileFolderService = (FileFolderService)getServer().getApplicationContext().getBean("FileFolderService"); - - // sets the testMode property to true via spring injection. This will prevent emails - // from being sent from within this test case. - this.authenticationComponent.setSystemUserAsCurrentUser(); // Create users createUser(USER_ONE); @@ -124,36 +101,10 @@ public class SiteServiceTest extends BaseWebScriptTest this.authenticationComponent.setCurrentUser(USER_ONE); } - private void createUser(String userName) - { - if (this.authenticationService.authenticationExists(userName) == false) - { - this.authenticationService.createAuthentication(userName, "PWD".toCharArray()); - - PropertyMap ppOne = new PropertyMap(4); - ppOne.put(ContentModel.PROP_USERNAME, userName); - ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); - ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); - ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); - ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); - - this.personService.createPerson(ppOne); - } - } - private void deleteUser(String username) - { - this.personService.deletePerson(username); - if(this.authenticationService.authenticationExists(username)) - { - this.authenticationService.deleteAuthentication(username); - } - } - @Override protected void tearDown() throws Exception { super.tearDown(); - this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); // Clear the users deleteUser(USER_ONE); @@ -161,17 +112,8 @@ public class SiteServiceTest extends BaseWebScriptTest deleteUser(USER_THREE); deleteUser(USER_NUMERIC); deleteUser(USER_FOUR_AS_SITE_ADMIN); - - // Tidy-up any site's create during the execution of the test - for (String shortName : this.createdSites) - { - sendRequest(new DeleteRequest(URL_SITES + "/" + shortName), 0); - } - - // Clear the list - this.createdSites.clear(); } - + public void testCreateSite() throws Exception { String shortName = GUID.generate(); @@ -191,20 +133,6 @@ public class SiteServiceTest extends BaseWebScriptTest createSite("myPreset", shortName, "myTitle", "myDescription", SiteVisibility.PUBLIC, 400); } - private JSONObject createSite(String sitePreset, String shortName, String title, String description, SiteVisibility visibility, int expectedStatus) - throws Exception - { - JSONObject site = new JSONObject(); - site.put("sitePreset", sitePreset); - site.put("shortName", shortName); - site.put("title", title); - site.put("description", description); - site.put("visibility", visibility.toString()); - Response response = sendRequest(new PostRequest(URL_SITES, site.toString(), "application/json"), expectedStatus); - this.createdSites.add(shortName); - return new JSONObject(response.getContentAsString()); - } - public void testGetSites() throws Exception { int preexistingSiteCount = 0;