diff --git a/config/alfresco/templates/activities/org/alfresco/site/user-joined.atomentry.ftl b/config/alfresco/templates/activities/org/alfresco/site/user-joined.atomentry.ftl new file mode 100644 index 0000000000..3d3eb53e3f --- /dev/null +++ b/config/alfresco/templates/activities/org/alfresco/site/user-joined.atomentry.ftl @@ -0,0 +1,11 @@ + + ${memberFirstName}<#if memberLastName??> ${memberLastName}</#if> joined ${siteNetwork} site + + + ${id} + ${xmldate(date)} + ${memberFirstName}<#if memberLastName??> ${memberLastName} joined ${siteNetwork} site (with role ${role}) + + ${userId} + + \ No newline at end of file diff --git a/config/alfresco/templates/activities/org/alfresco/site/user-left.atomentry.ftl b/config/alfresco/templates/activities/org/alfresco/site/user-left.atomentry.ftl new file mode 100644 index 0000000000..37450c83d2 --- /dev/null +++ b/config/alfresco/templates/activities/org/alfresco/site/user-left.atomentry.ftl @@ -0,0 +1,11 @@ + + ${memberFirstName}<#if memberLastName??> ${memberLastName}</#if> left ${siteNetwork} site + + + ${id} + ${xmldate(date)} + ${memberFirstName}<#if memberLastName??> ${memberLastName} left ${siteNetwork} site + + ${userId} + + \ No newline at end of file diff --git a/config/alfresco/templates/activities/org/alfresco/site/user-role-changed.atomentry.ftl b/config/alfresco/templates/activities/org/alfresco/site/user-role-changed.atomentry.ftl new file mode 100644 index 0000000000..8c806fec20 --- /dev/null +++ b/config/alfresco/templates/activities/org/alfresco/site/user-role-changed.atomentry.ftl @@ -0,0 +1,11 @@ + + ${memberFirstName}<#if memberLastName??> ${memberLastName}</#if> role changed for ${siteNetwork} site + + + ${id} + ${xmldate(date)} + ${memberFirstName}<#if memberLastName??> ${memberLastName} role changed to ${role} for ${siteNetwork} site + + ${userId} + + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/activities/SiteActivitySystemTest.java b/source/java/org/alfresco/repo/web/scripts/activities/SiteActivitySystemTest.java new file mode 100644 index 0000000000..8fb9048467 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/activities/SiteActivitySystemTest.java @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2005-2008 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.web.scripts.activities; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Date; + +import junit.framework.TestCase; + +import org.alfresco.repo.site.SiteModel; +import org.alfresco.util.Base64; +import org.alfresco.util.ISO8601DateFormat; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; +import org.json.JSONObject; + +/** + * Simple Activity Service system test (requires remote repo to be running) using site (membership) activities + * + * @author janv + */ +public class SiteActivitySystemTest extends TestCase +{ + private static Log logger = LogFactory.getLog(SiteActivitySystemTest.class); + + // TODO - use test property file + private static final String REPO = "http://localhost:8080/alfresco"; + + // web service (SOAP) - temporary (see below) + private static final String WEBSERVICE_ENDPOINT = REPO + "/api"; + + private static final String URL_AUTH = "/AuthenticationService"; + private static final String URL_ADMIN = "/AdministrationService"; + + // web script (REST) + private static final String WEBSCRIPT_ENDPOINT = REPO + "/service"; + + // Site Service part-URLs + private static final String URL_SITES = "/api/sites"; + private static final String URL_MEMBERSHIPS = "/memberships"; + + // Activity Service part-URLs + private static final String URL_ACTIVITIES = "/api/activities"; + private static final String URL_SITE_FEED = "/feed/site"; + private static final String URL_USER_FEED = "/feed/user"; + + + private static boolean setup = false; + + private static String shortName = null; + private static String user1 = null; + private static String user2 = null; + private static String user3 = null; + + + public SiteActivitySystemTest() + { + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + if (! setup) + { + String testid = ""+System.currentTimeMillis(); + + shortName = "testSite_" + testid; + user1 = "testSite_user1_" + testid; + user2 = "testSite_user2_" + testid; + user3 = "testSite_user3_" + testid; + + // pre-create users + + createUser(user1, "password"); + createUser(user2, "password"); + createUser(user3, "password"); + + setup = true; + } + + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + } + + public void testCreateSite() throws Exception + { + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + JSONObject site = new JSONObject(); + site.put("sitePreset", "myPreset"); + site.put("shortName", shortName); + site.put("title", "myTitle"); + site.put("description", "myDescription"); + site.put("isPublic", true); + + String url = WEBSCRIPT_ENDPOINT + URL_SITES; + String response = callPostWebScript(url, ticket, site.toString()); + + if (logger.isDebugEnabled()) + { + logger.debug("testCreateSite"); + logger.debug("--------------"); + logger.debug(url); + logger.debug(response); + } + } + + public void testGetSite() throws Exception + { + // relies on testCreateSite + + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + String url = WEBSCRIPT_ENDPOINT + URL_SITES + "/" + shortName; + String response = callGetWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("testGetSite"); + logger.debug("-----------"); + logger.debug(url); + logger.debug(response); + } + } + + public void testGetSiteFeed1() throws Exception + { + // relies on testCreateSite + + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + String url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_SITE_FEED + "/" + shortName + "?format=json"; + String jsonArrayResult = callGetWebScript(url, ticket); + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(0, ja.length()); + } + else + { + fail("Error getting site feed"); + } + } + + public void testGetUserFeeds1_asAdmin() throws Exception + { + // relies on testCreateSite + + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + String url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_USER_FEED + "/" + user1 + "?format=json"; + String jsonArrayResult = callGetWebScript(url, ticket); + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(0, ja.length()); + } + else + { + fail("Error getting user feed"); + } + + url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_USER_FEED + "/" + user2 + "?format=json"; + jsonArrayResult = callGetWebScript(url, ticket); + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(0, ja.length()); + } + else + { + fail("Error getting user feed"); + } + + url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_USER_FEED + "/" + user3 + "?format=json"; + jsonArrayResult = callGetWebScript(url, ticket); + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(0, ja.length()); + } + else + { + fail("Error getting user feed"); + } + } + + public void testMemberships() throws Exception + { + // relies on testCreateSite + + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + // add member -> join site + testAddMembership(user1, ticket, SiteModel.SITE_CONSUMER); + testAddMembership(user2, ticket, SiteModel.SITE_MANAGER); + testAddMembership(user3, ticket, SiteModel.SITE_COLLABORATOR); + + // update member -> change role + testUpdateMembership(user1, ticket, SiteModel.SITE_MANAGER); + testUpdateMembership(user2, ticket, SiteModel.SITE_COLLABORATOR); + testUpdateMembership(user3, ticket, SiteModel.SITE_CONSUMER); + + // add pause - otherwise, activity service will not generate feed entries (since they will have already left the site) + Thread.sleep(90000); // 1 min + + // remove member -> leave site + testRemoveMembership(user1, ticket); + testRemoveMembership(user2, ticket); + testRemoveMembership(user3, ticket); + + // add pause + Thread.sleep(60000); // 1 min + } + + public void testGetSiteFeed2() throws Exception + { + // relies on testCreateSite, testMemberships + + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + String url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_SITE_FEED + "/" + shortName + "?format=json"; + String jsonArrayResult = callGetWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("testGetSiteFeed2"); + logger.debug("----------------"); + logger.debug(url); + logger.debug(jsonArrayResult); + } + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(9, ja.length()); + } + else + { + fail("Error getting site feed"); + } + } + + public void testGetUserFeeds2_asAdmin() throws Exception + { + // relies on testCreateSite, testMemberships + + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, "admin", "admin"); + + String url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_USER_FEED + "/" + user1 + "?format=json"; + String jsonArrayResult = callGetWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("testGetUserFeeds2_asAdmin: user1"); + logger.debug("--------------------------"); + logger.debug(url); + logger.debug(jsonArrayResult); + } + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(6, ja.length()); + } + else + { + fail("Error getting user feed"); + } + + url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_USER_FEED + "/" + user2 + "?format=json"; + jsonArrayResult = callGetWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("testGetUserFeeds2_asAdmin: user2"); + logger.debug("--------------------------"); + logger.debug(url); + logger.debug(jsonArrayResult); + } + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(6, ja.length()); + } + else + { + fail("Error getting user feed"); + } + + url = WEBSCRIPT_ENDPOINT + URL_ACTIVITIES + URL_USER_FEED + "/" + user3 + "?format=json"; + jsonArrayResult = callGetWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("testGetUserFeeds2_asAdmin: user3"); + logger.debug("--------------------------"); + logger.debug(url); + logger.debug(jsonArrayResult); + } + + if (jsonArrayResult != null) + { + JSONArray ja = new JSONArray(jsonArrayResult); + assertEquals(6, ja.length()); + } + else + { + fail("Error getting user feed"); + } + } + + private void testAddMembership(String userName, String ticket, String role) throws Exception + { + // Build the JSON membership object + JSONObject membership = new JSONObject(); + membership.put("role", role); + JSONObject person = new JSONObject(); + person.put("userName", userName); + membership.put("person", person); + + String url = WEBSCRIPT_ENDPOINT + URL_SITES + "/" + shortName + URL_MEMBERSHIPS; + String response = callPostWebScript(url, ticket, membership.toString()); + + if (logger.isDebugEnabled()) + { + logger.debug("testAddMembership: " + userName); + logger.debug("------------------"); + logger.debug(url); + logger.debug(response); + } + } + + private void testUpdateMembership(String userName, String ticket, String role) throws Exception + { + // Build the JSON membership object + JSONObject membership = new JSONObject(); + membership.put("role", role); + JSONObject person = new JSONObject(); + person.put("userName", userName); + membership.put("person", person); + + String url = WEBSCRIPT_ENDPOINT + URL_SITES + "/" + shortName + URL_MEMBERSHIPS + "/" + userName; + String response = callPutWebScript(url, ticket, membership.toString()); + + if (logger.isDebugEnabled()) + { + logger.debug("testUpdateMembership: " + userName); + logger.debug("------------------"); + logger.debug(url); + logger.debug(response); + } + } + + private void testRemoveMembership(String userName, String ticket) throws Exception + { + String url = WEBSCRIPT_ENDPOINT + URL_SITES + "/" + shortName + URL_MEMBERSHIPS + "/" + userName; + String response = callDeleteWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("testRemoveMembership: " + userName); + logger.debug("---------------------"); + logger.debug(url); + logger.debug(response); + } + } + + protected String callGetWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + return callOutWebScript(urlString, "GET", ticket); + } + + protected String callDeleteWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + return callOutWebScript(urlString, "DELETE", ticket); + } + + protected String callPostWebScript(String urlString, String ticket, String data) throws MalformedURLException, URISyntaxException, IOException + { + return callInOutWebScript(urlString, "POST", ticket, data); + } + + protected String callPutWebScript(String urlString, String ticket, String data) throws MalformedURLException, URISyntaxException, IOException + { + return callInOutWebScript(urlString, "PUT", ticket, data); + } + + private String callOutWebScript(String urlString, String method, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + URL url = new URL(urlString); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod(method); + + if (ticket != null) + { + // add Base64 encoded authorization header + // refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication + conn.addRequestProperty("Authorization", "Basic " + Base64.encodeBytes(ticket.getBytes())); + } + + String result = null; + InputStream is = null; + BufferedReader br = null; + + try + { + is = conn.getInputStream(); + br = new BufferedReader(new InputStreamReader(is)); + + String line = null; + StringBuffer sb = new StringBuffer(); + while(((line = br.readLine()) !=null)) { + sb.append(line); + } + + result = sb.toString(); + } + finally + { + if (br != null) { br.close(); }; + if (is != null) { is.close(); }; + } + + return result; + } + + private String callInOutWebScript(String urlString, String method, String ticket, String data) throws MalformedURLException, URISyntaxException, IOException + { + return callInOutWeb(urlString, method, ticket, data, "application/json", null); + } + + private String callInOutWeb(String urlString, String method, String ticket, String data, String contentType, String soapAction) throws MalformedURLException, URISyntaxException, IOException + { + URL url = new URL(urlString); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod(method); + + conn.setRequestProperty("Content-type", contentType); + + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setUseCaches (false); + + if (soapAction != null) + { + conn.setRequestProperty("SOAPAction", soapAction); + } + + if (ticket != null) + { + // add Base64 encoded authorization header + // refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication + conn.addRequestProperty("Authorization", "Basic " + Base64.encodeBytes(ticket.getBytes())); + } + + String result = null; + BufferedReader br = null; + DataOutputStream wr = null; + OutputStream os = null; + InputStream is = null; + + try + { + os = conn.getOutputStream(); + wr = new DataOutputStream(os); + wr.write(data.getBytes()); + wr.flush(); + } + finally + { + if (wr != null) { wr.close(); }; + if (os != null) { os.close(); }; + } + + try + { + is = conn.getInputStream(); + br = new BufferedReader(new InputStreamReader(is)); + + String line = null; + StringBuffer sb = new StringBuffer(); + while(((line = br.readLine()) !=null)) + { + sb.append(line); + } + + result = sb.toString(); + } + finally + { + if (br != null) { br.close(); }; + if (is != null) { is.close(); }; + } + + return result; + } + + protected String callLoginWebScript(String serviceUrl, String username, String password) throws MalformedURLException, URISyntaxException, IOException + { + // Refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication + String ticketResult = callGetWebScript(serviceUrl+"/api/login?u="+username+"&pw="+password, null); + + if (ticketResult != null) + { + int startTag = ticketResult.indexOf(""); + int endTag = ticketResult.indexOf(""); + if ((startTag != -1) && (endTag != -1)) + { + ticketResult = ticketResult.substring(startTag+("".length()), endTag); + } + } + + return ticketResult; + } + + // TODO - replace with Create Person REST API when it becomes available + + protected void createUser(String username, String password) throws MalformedURLException, URISyntaxException, IOException + { + String ticket = webServiceStartSession("admin", "admin"); + webServiceCreateUser(username, password, ticket); + webServiceEndSession(ticket); + } + + private String webServiceStartSession(String username, String password) throws MalformedURLException, URISyntaxException, IOException + { + String soapCall = + ""+ + ""+ + ""+ + ""+username+""+ + ""+password+""+ + ""; + + String response = callInOutWeb(WEBSERVICE_ENDPOINT + URL_AUTH, "POST", null, soapCall, "text/xml; charset=utf-8", "\"http://www.alfresco.org/ws/service/authentication/1.0/startSession\""); + + String ticket = null; + + if (response != null) + { + int idx1 = response.indexOf(""); + if (idx1 != -1) + { + int idx2 = response.indexOf(""); + if (idx2 != -1) + { + ticket = response.substring(idx1+"".length(), idx2); + } + } + } + + return ticket; + } + + private void webServiceCreateUser(String username, String password, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + Date now = new Date(); + String startTime = ISO8601DateFormat.format(now); + String expireTime = ISO8601DateFormat.format(new Date(now.getTime() + 5*60*1000)); + + String soapCall = + ""+ + ""+ + ""+ + ""+ + ""+startTime+""+expireTime+""+ + "ticket"+ticket+""+ + ""+ + ""+username+""+password+""+ + "{http://www.alfresco.org/model/content/1.0}homeFolder"+ + "false"+ + "workspace:////SpacesStore" + + "{http://www.alfresco.org/model/content/1.0}firstName"+ + "false"+ + ""+"FN_"+username+""+ + "{http://www.alfresco.org/model/content/1.0}middleName"+ + "false"+ + ""+ + "{http://www.alfresco.org/model/content/1.0}lastName"+ + "false" + + ""+"LN_"+username+"" + + "{http://www.alfresco.org/model/content/1.0}email"+ + "false"+ + "email1210929178773"+ + "{http://www.alfresco.org/model/content/1.0}organizationId"+ + "false"+ + "org1210929178773"; + + callInOutWeb(WEBSERVICE_ENDPOINT + URL_ADMIN, "POST", null, soapCall, "text/xml; charset=utf-8", "\"http://www.alfresco.org/ws/service/administration/1.0/createUsers\""); // ignore response + } + + private void webServiceEndSession(String ticket) throws MalformedURLException, URISyntaxException, IOException + { + String soapCall = + ""+ + ""+ + ""+ + ""+ticket+""+ + ""; + + callInOutWeb(WEBSERVICE_ENDPOINT + URL_AUTH, "POST", null, soapCall, "text/xml; charset=utf-8", "\"http://www.alfresco.org/ws/service/authentication/1.0/endSession\""); // ignore response + } +}