diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl
new file mode 100644
index 0000000000..c284191f19
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/authority.lib.ftl
@@ -0,0 +1,12 @@
+<#-- renders an authority object which can be either a GROUP or USER (and possibly ROLE in future)-->
+<#macro formJSON authority>
+ <#escape x as jsonUtils.encodeJSONString(x)>
+{
+ "authorityType" : "${authority.authorityType}",
+ "shortName" : "${authority.shortName}",
+ "fullName" : "${authority.fullName}",
+ "displayName" : "${authority.displayName}",
+ "url" : "/api/groups/${authority.shortName}"
+}
+ #escape>
+#macro>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.desc.xml
new file mode 100644
index 0000000000..bd7c9d6835
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.desc.xml
@@ -0,0 +1,14 @@
+
+ Get the list of child authorities for a group.
+
+
+ /api/groups/{shortName}/children?authorityType={authorityType?}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.json.ftl
new file mode 100644
index 0000000000..a418c831ce
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.get.json.ftl
@@ -0,0 +1 @@
+<#import "authority.lib.ftl" as authorityLib/>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.desc.xml
new file mode 100644
index 0000000000..e0b4db89de
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.desc.xml
@@ -0,0 +1,14 @@
+
+ Add group or user to a group
+
+
+ /api/groups/{shortName}/children
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/children.post.json.ftl
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.desc.xml
new file mode 100644
index 0000000000..5809b1b3fe
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.desc.xml
@@ -0,0 +1,12 @@
+
+ Get the details of a group
+
+
+ /api/groups/{shortName}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.get.json.ftl
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.desc.xml
new file mode 100644
index 0000000000..cb504873db
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.desc.xml
@@ -0,0 +1,17 @@
+
+ Update the details of a group
+
+ displayNameThe display name
+
+ ]]>
+
+ /api/groups/{shortName}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/group.put.json.ftl
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.desc.xml
new file mode 100644
index 0000000000..32a529619b
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.desc.xml
@@ -0,0 +1,12 @@
+
+ Delete a group.
+
+
+ /api/groups/{shortName}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.delete.json.ftl
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.desc.xml
new file mode 100644
index 0000000000..a02c23e24c
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.desc.xml
@@ -0,0 +1,20 @@
+
+ List groups
+
+ Parameters
+
+ - if the optional includeInternal parameter is true then will include internal groups, otherwise internalGroups are not returned.
+ - If the optional shortNameFilter parameter is set then returns those root groups with a partial match on shortName.
+
+
+ Returns an Array of groups in JSON format.
+ ]]>
+
+ /api/groups?shortNameFilter={shortNameFilter?}&includeInternal={includeInternal?}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/groups.get.json.ftl
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.desc.xml
new file mode 100644
index 0000000000..b2ca586cd2
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.desc.xml
@@ -0,0 +1,14 @@
+
+ Get the list of child authorities for a group.
+
+
+ /api/groups/{shortName}/parents?level={level?}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.json.ftl
new file mode 100644
index 0000000000..a418c831ce
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/parent.get.json.ftl
@@ -0,0 +1 @@
+<#import "authority.lib.ftl" as authorityLib/>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.desc.xml
new file mode 100644
index 0000000000..a27d4840e4
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.desc.xml
@@ -0,0 +1,15 @@
+
+ List all root groups
+
+
+ /api/rootgroups?shortNameFilter={shortNameFilter?}&includeInternal={includeInternal?}
+ argument
+ user
+ required
+ draft_public_api
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.js
new file mode 100644
index 0000000000..bbb4436636
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.js
@@ -0,0 +1 @@
+// get rootgroups
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/groups/rootgroups.get.json.ftl
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.desc.xml
new file mode 100644
index 0000000000..8729cc8ec3
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.desc.xml
@@ -0,0 +1,26 @@
+
+ List Invitations
+
+ With no parameters, returns all open invitations (which could be a large number).
+
+ With inviteeUserName, returns all open invitations for this invitee.
+
+ With invitationType, returns invitations of the specified type (Either NOMINATED or MODERATED).
+
+ With resourceType, returns invitations of the specified type (WEB_SITE only at the moment).
+
+
+
+ Returns a JSON array of Invitations.
+
+
+ ]]>
+
+ /api/invitations?inviteeUserName={inviteeUserName?}&invitationType={invitationType?}&resourceType={resourceType?}
+
+ draft_public_api
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.js
new file mode 100644
index 0000000000..541f89f566
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.js
@@ -0,0 +1,42 @@
+/**
+ * List/Search invitations implementation
+ */
+
+function main ()
+{
+ // Get the site id
+ var urlElements = url.extension.split("/");
+ var shortName = urlElements[0];
+
+ // Get the args
+ var inviteeUserName = args["inviteeUserName"];
+ var invitationType = args["invitationType"];
+ var resourceType = args["resourceType"];
+ var resourceName = args["resourceName"];
+
+ var props = {};
+
+ if(inviteeUserName != null)
+ {
+ props.inviteeUserName = inviteeUserName
+ }
+ if(invitationType != null)
+ {
+ props.invitationType = invitationType
+ }
+ if(resourceType != null)
+ {
+ props.resourceType = resourceType
+ }
+ if(resourceName != null)
+ {
+ props.resourceName = resourceName
+ }
+
+ var invites = invitations.listInvitations(props);
+
+ // Pass the information to the template
+ model.invitations = invites;
+}
+
+main();
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.json.ftl
new file mode 100644
index 0000000000..1f422f89e8
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/invitation/invitations.get.json.ftl
@@ -0,0 +1,11 @@
+<#-- list / search / invitations -->
+
+<#import "invitation.lib.ftl" as invitationLib/>
+{
+ "data": [
+ <#list invitations as invitation>
+ <@invitationLib.invitationJSON invitation=invitation />
+ <#if invitation_has_next>,#if>
+ #list>
+ ]
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/invitation/InvitationTest.java b/source/java/org/alfresco/repo/web/scripts/invitation/InvitationTest.java
new file mode 100644
index 0000000000..4e508eeabd
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/invitation/InvitationTest.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2005-2007 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.invitation;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.AuthenticationService;
+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.QName;
+import org.alfresco.util.GUID;
+import org.alfresco.util.PropertyMap;
+import org.alfresco.web.scripts.Status;
+import org.alfresco.web.scripts.TestWebScriptServer.DeleteRequest;
+import org.alfresco.web.scripts.TestWebScriptServer.GetRequest;
+import org.alfresco.web.scripts.TestWebScriptServer.PostRequest;
+import org.alfresco.web.scripts.TestWebScriptServer.PutRequest;
+import org.alfresco.web.scripts.TestWebScriptServer.Response;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ * Unit test of Invitation REST API.
+ *
+ * @See SiteServiceTest.java which tests invitations to Web sites.
+ *
+ * @author Mark Rogers
+ */
+public class InvitationTest extends BaseWebScriptTest
+{
+ private AuthenticationService authenticationService;
+ private AuthenticationComponent authenticationComponent;
+ private PersonService personService;
+ private SiteService siteService;
+ private NodeService nodeService;
+
+ private static final String USER_ONE = "InvitationTestOne";
+ private static final String USER_TWO = "InvitationTestTwo";
+ private static final String USER_THREE = "InvitationTestThree";
+
+ private static final String URL_SITES = "/api/sites";
+ private static final String URL_INVITATIONS = "/api/invitations";
+
+
+ private List createdSites = new ArrayList(5);
+ private List createdInvitations = new ArrayList(10);
+
+ private class Tracker
+ {
+ public Tracker(String inviteId, String siteName)
+ {
+ this.inviteId = inviteId;
+ this.siteName = siteName;
+ }
+ public String inviteId;
+ public String siteName;
+ }
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ this.authenticationService = (AuthenticationService)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.authenticationComponent.setSystemUserAsCurrentUser();
+
+ // Create users
+ createUser(USER_ONE);
+ createUser(USER_TWO);
+ createUser(USER_THREE);
+
+ // Do tests as user one
+ 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);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
+
+ // 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();
+
+ for (Tracker invite : this.createdInvitations)
+ {
+ sendRequest(new DeleteRequest(URL_SITES + "/" + invite.siteName + "/invitations/" + invite.inviteId), 0);
+ }
+
+ // Clear the list
+ this.createdSites.clear();
+ }
+
+ 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());
+ }
+
+ /**
+ * Detailed Test of List Invitation Web Script.
+ * @throws Exception
+ */
+ public void testListInvitation() throws Exception
+ {
+ // Create two sites.
+ String shortNameSiteA = GUID.generate();
+ createSite("myPreset", shortNameSiteA, "myTitle", "myDescription", SiteVisibility.PUBLIC, 200);
+
+ String shortNameSiteB = GUID.generate();
+ createSite("myPreset", shortNameSiteB, "myTitle", "myDescription", SiteVisibility.PUBLIC, 200);
+
+ // Create a moderated invitation on SiteA, USER_TWO
+ String inviteeComments = "Please sir, let $* me in";
+ String userName = USER_TWO;
+ String roleName = SiteModel.SITE_CONSUMER;
+ String moderatedIdAUSER_TWO = createModeratedInvitation(shortNameSiteA, inviteeComments, userName, roleName);
+
+ // Create a moderated invitation on SiteB, USER_TWO
+ String moderatedIdBUSER_TWO = createModeratedInvitation(shortNameSiteB, inviteeComments, userName, roleName);
+
+ String inviteeCommentsB = "Please sir, let $* me in";
+ String userNameB = USER_THREE;
+ String roleNameB = SiteModel.SITE_CONSUMER;
+ String moderatedIdBUSER_THREE = createModeratedInvitation(shortNameSiteA, inviteeCommentsB, userNameB, roleNameB);
+
+ String inviteeFirstName = "Buffy";
+ String inviteeLastName = "Summers";
+ String inviteeEmail = "buffy@sunnydale";
+ String inviteeUserName = userName;
+ String serverPath = "http://localhost:8081/share/";
+ String acceptURL = "page/accept-invite";
+ String rejectURL = "page/reject-invite";
+
+ // Create a nominated invitation
+ String nominatedId = createNominatedInvitation(shortNameSiteA, inviteeFirstName, inviteeLastName, inviteeEmail, inviteeUserName, roleName, serverPath, acceptURL, rejectURL);
+
+ /**
+ * search by user - find USER_TWO's three invitations
+ */
+ {
+ Response response = sendRequest(new GetRequest(URL_INVITATIONS + "?inviteeUserName=" + USER_TWO), 200);
+ JSONObject top = new JSONObject(response.getContentAsString());
+ //System.out.println(response.getContentAsString());
+ JSONArray data = top.getJSONArray("data");
+
+ JSONObject first = getInvitation(moderatedIdAUSER_TWO, data);
+ assertNotNull("first is null", first);
+ JSONObject second = getInvitation(moderatedIdBUSER_TWO, data);
+ assertNotNull("second is null", second);
+ JSONObject third = getInvitation(nominatedId, data);
+ assertNotNull("third is null", third);
+
+ for(int i = 0; i < data.length(); i++)
+ {
+ JSONObject obj = data.getJSONObject(i);
+ assertEquals("userid is wrong", obj.getString("inviteeUserName"), USER_TWO);
+ }
+ }
+
+ /**
+ * search by type - should find three moderated invitations
+ */
+
+ {
+ Response response = sendRequest(new GetRequest(URL_INVITATIONS + "?invitationType=MODERATED"), 200);
+ JSONObject top = new JSONObject(response.getContentAsString());
+ //System.out.println(response.getContentAsString());
+ JSONArray data = top.getJSONArray("data");
+ for(int i = 0; i < data.length(); i++)
+ {
+ JSONObject obj = data.getJSONObject(i);
+ assertEquals("invitation type ", obj.getString("invitationType"), "MODERATED");
+ }
+ JSONObject first = getInvitation(moderatedIdAUSER_TWO, data);
+ assertNotNull("first is null", first);
+ JSONObject second = getInvitation(moderatedIdBUSER_TWO, data);
+ assertNotNull("second is null", second);
+ JSONObject third = getInvitation(moderatedIdBUSER_THREE, data);
+ assertNotNull("third is null", third);
+ }
+
+ /**
+ * Search by type and site
+ */
+
+ {
+ Response response = sendRequest(new GetRequest(URL_INVITATIONS + "?invitationType=MODERATED&resourceName="+shortNameSiteA+ "&resourceType=WEB_SITE"), 200);
+ JSONObject top = new JSONObject(response.getContentAsString());
+ System.out.println(response.getContentAsString());
+ JSONArray data = top.getJSONArray("data");
+ assertEquals("two moderated invitations not found", data.length(), 2);
+ }
+
+ // negative test - unknown resourceType
+ {
+ sendRequest(new GetRequest(URL_INVITATIONS + "?invitationType=MODERATED&resourceName="+shortNameSiteA+ "&resourceType=crap"), 500);
+ }
+
+ }
+
+
+ private String createNominatedInvitation(String siteName, String inviteeFirstName, String inviteeLastName, String inviteeEmail, String inviteeUserName, String inviteeRoleName, String serverPath, String acceptURL, String rejectURL) throws Exception
+ {
+ /*
+ * Create a new nominated invitation
+ */
+ JSONObject newInvitation = new JSONObject();
+
+ newInvitation.put("invitationType", "NOMINATED");
+ newInvitation.put("inviteeRoleName", inviteeRoleName);
+ if(inviteeUserName != null)
+ {
+ // nominate an existing user
+ newInvitation.put("inviteeUserName", inviteeUserName);
+ }
+ else
+ {
+ // nominate someone else
+ newInvitation.put("inviteeFirstName", inviteeFirstName);
+ newInvitation.put("inviteeLastName", inviteeLastName);
+ newInvitation.put("inviteeEmail", inviteeEmail);
+ }
+ newInvitation.put("serverPath", serverPath);
+ newInvitation.put("acceptURL", acceptURL);
+ newInvitation.put("rejectURL", rejectURL);
+
+ 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");
+
+ createdInvitations.add(new Tracker(inviteId, siteName));
+
+ return inviteId;
+ }
+
+ private String createModeratedInvitation(String siteName, String inviteeComments, String inviteeUserName, String inviteeRoleName) throws Exception
+ {
+ /*
+ * 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");
+
+ createdInvitations.add(new Tracker(inviteId, siteName));
+
+ return inviteId;
+ }
+
+ private JSONObject getInvitation(String inviteId, JSONArray data) throws Exception
+ {
+ for(int i = 0; i < data.length(); i++)
+ {
+ JSONObject obj = data.getJSONObject(i);
+ if(inviteId.equals(obj.getString("inviteId")))
+ {
+ return obj;
+ }
+ }
+ return null;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java b/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java
index 240899eb04..9a5290fb4e 100644
--- a/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java
+++ b/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java
@@ -703,8 +703,9 @@ public class SiteServiceTest extends BaseWebScriptTest
// Create a nominated invitation
String nominatedId = createNominatedInvitation(shortName, inviteeFirstName, inviteeLastName, inviteeEmail, inviteeUserName, roleName, serverPath, acceptURL, rejectURL);
+
/**
- * search by user - wombat does not have an invitation
+ * search by user - negative test wombat does not have an invitation
*/
{
Response response = sendRequest(new GetRequest(URL_SITES + "/" + shortName + "/invitations?inviteeUserName=wombat"), 200);
@@ -722,11 +723,15 @@ public class SiteServiceTest extends BaseWebScriptTest
//System.out.println(response.getContentAsString());
JSONArray data = top.getJSONArray("data");
assertEquals("user two invitation not found", data.length(), 2);
+ JSONObject first = data.getJSONObject(0);
+ assertEquals("first userid is wrong", first.getString("inviteeUserName"), USER_TWO);
+ JSONObject second = data.getJSONObject(0);
+ assertEquals("second userid is wrong", second.getString("inviteeUserName"), USER_TWO);
}
/**
- * search by type
+ * search by type - should find two moderated invitations
*/
{
@@ -734,6 +739,7 @@ public class SiteServiceTest extends BaseWebScriptTest
JSONObject top = new JSONObject(response.getContentAsString());
//System.out.println(response.getContentAsString());
JSONArray data = top.getJSONArray("data");
+ assertEquals("two moderated invitations not found", data.length(), 2);
}
{
@@ -741,10 +747,11 @@ public class SiteServiceTest extends BaseWebScriptTest
JSONObject top = new JSONObject(response.getContentAsString());
//System.out.println(response.getContentAsString());
JSONArray data = top.getJSONArray("data");
+ assertEquals("one nominated invitation not found", data.length(), 1);
}
+
// negative test - unknown invitationType
{
-
Response response = sendRequest(new GetRequest(URL_SITES + "/" + shortName + "/invitations?invitationType=Crap"), 500);
JSONObject top = new JSONObject(response.getContentAsString());
}
@@ -758,12 +765,10 @@ public class SiteServiceTest extends BaseWebScriptTest
//System.out.println(response.getContentAsString());
JSONArray data = top.getJSONArray("data");
assertEquals("user two invitation not found", data.length(), 1);
-
- }
-
-
-
-
+ JSONObject first = data.getJSONObject(0);
+ assertEquals("first userid is wrong", first.getString("inviteeUserName"), USER_TWO);
+ assertEquals("type is wrong", first.getString("invitationType"), "MODERATED");
+ }
}
/**