Java tutorial
/* * #%L * Alfresco Remote API * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * * 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/>. * #L% */ package org.alfresco.repo.web.scripts.invite; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.repo.action.executer.MailActionExecuter; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.invitation.InvitationServiceImpl; import org.alfresco.repo.invitation.WorkflowModelNominatedInvitation; import org.alfresco.repo.invitation.script.ScriptInvitationService; import org.alfresco.repo.invitation.site.InviteInfo; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; import org.alfresco.repo.node.archive.NodeArchiveService; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.MutableAuthenticationDao; import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.web.scripts.BaseWebScriptTest; import org.alfresco.repo.workflow.activiti.ActivitiConstants; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.MutableAuthenticationService; 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.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowInstance; import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.GUID; import org.alfresco.util.PropertyMap; import org.apache.commons.lang.RandomStringUtils; import org.json.JSONArray; import org.json.JSONObject; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.extensions.surf.util.URLEncoder; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.TestWebScriptServer; import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; import org.springframework.extensions.webscripts.TestWebScriptServer.PutRequest; import org.springframework.extensions.webscripts.TestWebScriptServer.Response; /** * Unit Test to test Invite Web Script API * * @author Glen Johnson at Alfresco dot com */ public class InviteServiceTest extends BaseWebScriptTest { // member variables for service instances private AuthorityService authorityService; private MutableAuthenticationService authenticationService; private AuthenticationComponent authenticationComponent; private PersonService personService; private SiteService siteService; private NodeService nodeService; private WorkflowService workflowService; private MutableAuthenticationDao mutableAuthenticationDao; private NamespaceService namespaceService; private TransactionService transactionService; private NodeArchiveService nodeArchiveService; private InvitationServiceImpl invitationServiceImpl; // stores invitee email addresses, one entry for each "start invite" operation // invoked, so that resources created for each invitee for each test // can be removed in the tearDown() method private List<String> inviteeEmailAddrs; private static final String WF_DEFINITION_INVITE = WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI_INVITE; private static final String USER_INVITER = "InviterUser"; private static final String USER_INVITER_2 = "InviterUser2"; private static final String INVITEE_FIRSTNAME = "InviteeFirstName"; private static final String INVITEE_LASTNAME = "InviteeLastName"; private static final String INVITER_EMAIL = "FirstName123.LastName123@email.com"; private static final String INVITER_EMAIL_2 = "FirstNameabc.LastNameabc@email.com"; private static final String INVITEE_EMAIL_DOMAIN = "alfrescotesting.com"; private static final String INVITEE_EMAIL_PREFIX = "invitee"; private static final String INVITEE_SITE_ROLE = SiteModel.SITE_COLLABORATOR; private static final String SITE_SHORT_NAME_INVITE_1 = "SiteOneInviteTest"; private static final String SITE_SHORT_NAME_INVITE_2 = "SiteTwoInviteTest"; private static final String SITE_SHORT_NAME_INVITE_3 = "SiteThreeInviteTest"; private static final String URL_INVITE = "/api/invite"; private static final String URL_INVITES = "/api/invites"; private static final String INVITE_ACTION_START = "start"; private static final String INVITE_ACTION_CANCEL = "cancel"; @Override protected void setUp() throws Exception { super.setUp(); /** * We don't want to be authenticated as 'system' but run as 'InviterUser', because then * 'system' will be the creator for the sites and 'inviterUser' will be a nobody. */ AuthenticationUtil.clearCurrentSecurityContext(); // get references to services this.authorityService = (AuthorityService) getServer().getApplicationContext().getBean("AuthorityService"); 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.workflowService = (WorkflowService) getServer().getApplicationContext().getBean("WorkflowService"); this.mutableAuthenticationDao = (MutableAuthenticationDao) getServer().getApplicationContext() .getBean("authenticationDao"); this.namespaceService = (NamespaceService) getServer().getApplicationContext().getBean("NamespaceService"); this.transactionService = (TransactionService) getServer().getApplicationContext() .getBean("TransactionService"); this.nodeArchiveService = (NodeArchiveService) getServer().getApplicationContext() .getBean("nodeArchiveService"); this.invitationServiceImpl = (InvitationServiceImpl) getServer().getApplicationContext() .getBean("invitationService"); ScriptInvitationService scriptInvitationService = (ScriptInvitationService) getServer() .getApplicationContext().getBean("invitationServiceScript"); scriptInvitationService.setSiteService(this.siteService); Invite invite = (Invite) getServer().getApplicationContext() .getBean("webscript.org.alfresco.repository.invite.invite.get"); invite.setSiteService(this.siteService); configureMailExecutorForTestMode(this.getServer()); // We're using a MailActionExecuter defined in outboundSMTP-test-context.xml which // sets the testMode property to true via spring injection. This will prevent emails // from being sent from within this test case. // This MailExecutorAction bean is named "test-mail" but is in all other respects equivalent to the // 'real' executer bean. It is automatically included during OutboundSMTP subsystem startup. this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { // // various setup operations which need to be run as system user // AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { // // redeploy invite process definition in case it has been modified // WorkflowDefinition inviteWfDefinition = workflowService.getDefinitionByName( // "jbpm$" + WorkflowModelNominatedInvitation.WF_PROCESS_INVITE.toPrefixString(namespaceService)); // workflowService.undeployDefinition(inviteWfDefinition.id); // ClassPathResource inviteWfResource = new ClassPathResource( // "alfresco/workflow/invitation-nominated_processdefinition.xml"); // workflowService.deployDefinition( // JBPMEngine.ENGINE_ID, inviteWfResource.getInputStream(), MimetypeMap.MIMETYPE_XML); // Create new invitee email address list inviteeEmailAddrs = new ArrayList<String>(); // Create inviter person createPerson(PERSON_FIRSTNAME, PERSON_LASTNAME, USER_INVITER, INVITER_EMAIL); // Create inviter2 person createPerson(PERSON_FIRSTNAME, PERSON_LASTNAME, USER_INVITER_2, INVITER_EMAIL_2); return null; } }, AuthenticationUtil.getSystemUserName()); // The creation of sites is heavily dependent on the authenticated user. We must ensure that, // when doing the runAs below, the user both 'runAs' and 'fullyAuthenticated'. In order for // this to be the case, the security context MUST BE EMPTY now. We could do the old // "defensive clear", but really there should not be any lurking authentications on this thread // after the context starts up. If there are, that is a bug, and we fail explicitly here. String residuallyAuthenticatedUser = AuthenticationUtil.getFullyAuthenticatedUser(); assertNull("Residual authentication on context-initiating thread (this thread):" + residuallyAuthenticatedUser, residuallyAuthenticatedUser); // // various setup operations which need to be run as inviter user // AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { // Create first site for Inviter to invite Invitee to SiteInfo siteInfo = siteService.getSite(SITE_SHORT_NAME_INVITE_1); if (siteInfo == null) { siteService.createSite("InviteSitePreset", SITE_SHORT_NAME_INVITE_1, "InviteSiteTitle", "InviteSiteDescription", SiteVisibility.PUBLIC); } // Create second site for inviter to invite invitee to siteInfo = siteService.getSite(SITE_SHORT_NAME_INVITE_2); if (siteInfo == null) { siteService.createSite("InviteSitePreset", SITE_SHORT_NAME_INVITE_2, "InviteSiteTitle", "InviteSiteDescription", SiteVisibility.PUBLIC); } // Create third site for inviter to invite invitee to siteInfo = InviteServiceTest.this.siteService.getSite(SITE_SHORT_NAME_INVITE_3); if (siteInfo == null) { siteService.createSite("InviteSitePreset", SITE_SHORT_NAME_INVITE_3, "InviteSiteTitle", "InviteSiteDescription", SiteVisibility.PUBLIC); } // set inviter2's role on third site to collaborator String inviterSiteRole = siteService.getMembersRole(SITE_SHORT_NAME_INVITE_3, USER_INVITER_2); if ((inviterSiteRole == null) || (inviterSiteRole.equals(SiteModel.SITE_COLLABORATOR) == false)) { siteService.setMembership(SITE_SHORT_NAME_INVITE_3, USER_INVITER_2, SiteModel.SITE_COLLABORATOR); } return null; } }, USER_INVITER); // Do tests as inviter user InviteServiceTest.this.authenticationComponent.setCurrentUser(USER_INVITER); return null; } }); } /** * This method turns off email-sending within the MailActionExecuter bean. */ public static void configureMailExecutorForTestMode(TestWebScriptServer server) { // This test class depends on a MailActionExecuter bean which sends out emails // in a live system. We want to prevent these emails from being sent during // test execution. // To do that, we need to get at the outboundSMTP-context.xml and change its // "mail" MailActionExecuter bean to test mode. setTestMode(true) on that object // will turn off email sending. // But that bean is defined within a subsystem i.e. a child application context. // There are a number of ways we could do this, none of them perfect. // // 1. Expose the setTestMode(boolean) method in the subsystem API. // We could have the "mail" bean implement a "TestModeable" interface and // expose that through the proxy. // But that would mean that the setTestMode method would be available in the // live system too, which is not ideal. // 2. Replace the "mail" bean in outboundSMTP-context.xml with an alternative in a // different subsystem context file as described in // http://wiki.alfresco.com/wiki/Alfresco_Subsystems#Debugging_Alfresco_Subsystems // But to do that, we'd have to reproduce all the spring config for that bean // and add a testMode property. Again not ideal. // 3. Hack into the "mail" bean by programmatically going through the known applicationContext // and bean structure. This is not ideal either, but it has no effect on product code // and isolates all the hacking into this test class. // // Therefore we've decided to do [3]. ChildApplicationContextFactory outboundSmptSubsystem = (ChildApplicationContextFactory) server .getApplicationContext().getBean("OutboundSMTP"); ApplicationContext childAppCtxt = outboundSmptSubsystem.getApplicationContext(); MailActionExecuter mailActionExecutor = (MailActionExecuter) childAppCtxt.getBean("mail"); mailActionExecutor.setTestMode(true); } @Override protected void tearDown() throws Exception { super.tearDown(); RunAsWork<SiteInfo[]> runAsWork = new RunAsWork<SiteInfo[]>() { public SiteInfo[] doWork() throws Exception { SiteInfo[] siteInfos = { siteService.getSite(SITE_SHORT_NAME_INVITE_1), siteService.getSite(SITE_SHORT_NAME_INVITE_2), siteService.getSite(SITE_SHORT_NAME_INVITE_3) }; return siteInfos; } }; final SiteInfo[] siteInfos = AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getSystemUserName()); // // run various teardown operations which need to be run as 'admin' // transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { RunAsWork<Object> runAsWork = new RunAsWork<Object>() { public Object doWork() throws Exception { // delete the inviter deletePersonByUserName(USER_INVITER); // delete all invitee people for (String inviteeEmail : inviteeEmailAddrs) { // // delete all people with given email address // Set<NodeRef> people = personService.getPeopleFilteredByProperty(ContentModel.PROP_EMAIL, inviteeEmail, 1000); for (NodeRef person : people) { String userName = DefaultTypeConverter.INSTANCE.convert(String.class, InviteServiceTest.this.nodeService.getProperty(person, ContentModel.PROP_USERNAME)); // delete person deletePersonByUserName(userName); } } // delete invite sites siteService.deleteSite(SITE_SHORT_NAME_INVITE_1); siteService.deleteSite(SITE_SHORT_NAME_INVITE_2); siteService.deleteSite(SITE_SHORT_NAME_INVITE_3); // Sleep to ensure asynchronous invite deletion completes Thread.sleep(5000); return null; } }; AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getSystemUserName()); // cancel all active invite workflows WorkflowDefinition wfDef = InviteServiceTest.this.workflowService .getDefinitionByName(WF_DEFINITION_INVITE); List<WorkflowInstance> workflowList = InviteServiceTest.this.workflowService .getActiveWorkflows(wfDef.id); for (WorkflowInstance workflow : workflowList) { InviteServiceTest.this.workflowService.cancelWorkflow(workflow.id); } return null; } }); AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { for (SiteInfo siteInfo : siteInfos) { nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(siteInfo.getNodeRef())); } return null; } }, AuthenticationUtil.getSystemUserName()); } public static String PERSON_FIRSTNAME = "FirstName123"; public static String PERSON_LASTNAME = "LastName123"; public static String PERSON_JOBTITLE = "JobTitle123"; public static String PERSON_ORG = "Organisation123"; private void createPerson(String firstName, String lastName, String userName, String emailAddress) { // if user with given user name doesn't already exist then create user if (this.authenticationService.authenticationExists(userName) == false) { // create user this.authenticationService.createAuthentication(userName, "password".toCharArray()); } // if person node with given user name doesn't already exist then create // person if (this.personService.personExists(userName) == false) { // create person properties PropertyMap personProps = new PropertyMap(); personProps.put(ContentModel.PROP_USERNAME, userName); personProps.put(ContentModel.PROP_FIRSTNAME, firstName); personProps.put(ContentModel.PROP_LASTNAME, lastName); personProps.put(ContentModel.PROP_EMAIL, emailAddress); personProps.put(ContentModel.PROP_JOBTITLE, PERSON_JOBTITLE); personProps.put(ContentModel.PROP_ORGANIZATION, PERSON_ORG); // create person node for user this.personService.createPerson(personProps); } } private void deletePersonByUserName(String userName) { // delete person node associated with given user name // if one exists if (this.personService.personExists(userName)) { this.personService.deletePerson(userName); } } private JSONObject startInvite(String inviteeFirstName, String inviteeLastName, String inviteeEmail, String inviteeSiteRole, String siteShortName, int expectedStatus) throws Exception { this.inviteeEmailAddrs.add(inviteeEmail); // Inviter sends invitation to Invitee to join a Site String startInviteUrl = URL_INVITE + "/" + INVITE_ACTION_START + "?inviteeFirstName=" + inviteeFirstName + "&inviteeLastName=" + inviteeLastName + "&inviteeEmail=" + URLEncoder.encode(inviteeEmail) + "&siteShortName=" + siteShortName + "&inviteeSiteRole=" + inviteeSiteRole + "&serverPath=" + "http://localhost:8081/share/" + "&acceptUrl=" + "page/accept-invite" + "&rejectUrl=" + "page/reject-invite"; Response response = sendRequest(new GetRequest(startInviteUrl), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject startInvite(String inviteeFirstName, String inviteeLastName, String inviteeSiteRole, String siteShortName, int expectedStatus) throws Exception { String inviteeEmail = INVITEE_EMAIL_PREFIX + RandomStringUtils.randomAlphanumeric(6) + "@" + INVITEE_EMAIL_DOMAIN; return startInvite(inviteeFirstName, inviteeLastName, inviteeEmail, inviteeSiteRole, siteShortName, expectedStatus); } private JSONObject cancelInvite(String inviteId, String siteShortName, int expectedStatus) throws Exception { String cancelInviteUrl = URL_INVITE + "/" + INVITE_ACTION_CANCEL + "?inviteId=" + inviteId; if (siteShortName != null && !siteShortName.isEmpty()) { cancelInviteUrl = cancelInviteUrl + "&siteShortName=" + siteShortName; } Response response = sendRequest(new GetRequest(cancelInviteUrl), expectedStatus); ; JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject rejectInvite(String inviteId, String inviteTicket, int expectedStatus) throws Exception { // Invitee rejects invitation to a Site from Inviter String rejectInviteUrl = URL_INVITE + "/" + inviteId + "/" + inviteTicket + "/reject"; Response response = sendRequest(new PutRequest(rejectInviteUrl, (byte[]) null, null), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject getInvitesByInviteId(String inviteId, int expectedStatus) throws Exception { // construct get invites URL String getInvitesUrl = URL_INVITES + "?inviteId=" + inviteId; // invoke get invites web script Response response = sendRequest(new GetRequest(getInvitesUrl), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject getInvitesByInviterUserName(String inviterUserName, int expectedStatus) throws Exception { // construct get invites URL String getInvitesUrl = URL_INVITES + "?inviterUserName=" + inviterUserName; // invoke get invites web script Response response = sendRequest(new GetRequest(getInvitesUrl), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject getInvitesByInviteeUserName(String inviteeUserName, int expectedStatus) throws Exception { // construct get invites URL String getInvitesUrl = URL_INVITES + "?inviteeUserName=" + inviteeUserName; // invoke get invites web script Response response = sendRequest(new GetRequest(getInvitesUrl), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject getInvitesBySiteShortName(String siteShortName, int expectedStatus) throws Exception { // construct get invites URL String getInvitesUrl = URL_INVITES + "?siteShortName=" + siteShortName; // invoke get invites web script Response response = sendRequest(new GetRequest(getInvitesUrl), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject listInvitations(String siteShortName, String userNameSearch, int expectedStatus) throws Exception { // construct get invites URL String getInvitesUrl = "/api/sites/" + siteShortName + "/potentialmembers?authorityType=USER&sortBy=fullName&dir=asc&filter=" + userNameSearch + "&maxResults=250"; // invoke get invites web script Response response = sendRequest(new GetRequest(getInvitesUrl), expectedStatus); JSONObject result = new JSONObject(response.getContentAsString()); return result; } private JSONObject getInviteInfo(String inviteId, String inviteTicket, String inviteeUid) throws Exception { String url = "/api/invite/" + inviteId + "/" + inviteTicket + "?inviteeUserName=" + inviteeUid; String runAsUser = AuthenticationUtil.getRunAsUser(); Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); if (!runAsUser.equals(AuthenticationUtil.getRunAsUser())) { AuthenticationUtil.setRunAsUser(runAsUser); } JSONObject result = new JSONObject(response.getContentAsString()); return result; } public void testStartInvite() throws Exception { JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); assertEquals(INVITE_ACTION_START, result.get("action")); assertEquals(INVITEE_FIRSTNAME, result.get("inviteeFirstName")); assertEquals(INVITEE_LASTNAME, result.get("inviteeLastName")); assertEquals(this.inviteeEmailAddrs.get(this.inviteeEmailAddrs.size() - 1), result.get("inviteeEmail")); assertEquals(SITE_SHORT_NAME_INVITE_1, result.get("siteShortName")); } public void testStartInviteWhenInviteeIsAlreadyMemberOfSite() throws Exception { // // add invitee as member of site: SITE_SHORT_NAME_INVITE // String randomStr = RandomStringUtils.randomNumeric(6); final String inviteeUserName = "inviteeUserName" + randomStr; final String inviteeEmailAddr = INVITEE_EMAIL_PREFIX + randomStr + "@" + INVITEE_EMAIL_DOMAIN; // create person with invitee user name and invitee email address AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { createPerson(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeUserName, inviteeEmailAddr); return null; } }, AuthenticationUtil.getSystemUserName()); // add invitee person to site: SITE_SHORT_NAME_INVITE AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { InviteServiceTest.this.siteService.setMembership(SITE_SHORT_NAME_INVITE_1, inviteeUserName, INVITEE_SITE_ROLE); return null; } }, USER_INVITER); /** * Should conflict */ startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmailAddr, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_CONFLICT); // Should go through startInvite(INVITEE_FIRSTNAME, "Belzebub", inviteeEmailAddr, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // Should go through startInvite("Lucifer", INVITEE_LASTNAME, inviteeEmailAddr, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); } // public void testStartInviteWhenAlreadyInProgress() // throws Exception // { // JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, // SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // // String inviteeEmail = (String) result.get("inviteeEmail"); // // startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE, // SITE_SHORT_NAME_INVITE_1, Status.STATUS_CONFLICT); // } // public void testStartInviteForSameInviteeButTwoDifferentSites() throws Exception { final String inviteeUsername = INVITEE_FIRSTNAME + "_" + INVITEE_LASTNAME; final String inviteeEmail = INVITEE_EMAIL_PREFIX + RandomStringUtils.randomAlphanumeric(6) + "@" + INVITEE_EMAIL_DOMAIN; // Create person AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { createPerson(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeUsername, inviteeEmail); return null; } }, AuthenticationUtil.getSystemUserName()); JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_2, Status.STATUS_OK); } public void testCancelInvite() throws Exception { // inviter starts invite workflow JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of invite ID of started invite String inviteId = result.getString("inviteId"); // Inviter cancels pending invitation cancelInvite(inviteId, null, Status.STATUS_OK); } public void testAcceptInvite() throws Exception { // inviter starts invite (sends out invitation) JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of invite ID and invite ticket of started invite String inviteId = result.getString("inviteId"); String inviteTicket = result.getString("inviteTicket"); // Invitee accepts invitation to a Site from Inviter String acceptInviteUrl = URL_INVITE + "/" + inviteId + "/" + inviteTicket + "/accept"; sendRequest(new PutRequest(acceptInviteUrl, (byte[]) null, null), Status.STATUS_OK); // Invitee attempts to accept the invitation again sendRequest(new PutRequest(acceptInviteUrl, (byte[]) null, null), Status.STATUS_CONFLICT); // Invitee attempts to reject an invitation that has already been accepted. rejectInvite(inviteId, inviteTicket, Status.STATUS_CONFLICT); // // test that invitation represented by invite ID (of invitation started above) // is no longer pending (as a result of the invitation having being accepted) // // get pending invite matching inviteId from invite started above (run as inviter user) this.authenticationComponent.setCurrentUser(USER_INVITER); JSONObject getInvitesResult = getInvitesByInviteId(inviteId, Status.STATUS_OK); // there should no longer be any invites identified by invite ID pending //assertEquals(0, getInvitesResult.getJSONArray("invites").length()); } public void testRejectInvite() throws Exception { // inviter starts invite (sends out invitation) JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of invite ID of started invite String inviteId = result.getString("inviteId"); String inviteTicket = result.getString("inviteTicket"); rejectInvite(inviteId, inviteTicket, Status.STATUS_OK); // Negative test rejectInvite(inviteId, inviteTicket, Status.STATUS_CONFLICT); // // test that invite represented by invite ID (of invitation started above) // is no longer pending (as a result of the invitation having being rejected) // // get pending invite matching inviteId from invite started above (run as inviter user) this.authenticationComponent.setCurrentUser(USER_INVITER); JSONObject getInvitesResult = getInvitesByInviteId(inviteId, Status.STATUS_OK); // there should no longer be any invites identified by invite ID pending // assertEquals(0, getInvitesResult.getJSONArray("invites").length()); } public void testGetInvitationStatus() throws Exception { for (String invitationStatus : new String[] { InviteInfo.INVITATION_STATUS_REJECTED, InviteInfo.INVITATION_STATUS_ACCEPTED }) { // inviter starts invite (sends out invitation) JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); String inviteId = result.getString("inviteId"); String inviteTicket = result.getString("inviteTicket"); String inviteeUserName = result.getString("inviteeUserName"); // get inviteInfo about invitation result = getInviteInfo(inviteId, inviteTicket, inviteeUserName); // get status of current invitation String status = result.getJSONObject("invite").getString("invitationStatus"); // it should be peding assertEquals(status, InviteInfo.INVITATION_STATUS_PENDING); // accept/reject invitation if (invitationStatus.equals(InviteInfo.INVITATION_STATUS_REJECTED)) { rejectInvite(inviteId, inviteTicket, Status.STATUS_OK); } else if (invitationStatus.equals(InviteInfo.INVITATION_STATUS_ACCEPTED)) { // Invitee accepts invitation to a Site from Inviter String acceptInviteUrl = URL_INVITE + "/" + inviteId + "/" + inviteTicket + "/accept"; sendRequest(new PutRequest(acceptInviteUrl, (byte[]) null, null), Status.STATUS_OK); } else { fail(); } // get inviteInfo about invitation result = getInviteInfo(inviteId, inviteTicket, inviteeUserName); status = result.getJSONObject("invite").getString("invitationStatus"); // invitation status should be accepted/rejected assertEquals(status, invitationStatus); } } public void testGetInvitesByInviteId() throws Exception { // inviter starts invite workflow JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of workflow ID of started invite workflow instance String inviteId = startInviteResult.getString("inviteId"); assertEquals(true, ((inviteId != null) && (inviteId.length() != 0))); // get pending invite matching inviteId from invite started above JSONObject getInvitesResult = getInvitesByInviteId(inviteId, Status.STATUS_OK); assertEquals(getInvitesResult.getJSONArray("invites").length(), 1); JSONObject inviteJSONObj = getInvitesResult.getJSONArray("invites").getJSONObject(0); assertEquals(inviteId, inviteJSONObj.get("inviteId")); } public void testGetInvitesByInviterUserName() throws Exception { // inviter starts invite workflow startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get pending invites matching inviter user name used in invite started // above JSONObject getInvitesResult = getInvitesByInviterUserName(USER_INVITER, Status.STATUS_OK); assertEquals(true, getInvitesResult.length() > 0); JSONObject inviteJSONObj = getInvitesResult.getJSONArray("invites").getJSONObject(0); assertEquals(USER_INVITER, inviteJSONObj.getJSONObject("inviter").get("userName")); } public void testGetInvitesByInviteeUserName() throws Exception { // inviter starts invite workflow JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of invitee user name property of started invite workflow // instance String inviteeUserName = startInviteResult.getString("inviteeUserName"); assertEquals(true, ((inviteeUserName != null) && (inviteeUserName.length() != 0))); // get pending invites matching invitee user name from invite started // above JSONObject getInvitesResult = getInvitesByInviteeUserName(inviteeUserName, Status.STATUS_OK); assertEquals(true, getInvitesResult.length() > 0); JSONObject inviteJSONObj = getInvitesResult.getJSONArray("invites").getJSONObject(0); assertEquals(inviteeUserName, inviteJSONObj.getJSONObject("invitee").get("userName")); } public void testGetInvitesBySiteShortName() throws Exception { // inviter starts invite workflow JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of site short name property of started invite workflow // instance String siteShortName = startInviteResult.getString("siteShortName"); assertEquals(true, ((siteShortName != null) && (siteShortName.length() != 0))); // get pending invites matching site short name from invite started // above JSONObject getInvitesResult = getInvitesBySiteShortName(siteShortName, Status.STATUS_OK); assertEquals(true, getInvitesResult.getJSONArray("invites").length() > 0); JSONObject inviteJSONObj = getInvitesResult.getJSONArray("invites").getJSONObject(0); assertEquals(siteShortName, inviteJSONObj.getJSONObject("site").get("shortName")); } public void testStartInviteForbiddenWhenInviterNotSiteManager() throws Exception { // inviter2 starts invite workflow, but he/she is not the site manager of the given site AuthenticationUtil.setFullyAuthenticatedUser(USER_INVITER_2); startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_3, Status.STATUS_FORBIDDEN); } public void testCancelInviteForbiddenWhenInviterNotSiteManager() throws Exception { // inviter (who is Site Manager of the given site) starts invite workflow JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_3, Status.STATUS_OK); // get hold of invite ID of started invite String inviteId = result.getString("inviteId"); // when inviter 2 (who is not Site Manager of the given site) tries to cancel invite // http status FORBIDDEN must be returned AuthenticationUtil.setFullyAuthenticatedUser(USER_INVITER_2); cancelInvite(inviteId, null, Status.STATUS_FORBIDDEN); } public void testInviteeResourcesDeletedUponRejectWhenNoInvitePending() throws Exception { // inviter starts invite workflow JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of properties of started invite String inviteId = result.getString("inviteId"); String inviteTicket = result.getString("inviteTicket"); final String inviteeUserName = result.getString("inviteeUserName"); rejectInvite(inviteId, inviteTicket, Status.STATUS_OK); AuthenticationUtil.runAs(new RunAsWork<Void>() { public Void doWork() throws Exception { transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { public Void execute() throws Throwable { assertEquals(false, mutableAuthenticationDao.userExists(inviteeUserName)); assertEquals(false, personService.personExists(inviteeUserName)); return null; } }); return null; } }, AuthenticationUtil.getSystemUserName()); } public void testInviteeResourcesNotDeletedUponRejectWhenInvitesPending() throws Exception { // Test only applies to legacy invite workflow this.invitationServiceImpl.setNominatedInvitationWorkflowId( WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI_INVITE); // Create invitee person final String inviteeEmail = INVITEE_EMAIL_PREFIX + RandomStringUtils.randomAlphanumeric(6) + "@" + INVITEE_EMAIL_DOMAIN; AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { createPerson(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_FIRSTNAME + "_" + INVITEE_LASTNAME, inviteeEmail); return null; } }, AuthenticationUtil.getSystemUserName()); // inviter invites invitee to site 1 JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); // get hold of properties of started invite String invite1Id = result.getString("inviteId"); String invite1Ticket = result.getString("inviteTicket"); final String inviteeUserName = result.getString("inviteeUserName"); // inviter invites invitee to site 2 startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_2, Status.STATUS_OK); rejectInvite(invite1Id, invite1Ticket, Status.STATUS_OK); boolean inviteeUserExists = AuthenticationUtil.runAs(new RunAsWork<Boolean>() { public Boolean doWork() throws Exception { RetryingTransactionHelper tranHelper = transactionService.getRetryingTransactionHelper(); Boolean result = tranHelper.doInTransaction(new RetryingTransactionCallback<Boolean>() { public Boolean execute() throws Throwable { Boolean result = mutableAuthenticationDao.userExists(inviteeUserName); return result; } }); return result; } }, AuthenticationUtil.getSystemUserName()); // test that the invitee's user account still exists (has not been deleted assertEquals(true, inviteeUserExists); boolean inviteePersonExists = AuthenticationUtil.runAs(new RunAsWork<Boolean>() { public Boolean doWork() throws Exception { Boolean result = personService.personExists(inviteeUserName); return result; } }, AuthenticationUtil.getSystemUserName()); assertEquals(true, inviteePersonExists); // Reset back to default this.invitationServiceImpl.setNominatedInvitationWorkflowId( WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI_ADD_DIRECT); } /** * https://issues.alfresco.com/jira/browse/ETHREEOH-520 */ public void testETHREEOH_520() throws Exception { final String userName = "userInviteServiceTest" + GUID.generate(); final String emailAddress = " "; // Create a person with a blank email address and AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { createPerson(PERSON_FIRSTNAME, PERSON_LASTNAME, userName, " "); return null; } }, AuthenticationUtil.getSystemUserName()); // Try and add an existing person to the site with no email address // Should return bad request since the email address has not been provided startInvite(PERSON_FIRSTNAME, PERSON_LASTNAME, emailAddress, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, 400); } public void testMNT9905() throws Exception { String[] managerUsersArr = { "user1", "user2" }; String[] allUsersArr = { "user1", "user2", "user3", "user4" }; String collaborator = "user3"; try { // create users for (String user : allUsersArr) { final String userName = user; // Create a person with a blank email address and AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { createPerson(userName, userName, userName, ""); return null; } }, AuthenticationUtil.getSystemUserName()); } // add manager to site for (String manager : managerUsersArr) { String manag = manager; startInvite(manag, manag, SiteModel.SITE_MANAGER, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); siteService.setMembership(SITE_SHORT_NAME_INVITE_1, manag, SiteModel.SITE_MANAGER); } InviteServiceTest.this.authenticationComponent.setCurrentUser(managerUsersArr[0]); JSONObject collInv = startInvite(collaborator, collaborator, SiteModel.SITE_COLLABORATOR, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); siteService.setMembership(SITE_SHORT_NAME_INVITE_1, collaborator, SiteModel.SITE_COLLABORATOR); // get pending invites matching inviter user name used in invite started InviteServiceTest.this.authenticationComponent.setCurrentUser(managerUsersArr[1]); JSONObject getInvitesResult = getInvitesBySiteShortName(SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); assertEquals(true, getInvitesResult.length() == 1); // get site member JSONObject userList = listInvitations(SITE_SHORT_NAME_INVITE_1, "user", Status.STATUS_OK); JSONArray inviteJSONArr = userList.getJSONArray("people"); List<String> siteUsers = new ArrayList<String>(); for (int i = 0; i < inviteJSONArr.length(); i++) { String userName = (String) inviteJSONArr.getJSONObject(i).get("userName"); if (userName != null) { String role = siteService.getMembersRole(SITE_SHORT_NAME_INVITE_1, userName); if (role != null) { siteUsers.add(userName); } } } // MNT-14113: User admin console: sorting users causes some to disappear // // It was decided to make the search results of AFTS (indexed) search to be the // same as the CQ search results. Therefore, 'People.getPeople(String filter)' // transforms 'filter' to '*<filter>*' (adds leading wildcard). // 'InviterUser' is the creator of the test site (see the 'setUp()' method). // Thus, plus one more user ('user1', 'user2', 'user3' and the creator // 'InviterUser') assertEquals(4, siteUsers.size()); // cancel invite different manager String inviteId = (String) collInv.get("inviteId"); cancelInvite(inviteId, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK); } finally { AuthenticationUtil.setRunAsUserSystem(); // delete users for (String user : allUsersArr) { deletePersonByUserName(user); } deletePersonByUserName(collaborator); } } @Test public void testDontOwerrideModeratedSitePermissions() throws Exception { final String MODERATED_SITE_NAME = RandomStringUtils.randomAlphabetic(6); final String siteManager = RandomStringUtils.randomAlphabetic(6); final String secondUser = RandomStringUtils.randomAlphabetic(6); // Create two users AuthenticationUtil.runAs(new RunAsWork<Object>() { public Object doWork() throws Exception { createPerson(siteManager, siteManager, siteManager, ""); createPerson(secondUser, secondUser, secondUser, ""); return null; } }, AuthenticationUtil.getSystemUserName()); // Create moderated site SiteInfo siteInfo = InviteServiceTest.this.siteService.getSite(MODERATED_SITE_NAME); if (siteInfo == null) { siteService.createSite("InviteSitePreset", MODERATED_SITE_NAME, MODERATED_SITE_NAME, MODERATED_SITE_NAME, SiteVisibility.MODERATED); } siteService.setMembership(MODERATED_SITE_NAME, siteManager, SiteModel.SITE_MANAGER); String role = siteService.getMembersRole(MODERATED_SITE_NAME, siteManager); assertEquals(SiteModel.SITE_MANAGER, role); // Create request to join to site String inviteId = createModeratedInvitation(MODERATED_SITE_NAME, "", secondUser, SiteModel.SITE_CONSUMER); // Set second user to Collaborator siteService.setMembership(MODERATED_SITE_NAME, secondUser, SiteModel.SITE_COLLABORATOR); role = siteService.getMembersRole(MODERATED_SITE_NAME, secondUser); assertEquals(SiteModel.SITE_COLLABORATOR, role); final String taskId = getTaskId(inviteId); assertNotNull("Cannot find taskId", taskId); // Accept invitation String oldUser = AuthenticationUtil.getFullyAuthenticatedUser(); AuthenticationUtil.setFullyAuthenticatedUser(siteManager); workflowService.endTask(taskId, "approve"); AuthenticationUtil.setFullyAuthenticatedUser(oldUser); // Check the role role = siteService.getMembersRole(MODERATED_SITE_NAME, secondUser); assertEquals(SiteModel.SITE_COLLABORATOR, role); } private String createModeratedInvitation(String siteName, String inviteeComments, String inviteeUserName, String inviteeRoleName) throws Exception { String URL_SITES = "/api/sites"; /* * Create a new moderated invitation */ JSONObject newInvitation = new JSONObject(); newInvitation.put("invitationType", "MODERATED"); newInvitation.put("inviteeRoleName", inviteeRoleName); newInvitation.put("inviteeComments", inviteeComments); newInvitation.put("inviteeUserName", inviteeUserName); Response response = sendRequest(new PostRequest(URL_SITES + "/" + siteName + "/invitations", newInvitation.toString(), "application/json"), 201); JSONObject top = new JSONObject(response.getContentAsString()); JSONObject data = top.getJSONObject("data"); String inviteId = data.getString("inviteId"); return inviteId; } private String getTaskId(String inviteId) throws Exception { String url = "/api/task-instances"; Response response = sendRequest(new GetRequest(url), 200); JSONObject top = new JSONObject(response.getContentAsString()); JSONArray data = top.getJSONArray("data"); for (int i = 0; i < data.length(); i++) { JSONObject task = data.getJSONObject(i); JSONObject workflowInstance = task.getJSONObject("workflowInstance"); if (!inviteId.equalsIgnoreCase(workflowInstance.getString("id"))) { continue; } return task.getString("id"); } return null; } }