Change to Invite Service so that 'start invite' operation receives a given invitee site role and 'accept invite' picks it off the workflow and sets the invitee's site membership with that role

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10435 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Glen Johnson
2008-08-20 09:06:13 +00:00
parent 31bf4fc817
commit f4da392bc3
5 changed files with 128 additions and 36 deletions

View File

@@ -1,7 +1,7 @@
<webscript>
<shortname>Invite</shortname>
<description>Processes Inviter actions ('start' or 'cancel' invite)</description>
<url>/api/invite/start?inviteeFirstName={inviteeFirstName}&amp;inviteeLastName={inviteeLastName}&amp;inviteeEmail={inviteeEmailAddress}&amp;siteShortName={siteShortName}</url>
<url>/api/invite/start?inviteeFirstName={inviteeFirstName}&amp;inviteeLastName={inviteeLastName}&amp;inviteeEmail={inviteeEmailAddress}&amp;siteShortName={siteShortName}&amp;inviteeSiteRole={inviteeSiteRole}</url>
<url>/api/invite/cancel?inviteId={inviteId}</url>
<format default="json"/>
<authentication>user</authentication>

View File

@@ -36,6 +36,9 @@
<property name="wf:siteShortName">
<type>d:text</type>
</property>
<property name="wf:inviteeSiteRole">
<type>d:text</type>
</property>
</properties>
</type>

View File

@@ -82,6 +82,7 @@ public class Invite extends DeclarativeWebScript
private static final String PARAM_INVITEE_EMAIL = "inviteeEmail";
private static final String PARAM_SITE_SHORT_NAME = "siteShortName";
private static final String PARAM_INVITE_ID = "inviteId";
private static final String PARAM_INVITEE_SITE_ROLE = "inviteeSiteRole";
// services
private WorkflowService workflowService;
@@ -103,6 +104,7 @@ public class Invite extends DeclarativeWebScript
public static final String WF_PROP_INVITEE_FIRSTNAME = "wf:inviteeFirstName";
public static final String WF_PROP_INVITEE_LASTNAME = "wf:inviteeLastName";
public static final String WF_PROP_SITE_SHORT_NAME = "wf:siteShortName";
public static final String WF_PROP_INVITEE_SITE_ROLE = "wf:inviteeSiteRole";
private static final String WF_PROP_INVITEE_GEN_PASSWORD = "wf:inviteeGenPassword";
public static final String WF_INVITE_TASK_INVITE_TO_SITE = "wf:inviteToSiteTask";
@@ -301,11 +303,21 @@ public class Invite extends DeclarativeWebScript
+ ACTION_START + "'");
}
// check for 'inviteeSiteRole' parameter not provided
String inviteeSiteRole = req.getParameter(PARAM_INVITEE_SITE_ROLE);
if ((inviteeSiteRole == null) || (inviteeSiteRole.length() == 0))
{
// handle inviteeSiteRole URL parameter not provided
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"'inviteeSiteRole' parameter has not been provided in URL for action '"
+ ACTION_START + "'");
}
// get externally reachable address of server hosting invite web scripts
String serverPath = req.getServerPath();
// process action 'start' with provided parameters
startInvite(model, inviteeFirstName, inviteeLastName, inviteeEmail, siteShortName, serverPath);
startInvite(model, inviteeFirstName, inviteeLastName, inviteeEmail, siteShortName, inviteeSiteRole, serverPath);
}
// else handle if provided 'action' is 'cancel'
else if (action.equals(ACTION_CANCEL))
@@ -453,11 +465,13 @@ public class Invite extends DeclarativeWebScript
* @param siteShortName
* short name of site that the invitee is being invited to by the
* inviter
* @param inviteeSiteRole
* role under which invitee is being invited to the site by the inviter
* @param serverPath
* externally accessible server address of server hosting invite web scripts
*/
private void startInvite(Map<String, Object> model, String inviteeFirstName, String inviteeLastName,
String inviteeEmail, String siteShortName, String serverPath)
String inviteeEmail, String siteShortName, String inviteeSiteRole, String serverPath)
{
// get the inviter user name (the name of user web script is executed under)
// - needs to be assigned here because various system calls further on
@@ -558,6 +572,8 @@ public class Invite extends DeclarativeWebScript
inviteePassword);
workflowProps.put(QName.createQName(WF_PROP_SITE_SHORT_NAME, this.namespaceService),
siteShortName);
workflowProps.put(QName.createQName(WF_PROP_INVITEE_SITE_ROLE, this.namespaceService),
inviteeSiteRole);
workflowProps.put(QName.createQName(WF_PROP_SERVER_PATH, this.namespaceService),
serverPath);

