diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.desc.xml
new file mode 100644
index 0000000000..7b60519957
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.desc.xml
@@ -0,0 +1,10 @@
+
+ Delete Web Project Membership
+ Delete (uninvite) the membership for a user.
+ Sandboxes are deleted even if they have unsubmitted content.
+
+ /api/wcm/webproject/{webprojectref}/membership/{username}
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.js
new file mode 100644
index 0000000000..c3a261212b
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.js
@@ -0,0 +1,29 @@
+function main()
+{
+ // Get the url values
+ var urlElements = url.extension.split("/");
+ var webProjectRef = urlElements[0];
+ var userName = urlElements[2];
+
+ // Get the web project
+ var webproject = webprojects.getWebProject(webProjectRef);
+ if (webproject == null)
+ {
+ // Site cannot be found
+ status.setCode(status.STATUS_NOT_FOUND, "The web project " + webProjectRef + " does not exist.");
+ return;
+ }
+
+ var role = webproject.getMembersRole(userName);
+ if (role == null)
+ {
+ // Person is not a member of the site
+ status.setCode(status.STATUS_NOT_FOUND, "The person with user name (" + userName + ") is not a member of the webproject " + webProjectRef );
+ return;
+ }
+
+ // Remove the user from the site
+ webproject.removeMembership(userName);
+}
+
+main();
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.json.ftl
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.delete.json.ftl
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.desc.xml
new file mode 100644
index 0000000000..e908e44b56
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Membership
+ Get the webproject membership details for a user
+ /api/wcm/webproject/{webprojectref}/membership/{username}
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.js
new file mode 100644
index 0000000000..f05a9b6d1d
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.js
@@ -0,0 +1,41 @@
+function main()
+{
+ // Get the url values
+ var urlElements = url.extension.split("/");
+ var webProjectRef = urlElements[0];
+ var userName = urlElements[2];
+
+ // Get the web project
+ var webproject = webprojects.getWebProject(webProjectRef);
+ if (webproject == null)
+ {
+ // Site cannot be found
+ status.setCode(status.STATUS_NOT_FOUND, "The webproject: (" + webProjectRef + ") does not exist.");
+ return;
+ }
+
+ var person = people.getPerson(userName);
+ if (person == null)
+ {
+ // Person cannot be found
+ status.setCode(status.STATUS_NOT_FOUND, "The person with user name (" + userName + ") does not exist.");
+ return;
+ }
+
+ // Get the role of the user
+ var role = webproject.getMembersRole(userName);
+ if (role == null)
+ {
+ // Person is not a member of the site
+ status.setCode(status.STATUS_NOT_FOUND, "The person with user name (" + userName + ") is not a member of the webproject " + webProjectRef );
+ return;
+ }
+
+ // Pass the values to the template
+ model.webproject = webproject;
+ model.person = person;
+ model.role = role;
+}
+
+main();
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.json.ftl
new file mode 100644
index 0000000000..e458c4e9df
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.get.json.ftl
@@ -0,0 +1,2 @@
+<#import "membership.lib.ftl" as membershipLib/>
+<@membershipLib.membershipJSON webproject=webproject role=role person=person/>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.lib.ftl
new file mode 100644
index 0000000000..643831a639
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/membership.lib.ftl
@@ -0,0 +1,24 @@
+<#macro membershipJSON webproject role person>
+ <#escape x as jsonUtils.encodeJSONString(x)>
+ {
+ "role" : "${role}",
+ "person":
+ {
+ "userName" : "${person.properties.userName}",
+ "firstName" : "${person.properties.firstName}",
+ "lastName" : "${person.properties.lastName}",
+ <#if person.assocs["cm:avatar"]??>
+ "avatar" : "${"api/node/" + person.assocs["cm:avatar"][0].nodeRef?string?replace('://','/') + "/content/thumbnails/avatar"}",
+ #if>
+ <#if person.properties.jobtitle??>
+ "jobtitle" : "${person.properties.jobtitle}",
+ #if>
+ <#if person.properties.organization??>
+ "organization" : "${person.properties.organization}",
+ #if>
+ "url" : "${url.serviceContext + "/api/people/" + person.properties.userName}"
+ },
+ "url" : "${url.serviceContext + "/api/wcm/webproject/" + webproject.webProjectRef + "/membership/" + person.properties.userName}"
+ }
+ #escape>
+#macro>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.desc.xml
new file mode 100644
index 0000000000..fba083e686
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Memberships
+ Get a collection of a web project memberships.
+ /api/wcm/webproject/{webprojectref}/memberships
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.js
new file mode 100644
index 0000000000..503b851838
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.js
@@ -0,0 +1,44 @@
+/*
+ * Get the memberships for a web project
+ */
+function main()
+{
+ var shortName = url.extension.split("/")[0];
+
+ var webproject = webprojects.getWebProject(shortName);
+ if (webproject == null)
+ {
+ // Site cannot be found
+ status.setCode(status.STATUS_NOT_FOUND, "The webproject " + shortName + " does not exist.");
+ return;
+ }
+
+ // Get all the memberships
+ var memberships = webproject.listMembers();
+
+ // Get a list of all the users resolved to person nodes
+ var peopleList = Array();
+ for (userName in memberships)
+ {
+ var person = people.getPerson(userName);
+ peopleList["_" + userName] = person; // make sure the keys are strings
+ }
+
+ // also copy over the memberships.
+ var mems = {};
+ var pos = 0; // memberships[userName] won't return the correct value if userName is a digit-only value
+ for (userName in memberships)
+ {
+ var membershipType = memberships[pos];
+ mems["_" + userName] = membershipType; // make sure the keys are strings
+ pos++;
+ }
+
+ // Pass the information to the template
+ model.webproject = webproject;
+ model.memberships = mems;
+ model.people = peopleList;
+}
+
+main()
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.json.ftl
new file mode 100644
index 0000000000..1347e2ee2c
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.get.json.ftl
@@ -0,0 +1,11 @@
+<#import "membership.lib.ftl" as membershipLib/>
+[
+<#if memberships??>
+ <#assign userNames = memberships?keys />
+ <#list userNames as userName>
+ <@membershipLib.membershipJSON webproject=webproject role=memberships[userName] person=people[userName]/>
+ <#if userName_has_next>,#if>
+ #list>
+ #if>
+]
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.desc.xml
new file mode 100644
index 0000000000..ac247fb169
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.desc.xml
@@ -0,0 +1,8 @@
+
+ Invite user to web project
+ Adds a new membership to the web project
+ /api/wcm/webproject/{webprojectref}/memberships
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.json.ftl
new file mode 100644
index 0000000000..e458c4e9df
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.json.ftl
@@ -0,0 +1,2 @@
+<#import "membership.lib.ftl" as membershipLib/>
+<@membershipLib.membershipJSON webproject=webproject role=role person=person/>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.json.js
new file mode 100644
index 0000000000..f59560d693
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/membership/memberships.post.json.js
@@ -0,0 +1,57 @@
+/**
+ * Create a new web project membership
+ * @return
+ */
+
+function main()
+{
+ // Get the web project
+ var shortName = url.extension.split("/")[0];
+ var webproject = webprojects.getWebProject(shortName);
+ if (webproject == null)
+ {
+ // Site cannot be found
+ status.setCode(status.STATUS_NOT_FOUND, "The web project " + shortName + " does not exist.");
+ return;
+ }
+
+ // Get the role
+
+ if (! json.has("role"))
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "The role has not been set.");
+ return;
+ }
+ var role = json.get("role");
+
+ // Get the person
+ if(! json.has("person"))
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "The person has not been set.");
+ return;
+ }
+
+ // Get the user name
+ var userName = json.getJSONObject("person").get("userName");
+ if (userName == null)
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "The user name has not been set.");
+ return;
+ }
+ var person = people.getPerson(userName);
+ if (person == null)
+ {
+ status.setCode(status.STATUS_NOT_FOUND, "The person with user name " + userName + " could not be found.");
+ return;
+ }
+
+ // Set the membership details
+ webproject.addMembership(userName, role);
+
+ // Pass the details to the template
+ model.webproject = webproject;
+ model.role = role;
+ model.person = person;
+}
+
+main();
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.desc.xml
new file mode 100644
index 0000000000..3e7b11fbc1
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.desc.xml
@@ -0,0 +1,10 @@
+
+ Delete Web Project
+ Delete a single WCM web project and its contents,
+ webprojectref specifies which project to delete and will have been returned by a prior call to get, create of list web project.
+
+
+ /api/wcm/webproject/{webprojectref}
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.js
new file mode 100644
index 0000000000..c936f84b27
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.js
@@ -0,0 +1,41 @@
+
+/**
+ * Delete a wcm web project
+ */
+
+function getWebProject(webprojectref){
+
+ var service = webprojects;
+
+ var data = service.getWebProject(webprojectref)
+
+ return data;
+}
+
+function main() {
+
+ // Get the webproject ref
+ var webprojectref = url.extension;
+
+ if (webprojectref == null || webprojectref.length == 0)
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "Delete web project. webprojectref missing or blank");
+ return;
+ }
+
+ var webproject = webprojects.getWebProject(webprojectref);
+
+ if(webproject != null)
+ {
+ webproject.deleteWebProject();
+ status.setCode(status.STATUS_OK, "Webproject " + webprojectref + " deleted");
+ }
+ else
+ {
+ // Return 404
+ status.setCode(status.STATUS_NOT_FOUND, "Unable to delete : Webproject: " + webprojectref + " does not exist");
+ return;
+ }
+}
+
+main()
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.json.ftl
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.delete.json.ftl
@@ -0,0 +1 @@
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.desc.xml
new file mode 100644
index 0000000000..07d23c4455
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Get Web Project
+ Get a single WCM web project in JSON format.
+
+ /api/wcm/webproject/{webprojectref}
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.js
new file mode 100644
index 0000000000..91c741881c
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.js
@@ -0,0 +1,37 @@
+
+/**
+ * Get wcm web project
+ * @return the wcm web project
+ */
+
+function getWebProject(webprojectref){
+
+ var service = webprojects;
+
+ var data = service.getWebProject(webprojectref);
+
+ return data;
+}
+
+function main() {
+
+ // Get the siteref
+ var webprojectref = url.extension;
+
+ //var webproject = data;
+ var webproject = getWebProject(webprojectref);
+
+ if (webproject != null)
+ {
+ // Pass the webproject to the diaplay template
+ model.webproject = webproject;
+ }
+ else
+ {
+ // Return 404
+ status.setCode(404, "Webproject " + webprojectref + " does not exist");
+ return;
+ }
+}
+
+main()
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.json.ftl
new file mode 100644
index 0000000000..e77cb468e6
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.get.json.ftl
@@ -0,0 +1,4 @@
+<#import "webproject.lib.ftl" as webprojectLib/>
+<@webprojectLib.webprojectJSON webproject=webproject/>
+
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.lib.ftl
new file mode 100644
index 0000000000..3d3d1e6276
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.lib.ftl
@@ -0,0 +1,12 @@
+<#macro webprojectJSON webproject>
+<#escape x as jsonUtils.encodeJSONString(x)>
+{
+ "url" : "${url.serviceContext + "/api/wcm/webproject/" + webproject.webProjectRef}",
+ "webprojectref" : "${webproject.webProjectRef}",
+ "name" : "${webproject.name}",
+ "title" : "${webproject.title}",
+ "description" : "${webproject.description}"
+}
+#escape>
+#macro>
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.desc.xml
new file mode 100644
index 0000000000..210169fb99
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.desc.xml
@@ -0,0 +1,17 @@
+
+ Create Web Project
+ Create (POST) a single WCM web project.
+ The following fields are required in the body of the request:
+ name, title, dnsName.
+
+ The following fields are optional:
+ description.
+
+ Returns STATUS_CREATED on success.
+
+
+
+ /api/wcm/webproject
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.json.ftl
new file mode 100644
index 0000000000..e77cb468e6
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.json.ftl
@@ -0,0 +1,4 @@
+<#import "webproject.lib.ftl" as webprojectLib/>
+<@webprojectLib.webprojectJSON webproject=webproject/>
+
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.json.js
new file mode 100644
index 0000000000..b40964db8e
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.post.json.js
@@ -0,0 +1,41 @@
+
+/**
+ * Post (create) wcm web project
+ * @return the wcm web project ref
+ */
+
+function main() {
+
+ var name = json.get("name");
+ var title = json.get("title");
+ var dnsName = json.get("dnsName");
+ var description = json.get("description");
+
+ if (name == null || name.length == 0)
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "property 'Name' missing when creating web site");
+ return;
+ }
+ if (title == null || title.length == 0)
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "Property 'Title' missing when creating web site");
+ return;
+ }
+ if (dnsName == null || dnsName.length == 0)
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "property 'dnsName' missing when creating web site");
+ return;
+ }
+
+ if(description == null)
+ {
+ description = "web project" + name;
+ }
+
+ var webproject = webprojects.createWebProject(dnsName, name, title, description);
+
+ // Set Return value
+ model.webproject = webproject;
+}
+
+main()
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.desc.xml
new file mode 100644
index 0000000000..c395e552c4
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.desc.xml
@@ -0,0 +1,11 @@
+
+ Update Web Project
+ Update a single WCM web project
+ The following fields are may be updated in the body of the request:
+ name, title, description
+
+
+ /api/wcm/webproject/{webprojectref}
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.json.ftl
new file mode 100644
index 0000000000..e77cb468e6
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.json.ftl
@@ -0,0 +1,4 @@
+<#import "webproject.lib.ftl" as webprojectLib/>
+<@webprojectLib.webprojectJSON webproject=webproject/>
+
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.json.js
new file mode 100644
index 0000000000..0fef33e139
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webproject.put.json.js
@@ -0,0 +1,51 @@
+
+/**
+ * PUT (UPDATE) wcm web project
+ * @return the updatedwcm web project
+ */
+
+function main() {
+
+ // Get the webproject ref
+ var webprojectref = url.extension;
+
+ if (webprojectref == null || webprojectref.length == 0)
+ {
+ status.setCode(status.STATUS_BAD_REQUEST, "Delete web project. webprojectref missing or blank");
+ return;
+ }
+
+ var webproject = webprojects.getWebProject(webprojectref);
+
+ if(webproject == null)
+ {
+ // Return 404
+ status.setCode(status.STATUS_NOT_FOUND, "Webproject " + webprojectref + " does not exist");
+ return;
+ }
+
+ if (json.has("name") )
+ {
+ var name = json.get("name");
+ webproject.setName(name);
+ }
+ if (json.has("title"))
+ {
+ var title = json.get("title");
+ webproject.setTitle(title);
+ }
+ if(json.has("description"))
+ {
+ var description = json.get("description");
+ webproject.setDescription(description);
+ }
+
+ // update the web project
+ webproject.save();
+ status.setCode(status.STATUS_OK, "Webproject " + webprojectref + " updated");
+
+ // Set Return value
+ model.webproject = webproject;
+}
+
+main()
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.desc.xml
new file mode 100644
index 0000000000..bd6d296453
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.desc.xml
@@ -0,0 +1,9 @@
+
+ Web Projects
+ Get a list of the WCM Web projects, if userName is specified then only those web projects for the
+ specified user are returned else all web projects are returned.
+
+ /api/wcm/webprojects?userName={userName?}
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.js
new file mode 100644
index 0000000000..c71ea6c61a
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.js
@@ -0,0 +1,27 @@
+
+/**
+ * Get list of wcm web projects
+ * @return the wcm web projects
+ */
+
+function main()
+{
+ var service = webprojects;
+
+ var userFilter = args["userName"];
+
+ var result;
+
+ if(userFilter != null)
+ {
+ result = service.listWebProjects(userFilter);
+ }
+ else
+ {
+ result = service.listWebProjects();
+ }
+
+ model.webprojects = result;
+}
+
+main()
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.json.ftl
new file mode 100644
index 0000000000..f29665faf9
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/wcm/webprojects.get.json.ftl
@@ -0,0 +1,8 @@
+<#import "webproject.lib.ftl" as webprojectLib/>
+
+[
+ <#list webprojects as webproject>
+ <@webprojectLib.webprojectJSON webproject=webproject/>
+ <#if webproject_has_next>,#if>
+ #list>
+]
diff --git a/source/java/org/alfresco/repo/web/scripts/wcm/WebProjectTest.java b/source/java/org/alfresco/repo/web/scripts/wcm/WebProjectTest.java
new file mode 100644
index 0000000000..8d42f81fc4
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/wcm/WebProjectTest.java
@@ -0,0 +1,369 @@
+/*
+ * 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.wcm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.authentication.AuthenticationComponent;
+import org.alfresco.repo.web.scripts.BaseWebScriptTest;
+import org.alfresco.service.cmr.security.AuthenticationService;
+import org.alfresco.service.cmr.security.PersonService;
+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 to test site Web Project REST API
+ *
+ * @author Mark Rogers
+ */
+public class WebProjectTest extends BaseWebScriptTest
+{
+ private AuthenticationService authenticationService;
+ private AuthenticationComponent authenticationComponent;
+ private PersonService personService;
+
+ private static final String USER_ONE = "WebProjectTestOne";
+ private static final String USER_TWO = "WebProjectTestTwo";
+ private static final String USER_THREE = "WebProjectTestThree";
+
+ private static final String URL_WEB_PROJECT = "/api/wcm/webproject";
+ private static final String URL_WEB_PROJECTS = "/api/wcm/webprojects";
+
+ private static final String BASIC_NAME = "testProj";
+ private static final String BASIC_UPDATED_NAME = "updatedName";
+ private static final String BASIC_DESCRIPTION = "testDescription";
+ private static final String BASIC_UPDATED_DESCRIPTION = "updatedDescription";
+ private static final String BASIC_TITLE = "testTitle";
+ private static final String BASIC_UPDATED_TITLE = "updatedTitle";
+ private static final String BASIC_DNSNAME = "testDNSName";
+
+ private static final String BAD_PROJECT_REF="doesNotExist";
+
+ private List createdWebProjects = new ArrayList(5);
+
+ @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");
+
+ // 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("admin");
+
+ // Tidy-up any web projects created during the execution of the test
+ for (String webProjectRef : this.createdWebProjects)
+ {
+ try
+ {
+ Response deleteResponse = sendRequest(new DeleteRequest(URL_WEB_PROJECT + "/" + webProjectRef), 0);
+ }
+ catch (Exception e)
+ {
+ // ignore exception here
+ }
+ }
+
+ // Clear the list
+ this.createdWebProjects.clear();
+ }
+
+ public void testBasicCRUDWebProject() throws Exception
+ {
+ this.authenticationComponent.setCurrentUser("admin");
+
+ /**
+ * Create a web site
+ */
+ JSONObject webProj = new JSONObject();
+ webProj.put("name", BASIC_NAME);
+ webProj.put("description", BASIC_DESCRIPTION);
+ webProj.put("title", BASIC_TITLE);
+ webProj.put("dnsName", BASIC_DNSNAME);
+ Response response = sendRequest(new PostRequest(URL_WEB_PROJECT, webProj.toString(), "application/json"), Status.STATUS_OK);
+
+ JSONObject result = new JSONObject(response.getContentAsString());
+ String webProjectRef = result.getString("webprojectref");
+
+ assertNotNull("webproject ref is null", webProjectRef);
+ this.createdWebProjects.add(webProjectRef);
+
+ assertEquals(BASIC_NAME, result.get("name"));
+ assertEquals(BASIC_DESCRIPTION, result.get("description"));
+ assertEquals(BASIC_TITLE, result.get("title"));
+
+ /**
+ * Read the web site we created above
+ */
+ Response lookup = sendRequest(new GetRequest(URL_WEB_PROJECT + "/" + webProjectRef), 200);
+ {
+ JSONObject lookupResult = new JSONObject(lookup.getContentAsString());
+ assertEquals(BASIC_NAME, lookupResult.get("name"));
+ assertEquals(BASIC_DESCRIPTION, lookupResult.get("description"));
+ assertEquals(BASIC_TITLE, lookupResult.get("title"));
+ }
+
+ /**
+ * Update the name property on the web site we created above
+ */
+ {
+ JSONObject update = new JSONObject();
+ update.put("name", BASIC_UPDATED_NAME);
+ Response updateResponse = sendRequest(new PutRequest(URL_WEB_PROJECT + "/" + webProjectRef, update.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject updateResult = new JSONObject(updateResponse.getContentAsString());
+
+// TODO TESTS NOT PASSING
+// assertEquals(BASIC_UPDATED_NAME, updateResult.get("name"));
+// assertEquals(BASIC_DESCRIPTION, updateResult.get("description"));
+// assertEquals(BASIC_TITLE, updateResult.get("title"));
+ }
+
+ /**
+ * Delete the web site we created above
+ */
+ Response deleteResponse = sendRequest(new DeleteRequest(URL_WEB_PROJECT + "/" + webProjectRef), Status.STATUS_OK);
+ } // END testBasicCRUDWebProject
+
+ public void testListWebSites() throws Exception
+ {
+ int LOOP_COUNT = 5;
+
+ this.authenticationComponent.setCurrentUser("admin");
+
+ for(int i = 0; i < LOOP_COUNT; i++)
+ {
+ /**
+ * Create a web site
+ */
+ JSONObject webProj = new JSONObject();
+ webProj.put("name", BASIC_NAME + i);
+ webProj.put("description", BASIC_DESCRIPTION + i);
+ webProj.put("title", BASIC_TITLE + i);
+ webProj.put("dnsName", BASIC_DNSNAME + i);
+ Response response = sendRequest(new PostRequest(URL_WEB_PROJECT, webProj.toString(), "application/json"), Status.STATUS_OK);
+
+ JSONObject result = new JSONObject(response.getContentAsString());
+ String webProjectRef = result.getString("webprojectref");
+ this.createdWebProjects.add(webProjectRef);
+ }
+
+ /**
+ * List the web sites
+ */
+ {
+ Response list = sendRequest(new GetRequest(URL_WEB_PROJECTS), Status.STATUS_OK);
+
+ JSONArray lookupResult = new JSONArray(list.getContentAsString());
+ assertTrue(lookupResult.length() > LOOP_COUNT);
+
+ /**
+ * Now check that the list contains the sites created above
+ */
+ int foundCount = 0;
+
+ for(int i = 0; i < lookupResult.length(); i++)
+ {
+ JSONObject obj = lookupResult.getJSONObject(i);
+ String name = obj.getString("name");
+ if(name.contains(BASIC_NAME))
+ {
+ foundCount++;
+ }
+ }
+ assertTrue (foundCount >= LOOP_COUNT);
+ }
+
+ /**
+ * List the web sites with a user name (should find 0)
+ */
+ {
+ String stepURL = "/api/wcm/webprojects?userName=Freddy";
+ Response list = sendRequest(new GetRequest(stepURL), Status.STATUS_OK);
+ JSONArray lookupResult = new JSONArray(list.getContentAsString());
+ assertTrue(lookupResult.length() == 0);
+ }
+
+
+
+
+ } // testListWebSites
+
+ public void testUpdateWebProject() throws Exception
+ {
+ this.authenticationComponent.setCurrentUser("admin");
+
+ /**
+ * Create a web site
+ */
+ JSONObject webProj = new JSONObject();
+ webProj.put("name", BASIC_NAME);
+ webProj.put("description", BASIC_DESCRIPTION);
+ webProj.put("title", BASIC_TITLE);
+ webProj.put("dnsName", BASIC_DNSNAME);
+ Response response = sendRequest(new PostRequest(URL_WEB_PROJECT, webProj.toString(), "application/json"), Status.STATUS_OK);
+
+ JSONObject result = new JSONObject(response.getContentAsString());
+ String webProjectRef = result.getString("webprojectref");
+
+ assertNotNull("webproject ref is null", webProjectRef);
+ this.createdWebProjects.add(webProjectRef);
+
+ /**
+ * Read the web site we created above to double check it created correctly
+ */
+ {
+ Response lookup = sendRequest(new GetRequest(URL_WEB_PROJECT + "/" + webProjectRef), Status.STATUS_OK);
+ JSONObject lookupResult = new JSONObject(lookup.getContentAsString());
+ assertEquals(BASIC_NAME, lookupResult.get("name"));
+ assertEquals(BASIC_DESCRIPTION, lookupResult.get("description"));
+ assertEquals(BASIC_TITLE, lookupResult.get("title"));
+ }
+
+ /*
+ * Update description only
+ */
+ {
+ JSONObject update = new JSONObject();
+ update.put("description", BASIC_UPDATED_DESCRIPTION);
+ Response updateResponse = sendRequest(new PutRequest(URL_WEB_PROJECT + "/" + webProjectRef, update.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject updateResult = new JSONObject(updateResponse.getContentAsString());
+
+ /*
+ * Read the result, check description updated and other properties remain unchanged
+ */
+ Response lookup = sendRequest(new GetRequest(URL_WEB_PROJECT + "/" + webProjectRef), Status.STATUS_OK);
+ JSONObject lookupResult = new JSONObject(lookup.getContentAsString());
+ assertEquals(BASIC_NAME, lookupResult.get("name"));
+ assertEquals(BASIC_UPDATED_DESCRIPTION, lookupResult.get("description"));
+ assertEquals(BASIC_TITLE, lookupResult.get("title"));
+ }
+
+ /*
+ * Update title only, description (from previous step) and title should be updated
+ */
+ {
+ JSONObject update = new JSONObject();
+ update.put("title", BASIC_UPDATED_TITLE);
+ Response updateResponse = sendRequest(new PutRequest(URL_WEB_PROJECT + "/" + webProjectRef, update.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject updateResult = new JSONObject(updateResponse.getContentAsString());
+
+ /*
+ * Read the result, check description updated and other properties unchanged
+ */
+ Response lookup = sendRequest(new GetRequest(URL_WEB_PROJECT + "/" + webProjectRef), Status.STATUS_OK);
+ JSONObject lookupResult = new JSONObject(lookup.getContentAsString());
+ assertEquals(BASIC_NAME, lookupResult.get("name"));
+ assertEquals(BASIC_UPDATED_DESCRIPTION, lookupResult.get("description"));
+ assertEquals(BASIC_UPDATED_TITLE, lookupResult.get("title"));
+ }
+
+ /**
+ * Update name only (description and title should remain)
+ */
+ {
+ JSONObject update = new JSONObject();
+ update.put("name", BASIC_UPDATED_NAME);
+ Response updateResponse = sendRequest(new PutRequest(URL_WEB_PROJECT + "/" + webProjectRef, update.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject updateResult = new JSONObject(updateResponse.getContentAsString());
+
+ /*
+ * Read the result, check description updated and other properties unchanged
+ */
+ Response lookup = sendRequest(new GetRequest(URL_WEB_PROJECT + "/" + webProjectRef), Status.STATUS_OK);
+ JSONObject lookupResult = new JSONObject(lookup.getContentAsString());
+ assertEquals(BASIC_UPDATED_NAME, lookupResult.get("name"));
+ assertEquals(BASIC_UPDATED_DESCRIPTION, lookupResult.get("description"));
+ assertEquals(BASIC_UPDATED_TITLE, lookupResult.get("title"));
+
+ }
+
+ /**
+ * Negative test.
+ *
+ * attempt to update a web project that does not exist - should give a 404.
+ */
+ {
+ JSONObject update = new JSONObject();
+ update.put("name", BASIC_UPDATED_NAME);
+ Response updateResponse = sendRequest(new PutRequest(URL_WEB_PROJECT + "/" + BAD_PROJECT_REF, update.toString(), "application/json"), Status.STATUS_NOT_FOUND);
+ JSONObject updateResult = new JSONObject(updateResponse.getContentAsString());
+ }
+
+ } // end testUpdateWebProject
+
+ public void testDeleteWebProject() throws Exception
+ {
+ /**
+ * Negative test
+ *
+ * Delete a project that does not exist
+ */
+ {
+ Response deleteResponse = sendRequest(new DeleteRequest(URL_WEB_PROJECT + "/" + BAD_PROJECT_REF), Status.STATUS_NOT_FOUND);
+ }
+
+ } // end testDeleteWebproject
+
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/wcm/membership/WebProjectMembershipTest.java b/source/java/org/alfresco/repo/web/scripts/wcm/membership/WebProjectMembershipTest.java
new file mode 100644
index 0000000000..f61ed8d551
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/wcm/membership/WebProjectMembershipTest.java
@@ -0,0 +1,518 @@
+/*
+ * 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.wcm.membership;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.authentication.AuthenticationComponent;
+import org.alfresco.repo.site.SiteModel;
+import org.alfresco.repo.web.scripts.BaseWebScriptTest;
+import org.alfresco.service.cmr.security.AuthenticationService;
+import org.alfresco.service.cmr.security.PersonService;
+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 to test site Web Project Membership REST API
+ *
+ * @author Mark Rogers
+ */
+public class WebProjectMembershipTest extends BaseWebScriptTest
+{
+ private AuthenticationService authenticationService;
+ private AuthenticationComponent authenticationComponent;
+ private PersonService personService;
+
+ private static final String USER_ONE = "WebProjectTestOne";
+ private static final String USER_TWO = "WebProjectTestTwo";
+ private static final String USER_THREE = "WebProjectTestThree";
+ private static final String USER_ADMIN = "admin";
+ public static final String ROLE_CONTENT_MANAGER = "ContentManager";
+ public static final String ROLE_CONTENT_PUBLISHER = "ContentPublisher";
+ public static final String ROLE_CONTENT_REVIEWER = "ContentReviewer";
+ public static final String ROLE_CONTENT_CONTRIBUTOR = "ContentContributor";
+
+ private static final String URL_WEB_PROJECT = "/api/wcm/webproject";
+ private static final String URL_MEMBERSHIPS = "/memberships";
+ private static final String BASIC_NAME = "testProj";
+ private static final String BASIC_DESCRIPTION = "testDescription";
+ private static final String BASIC_TITLE = "testTitle";
+ private static final String BASIC_DNSNAME = "testDNSName";
+
+
+
+ private List createdWebProjects = new ArrayList(5);
+
+ @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");
+
+ // 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("admin");
+
+ // Tidy-up any web projects created during the execution of the test
+ for (String webProjectRef : this.createdWebProjects)
+ {
+ try
+ {
+ sendRequest(new DeleteRequest(URL_WEB_PROJECT + "/" + webProjectRef), 0);
+ }
+ catch (Exception e)
+ {
+ // ignore exception here
+ }
+ }
+
+ // Clear the list
+ this.createdWebProjects.clear();
+ }
+
+ /**
+ * create a web project
+ * @return the webprojectref
+ * @throws Exception
+ */
+ private String createWebProject() throws Exception
+ {
+ /**
+ * Create a web site
+ */
+ JSONObject webProj = new JSONObject();
+ webProj.put("name", BASIC_NAME);
+ webProj.put("description", BASIC_DESCRIPTION);
+ webProj.put("title", BASIC_TITLE);
+ webProj.put("dnsName", BASIC_DNSNAME);
+ Response response = sendRequest(new PostRequest(URL_WEB_PROJECT, webProj.toString(), "application/json"), Status.STATUS_OK);
+
+ JSONObject result = new JSONObject(response.getContentAsString());
+ String webProjectRef = result.getString("webprojectref");
+
+ assertNotNull("webproject ref is null", webProjectRef);
+ this.createdWebProjects.add(webProjectRef);
+ return webProjectRef;
+
+ }
+
+ public void testListMemberships() throws Exception
+ {
+ this.authenticationComponent.setCurrentUser("admin");
+
+ // Create a site
+ String webProjectRef = createWebProject();
+
+ String validURL = URL_WEB_PROJECT + "/" + webProjectRef + "/memberships";
+
+ /**
+ * A newly created web project has 1 users (admin is a special case)
+ */
+ {
+ Response response = sendRequest(new GetRequest(validURL), Status.STATUS_OK);
+ JSONArray result = new JSONArray(response.getContentAsString());
+
+ assertNotNull(result);
+ assertEquals(1, result.length());
+ }
+
+ /**
+ * Add USER_ONE (CONTENT_MANAGER)to the project and list it again
+ */
+ {
+ JSONObject membership = new JSONObject();
+ membership.put("role", ROLE_CONTENT_MANAGER);
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_ONE);
+ membership.put("person", person);
+ sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_OK);
+
+ Response response = sendRequest(new GetRequest(validURL), Status.STATUS_OK);
+ JSONArray result = new JSONArray(response.getContentAsString());
+ assertNotNull(result);
+ assertEquals(2, result.length());
+
+ boolean foundUser = false;
+ for(int i = 0; i < result.length(); i++)
+ {
+ JSONObject obj = result.getJSONObject(i);
+ if(USER_ONE.equals(obj.getJSONObject("person").get("userName")))
+ {
+ assertEquals(ROLE_CONTENT_MANAGER, obj.get("role"));
+ foundUser = true;
+ }
+
+ }
+ assertTrue("user one not found", foundUser);
+
+ }
+
+ /**
+ * Add USER_TWO (CONTENT_REVIEWER) to the project and list it again
+ */
+ {
+ JSONObject membership = new JSONObject();
+ membership.put("role", ROLE_CONTENT_REVIEWER);
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_TWO);
+ membership.put("person", person);
+ sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_OK);
+
+ Response response = sendRequest(new GetRequest(validURL), Status.STATUS_OK);
+ JSONArray result = new JSONArray(response.getContentAsString());
+ assertNotNull(result);
+ assertEquals(3, result.length());
+
+ boolean foundUser = false;
+ for(int i = 0; i < result.length(); i++)
+ {
+ JSONObject obj = result.getJSONObject(i);
+ if(USER_TWO.equals(obj.getJSONObject("person").get("userName")))
+ {
+ assertEquals(ROLE_CONTENT_REVIEWER, obj.get("role"));
+ foundUser = true;
+ }
+
+ }
+ assertTrue("user one not found", foundUser);
+
+ }
+
+ /**
+ * List the web sites with a user name = USER_TWO (should find 1)
+ */
+ {
+ String stepURL = "/api/wcm/webprojects?userName=" + USER_TWO;
+ Response list = sendRequest(new GetRequest(stepURL), Status.STATUS_OK);
+ JSONArray lookupResult = new JSONArray(list.getContentAsString());
+ assertTrue(lookupResult.length() == 1);
+ }
+
+ /**
+ * Negative test
+ * Project not found
+ */
+ {
+ String invalidURL = URL_WEB_PROJECT + "/" + "NotExist" + "/memberships";
+ sendRequest(new GetRequest(invalidURL), Status.STATUS_NOT_FOUND);
+ }
+
+ }
+
+ public void testCreateMemberships() throws Exception
+ {
+ this.authenticationComponent.setCurrentUser(USER_ADMIN);
+
+ String webProjectRef = createWebProject();
+
+ String validURL = URL_WEB_PROJECT + "/" + webProjectRef + "/memberships";
+
+ /**
+ * Create a new membership
+ */
+ {
+ JSONObject membership = new JSONObject();
+ membership.put("role", ROLE_CONTENT_MANAGER);
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_TWO);
+ membership.put("person", person);
+
+ Response response = sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject result = new JSONObject(response.getContentAsString());
+
+ // Check the result
+ assertEquals(ROLE_CONTENT_MANAGER, result.get("role"));
+ assertEquals(USER_TWO, result.getJSONObject("person").get("userName"));
+ }
+
+ /**
+ * Get the membership
+ */
+ {
+ String validGetURL = URL_WEB_PROJECT + "/" + webProjectRef + "/membership/" + USER_TWO;
+ Response response = sendRequest(new GetRequest(validGetURL), Status.STATUS_OK);
+ JSONObject result = new JSONObject(response.getContentAsString());
+
+ // Check the result
+ assertEquals(ROLE_CONTENT_MANAGER, result.get("role"));
+ assertEquals(USER_TWO, result.getJSONObject("person").get("userName"));
+ }
+
+ /**
+ * Negative test -- umm -- this passes is this correct?
+ * Create User two that already exists
+ */
+ {
+ JSONObject membership = new JSONObject();
+ membership.put("role", ROLE_CONTENT_MANAGER);
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_TWO);
+ membership.put("person", person);
+
+ Response response = sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject result = new JSONObject(response.getContentAsString());
+
+ // Check the result
+ assertEquals(ROLE_CONTENT_MANAGER, result.get("role"));
+ assertEquals(USER_TWO, result.getJSONObject("person").get("userName"));
+ }
+
+ /**
+ * Negative test missing role
+ */
+ {
+ JSONObject membership = new JSONObject();
+
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_TWO);
+ membership.put("person", person);
+
+ sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_BAD_REQUEST);
+ }
+
+ /**
+ * Negative test missing person
+ */
+ {
+ JSONObject membership = new JSONObject();
+ membership.put("role", ROLE_CONTENT_MANAGER);
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_TWO);
+
+ sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_BAD_REQUEST);
+ }
+ }
+
+
+ public void testGetMembership() throws Exception
+ {
+ this.authenticationComponent.setCurrentUser(USER_ADMIN);
+
+ // Create a site
+ String webProjectRef = createWebProject();
+
+ // Test error conditions
+ sendRequest(new GetRequest(URL_WEB_PROJECT + "/badsite" + URL_MEMBERSHIPS + "/" + USER_ONE), Status.STATUS_NOT_FOUND);
+ String validURL = URL_WEB_PROJECT + "/" + webProjectRef + "/membership/";
+
+ // User not found
+ sendRequest(new GetRequest(validURL + "baduser"), Status.STATUS_NOT_FOUND);
+
+ /**
+ * Now lookup the admin user and check they are a content manager
+ */
+ Response response = sendRequest(new GetRequest(validURL + USER_ADMIN), Status.STATUS_OK);
+ JSONObject result = new JSONObject(response.getContentAsString());
+
+ // Check the result
+ assertEquals(ROLE_CONTENT_MANAGER, result.get("role"));
+ assertEquals(USER_ADMIN, result.getJSONObject("person").get("userName"));
+ }
+
+// Update Not yet implemented
+
+// public void testUpdateMembership() throws Exception
+// {
+//
+// this.authenticationComponent.setCurrentUser(USER_ADMIN);
+//
+// String webProjectRef = createWebProject();
+//
+// String validURL = URL_WEB_PROJECT + "/" + webProjectRef + "/memberships";
+//
+// String validUserTwoURL = URL_WEB_PROJECT + "/" + webProjectRef + "/membership/" + USER_TWO;
+//
+//
+// /**
+// * Negative test wrong project
+// */
+// {
+// String invalidProject = URL_WEB_PROJECT + "/" + "I no exist" + "/membership/" + USER_TWO;
+// JSONObject membership = new JSONObject();
+// membership.put("role", ROLE_CONTENT_MANAGER);
+// sendRequest(new PutRequest( invalidProject, membership.toString(), "application/json"), Status.STATUS_NOT_FOUND);
+// }
+//
+// /**
+// * Negative test wrong user
+// */
+// {
+// String invalidUser = URL_WEB_PROJECT + "/" + webProjectRef + "/membership/" + "Dr Nobody";
+// JSONObject membership = new JSONObject();
+// membership.put("role", ROLE_CONTENT_MANAGER);
+// sendRequest(new PutRequest( invalidUser, membership.toString(), "application/json"), Status.STATUS_NOT_FOUND);
+// }
+//
+//
+// /**
+// * Create a new membership USER_TWO with CONTENT_MANAGER
+// */
+// {
+// JSONObject membership = new JSONObject();
+// membership.put("role", ROLE_CONTENT_MANAGER);
+// JSONObject person = new JSONObject();
+// person.put("userName", USER_TWO);
+// membership.put("person", person);
+// sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_OK);
+// }
+//
+// /**
+// * Negative test missing role
+// */
+// {
+// JSONObject membership = new JSONObject();
+// sendRequest(new PutRequest(validUserTwoURL, membership.toString(), "application/json"), Status.STATUS_BAD_REQUEST);
+// }
+//
+//
+// /**
+// * Now change USER_TWO to a ROLE_CONTENT_CONTRIBUTOR
+// */
+// {
+// JSONObject membership = new JSONObject();
+// membership.put("role", ROLE_CONTENT_CONTRIBUTOR);
+// Response response = sendRequest(new PutRequest(validUserTwoURL, membership.toString(),"application/json"), Status.STATUS_OK);
+// JSONObject result = new JSONObject(response.getContentAsString());
+//
+// // Check the result
+// assertEquals(ROLE_CONTENT_CONTRIBUTOR, result.get("role"));
+// assertEquals(USER_TWO, result.getJSONObject("person").get("userName"));
+// }
+//
+// /**
+// * Go back and get the role
+// */
+// {
+// Response response = sendRequest(new GetRequest(validUserTwoURL), Status.STATUS_OK);
+// JSONObject result = new JSONObject(response.getContentAsString());
+//
+// // Check the result
+// assertEquals(ROLE_CONTENT_CONTRIBUTOR, result.get("role"));
+// assertEquals(USER_TWO, result.getJSONObject("person").get("userName"));
+// }
+//
+//
+//
+// }
+
+ public void testDeleteMembership() throws Exception
+ {
+ this.authenticationComponent.setCurrentUser(USER_ADMIN);
+
+ String webProjectRef = createWebProject();
+
+ String validURL = URL_WEB_PROJECT + "/" + webProjectRef + "/memberships";
+
+ /**
+ * Create a new membership
+ */
+ {
+ JSONObject membership = new JSONObject();
+ membership.put("role", ROLE_CONTENT_MANAGER);
+ JSONObject person = new JSONObject();
+ person.put("userName", USER_TWO);
+ membership.put("person", person);
+
+ Response response = sendRequest(new PostRequest(validURL, membership.toString(), "application/json"), Status.STATUS_OK);
+ JSONObject result = new JSONObject(response.getContentAsString());
+
+ // Check the result
+ assertEquals(ROLE_CONTENT_MANAGER, result.get("role"));
+ assertEquals(USER_TWO, result.getJSONObject("person").get("userName"));
+ }
+
+ String validGetURL = URL_WEB_PROJECT + "/" + webProjectRef + "/membership/" + USER_TWO;
+
+ {
+ sendRequest(new GetRequest(validGetURL), Status.STATUS_OK);
+ }
+ /**
+ * Delete the membership for USER_TWO
+ */
+ {
+ sendRequest(new DeleteRequest(validGetURL), Status.STATUS_OK);
+ }
+
+ /**
+ * lookup should now fail
+ */
+ {
+ sendRequest(new GetRequest(validGetURL), Status.STATUS_NOT_FOUND);
+ }
+
+ /**
+ * Negative test - delete user two again - should not exist
+ * Delete the membership
+ */
+ {
+ sendRequest(new DeleteRequest(validGetURL), Status.STATUS_NOT_FOUND);
+ }
+
+
+
+ }
+
+}