View File

@@ -31,7 +31,6 @@ import java.util.Map;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.repo.site.SiteService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowService;
@@ -258,20 +257,28 @@ public class InviteResponse extends DeclarativeWebScript
// the model) out into workflow action class that gets run when task wf:acceptInviteTask
// is completed by this web script
// enable invitee person's user account because he/she has accepted the
// if there is already a user account for the invitee and that account
// is disabled, then enable the account because he/she has accepted the
// site invitation
this.mutableAuthenticationDao.setEnabled(inviteeUserName, true);
if ((this.mutableAuthenticationDao.userExists(inviteeUserName))
&& (this.mutableAuthenticationDao.getEnabled(inviteeUserName) == false))
{
this.mutableAuthenticationDao.setEnabled(inviteeUserName, true);
}
// Add Invitee to Site as "Site Collaborator" role
// retrieve the site role with which the invitee was invited to the site
String inviteeSiteRole = getInviteeSiteRoleFromInvite(inviteId);
// add Invitee to Site with the site role that the inviter "started" the invite process with
RunAsWork<Boolean> setSiteMembershipWorker = new InviteResponse.SetSiteMembershipWorker(
siteShortName, inviteeUserName, SiteModel.SITE_COLLABORATOR);
siteShortName, inviteeUserName, inviteeSiteRole);
AuthenticationUtil.runAs(setSiteMembershipWorker, USER_ADMIN);
// complete the wf:acceptInviteTask because the operations that need to be performed
// when the invitee has accepted the invitation have now been performed (code block
// above up to where wf:invitePendingTask is completed). This code block will soon
// be farmed out into a workflow action which gets executed when wf:acceptInviteTask
// gets completed
// starting from above where wf:invitePendingTask is completed, up to here). This code
// block will soon be farmed out into a workflow action which gets executed when
// wf:acceptInviteTask gets completed
completeInviteTask(QName.createQName(WF_TASK_ACCEPT_INVITE, this.namespaceService), WF_TRANSITION_ACCEPT_INVITE_END);
// add model properties for template to render
@@ -303,14 +310,26 @@ public class InviteResponse extends DeclarativeWebScript
// the model) out into workflow action class that gets run when task wf:rejectInviteTask
// is completed by this web script
// delete the person created for invitee
this.personService.deletePerson(inviteeUserName);
// if invitee's user account is still disabled then remove the account and
// delete the invitee's person node
if ((this.mutableAuthenticationDao.userExists(inviteeUserName))
&& (this.mutableAuthenticationDao.getEnabled(inviteeUserName) == false))
{
// delete the invitee's user account
this.mutableAuthenticationDao.deleteUser(inviteeUserName);
// delete the invitee's person node if one exists
if (this.personService.personExists(inviteeUserName))
{
this.personService.deletePerson(inviteeUserName);
}
}
// complete the wf:rejectInviteTask because the operations that need to be performed
// when the invitee has rejected the invitation have now been performed (code block
// above up to where wf:invitePendingTask is completed). This code block will soon
// be farmed out into a workflow action which gets executed when wf:rejectInviteTask
// gets completed
// starting from above where wf:invitePendingTask is completed, up to here). This code
// block will soon be farmed out into a workflow action which gets executed when
// wf:rejectInviteTask gets completed
completeInviteTask(QName.createQName(WF_TASK_REJECT_INVITE, this.namespaceService), WF_TRANSITION_REJECT_INVITE_END);
// add model properties for template to render
@@ -350,4 +369,57 @@ public class InviteResponse extends DeclarativeWebScript
this.workflowService.endTask(workflowTask.id, transitionId);
}
}
/**
* Gets the invitee site role from the invite
* workflow instance associated with the given invite ID.
* i.e. if the inviter 'starts' an invite (which is allocated some invite ID
* '12345' when it is processed), and that invite is requesting an invitee to
* to join some site under a given site role, then that site role is returned
* by this method when invite ID '12345' is passed in.
*
* @param inviteId the ID of the invitation (invite workflow instance)
* from which to retrieve the invitee site role
* @return the site role under which the invitee was invited to
* join the site. Returns <pre>null</pre> if no invite
* workflow instance was found matching the given invite ID
*/
private String getInviteeSiteRoleFromInvite(String inviteId)
{
// create workflow task query
WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery();
wfTaskQuery.setProcessId(inviteId);
// set process name to "wf:invite" so that only tasks associated with
// invite workflow instances are returned by query
wfTaskQuery.setProcessName(QName.createQName("wf:invite", this.namespaceService));
// pick up the start task because it has the "wf:inviteeSiteRole" property set with the
// site role value that we want to retrieve
wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED);
wfTaskQuery.setTaskName(QName.createQName(Invite.WF_INVITE_TASK_INVITE_TO_SITE, this.namespaceService));
// query for invite workflow task associate
List<WorkflowTask> inviteStartTasks = this.workflowService
.queryTasks(wfTaskQuery);
// if no results were returned for given inviteID, then return
// site role as null
if (inviteStartTasks.size() == 0)
{
return null;
}
else
{
// there should be only one start task returned for the given invite ID
// so just take the first one in the list
WorkflowTask inviteStartTask = inviteStartTasks.get(0);
String inviteeSiteRole = (String) inviteStartTask.properties.get(
QName.createQName(Invite.WF_PROP_INVITEE_SITE_ROLE, this.namespaceService));
return inviteeSiteRole;
}
}
}

View File

@@ -51,7 +51,6 @@ import org.alfresco.util.PropertyMap;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.Status;
import org.apache.commons.lang.RandomStringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -86,6 +85,7 @@ public class InviteServiceTest extends BaseWebScriptTest
private static final String INVITER_EMAIL = "FirstName123.LastName123@email.com";
private static final String INVITEE_EMAIL_DOMAIN = "alfrescotesting.com";
private static final String INVITEE_EMAIL_PREFIX = "invitee";
private static final String INVITEE_SITE_ROLE = SiteModel.SITE_COLLABORATOR;
private static final String SITE_SHORT_NAME_INVITE_1 = "BananaMilkshakeSite";
private static final String SITE_SHORT_NAME_INVITE_2 = "DoubleScoopSite";
@@ -144,6 +144,7 @@ public class InviteServiceTest extends BaseWebScriptTest
"InviteSitePreset", SITE_SHORT_NAME_INVITE_1,
"InviteSiteTitle", "InviteSiteDescription", true);
}
SiteInfo siteInfo2 = InviteServiceTest.this.siteService
.getSite(SITE_SHORT_NAME_INVITE_2);
if (siteInfo2 == null)
@@ -298,8 +299,8 @@ public class InviteServiceTest extends BaseWebScriptTest
}
}
private JSONObject startInvite(String inviteeFirstName,
String inviteeLastName, String inviteeEmail, String siteShortName, int expectedStatus)
private JSONObject startInvite(String inviteeFirstName, String inviteeLastName, String inviteeEmail, String inviteeSiteRole,
String siteShortName, int expectedStatus)
throws Exception
{
this.inviteeEmailAddrs.add(inviteeEmail);
@@ -309,7 +310,7 @@ public class InviteServiceTest extends BaseWebScriptTest
+ "?inviteeFirstName=" + inviteeFirstName + "&inviteeLastName="
+ inviteeLastName + "&inviteeEmail="
+ URLEncoder.encode(inviteeEmail) + "&siteShortName="
+ siteShortName;
+ siteShortName + "&inviteeSiteRole=" + inviteeSiteRole;
MockHttpServletResponse response = getRequest(startInviteUrl,
expectedStatus);
@@ -320,7 +321,7 @@ public class InviteServiceTest extends BaseWebScriptTest
}
private JSONObject startInvite(String inviteeFirstName,
String inviteeLastName, String siteShortName, int expectedStatus)
String inviteeLastName, String inviteeSiteRole, String siteShortName, int expectedStatus)
throws Exception
{
// String inviteeEmail = INVITEE_EMAIL_PREFIX +
@@ -328,7 +329,7 @@ public class InviteServiceTest extends BaseWebScriptTest
// + "@" + INVITEE_EMAIL_DOMAIN;
String inviteeEmail = "glen.johnson@alfresco.com";
return startInvite(inviteeFirstName, inviteeLastName, inviteeEmail, siteShortName,
return startInvite(inviteeFirstName, inviteeLastName, inviteeEmail, inviteeSiteRole, siteShortName,
expectedStatus);
}
@@ -397,7 +398,7 @@ public class InviteServiceTest extends BaseWebScriptTest
public void testStartInvite() throws Exception
{
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME,
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
assertEquals(INVITE_ACTION_START, result.get("action"));
@@ -431,45 +432,45 @@ public class InviteServiceTest extends BaseWebScriptTest
// add invitee person to site: SITE_SHORT_NAME_INVITE
InviteServiceTest.this.siteService.setMembership(
SITE_SHORT_NAME_INVITE_1, inviteeUserName,
SiteModel.SITE_COLLABORATOR);
INVITEE_SITE_ROLE);
return null;
}
}, USER_ADMIN);
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmailAddr,
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmailAddr, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_1, Status.STATUS_CONFLICT);
}
// public void testStartInviteWhenAlreadyInProgress()
// throws Exception
// {
// JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME,
// JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE,
// SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
//
// String inviteeEmail = (String) result.get("inviteeEmail");
//
// startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail,
// startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE,
// SITE_SHORT_NAME_INVITE_1, Status.STATUS_CONFLICT);
// }
//
public void testStartInviteForSameInviteeButTwoDifferentSites()
throws Exception
{
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME,
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
String inviteeEmail = (String) result.get("inviteeEmail");
startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail,
startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, inviteeEmail, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_2, Status.STATUS_OK);
}
public void testCancelInvite() throws Exception
{
// inviter starts invite workflow
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME,
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get hold of invite ID of started invite
@@ -485,7 +486,7 @@ public class InviteServiceTest extends BaseWebScriptTest
public void testAcceptInvite() throws Exception
{
// inviter starts invite (sends out invitation)
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME,
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get hold of invite ID of started invite
@@ -521,7 +522,7 @@ public class InviteServiceTest extends BaseWebScriptTest
public void testRejectInvite() throws Exception
{
// inviter starts invite (sends out invitation)
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME,
JSONObject result = startInvite(INVITEE_FIRSTNAME, INVITEE_LASTNAME, INVITEE_SITE_ROLE,
SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get hold of invite ID of started invite
@@ -558,7 +559,7 @@ public class InviteServiceTest extends BaseWebScriptTest
{
// inviter starts invite workflow
JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME,
INVITEE_LASTNAME, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get hold of workflow ID of started invite workflow instance
@@ -581,7 +582,7 @@ public class InviteServiceTest extends BaseWebScriptTest
{
// inviter starts invite workflow
JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME,
INVITEE_LASTNAME, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get pending invites matching inviter user name used in invite started
// above
@@ -599,7 +600,7 @@ public class InviteServiceTest extends BaseWebScriptTest
{
// inviter starts invite workflow
JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME,
INVITEE_LASTNAME, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get hold of invitee user name property of started invite workflow
// instance
@@ -624,7 +625,7 @@ public class InviteServiceTest extends BaseWebScriptTest
{
// inviter starts invite workflow
JSONObject startInviteResult = startInvite(INVITEE_FIRSTNAME,
INVITEE_LASTNAME, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
INVITEE_LASTNAME, INVITEE_SITE_ROLE, SITE_SHORT_NAME_INVITE_1, Status.STATUS_OK);
// get hold of site short name property of started invite workflow
// instance