Fix for inviteresponse web script - when an invitation is either accepted or rejected, the respective tasks in the invite workflow are now getting ended properly, thus ending the workflow

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10105 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Glen Johnson
2008-07-29 15:50:42 +00:00
parent 87782d4124
commit 6079c6fdfb
4 changed files with 110 additions and 54 deletions

View File

@@ -310,6 +310,7 @@
<property name="mutableAuthenticationDao" ref="authenticationDao"/> <property name="mutableAuthenticationDao" ref="authenticationDao"/>
<property name="siteService" ref="siteService"/> <property name="siteService" ref="siteService"/>
<property name="personService" ref="personService"/> <property name="personService" ref="personService"/>
<property name="namespaceService" ref="namespaceService"/>
</bean> </bean>
<!-- --> <!-- -->

View File

@@ -58,12 +58,12 @@
<task-node name="inviteAccepted"> <task-node name="inviteAccepted">
<task name="wf:acceptInviteTask" swimlane="assignee" /> <task name="wf:acceptInviteTask" swimlane="assignee" />
<transition name="" to="end" /> <transition name="end" to="end" />
</task-node> </task-node>
<task-node name="inviteRejected"> <task-node name="inviteRejected">
<task name="wf:rejectInviteTask" swimlane="assignee" /> <task name="wf:rejectInviteTask" swimlane="assignee" />
<transition name="" to="end" /> <transition name="end" to="end" />
</task-node> </task-node>
<end-state name="end" /> <end-state name="end" />

View File

@@ -34,8 +34,12 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.site.SiteModel;
import org.alfresco.repo.site.SiteService; import org.alfresco.repo.site.SiteService;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.scripts.DeclarativeWebScript; import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status; import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException; import org.alfresco.web.scripts.WebScriptException;
@@ -85,8 +89,13 @@ public class InviteResponse extends DeclarativeWebScript
private static final String RESPONSE_ACCEPT = "accept"; private static final String RESPONSE_ACCEPT = "accept";
private static final String RESPONSE_REJECT = "reject"; private static final String RESPONSE_REJECT = "reject";
private static final String TRANSITION_ACCEPT = "accept"; private static final String WF_TASK_ACCEPT_INVITE = "wf:acceptInviteTask";
private static final String TRANSITION_REJECT = "reject"; private static final String WF_TASK_REJECT_INVITE = "wf:rejectInviteTask";
private static final String WF_TASK_INVITE_PENDING = "wf:invitePendingTask";
private static final String WF_TRANSITION_ACCEPT = "accept";
private static final String WF_TRANSITION_REJECT = "reject";
private static final String WF_TRANSITION_ACCEPT_INVITE_END = "end";
private static final String WF_TRANSITION_REJECT_INVITE_END = "end";
private static final String MODEL_PROP_KEY_RESPONSE = "response"; private static final String MODEL_PROP_KEY_RESPONSE = "response";
private static final String MODEL_PROP_KEY_SITE_SHORT_NAME = "siteShortName"; private static final String MODEL_PROP_KEY_SITE_SHORT_NAME = "siteShortName";
private static final String USER_ADMIN = "admin"; private static final String USER_ADMIN = "admin";
@@ -96,6 +105,7 @@ public class InviteResponse extends DeclarativeWebScript
private MutableAuthenticationDao mutableAuthenticationDao; private MutableAuthenticationDao mutableAuthenticationDao;
private SiteService siteService; private SiteService siteService;
private PersonService personService; private PersonService personService;
private NamespaceService namespaceService;
/** /**
* Sets the workflow service property * Sets the workflow service property
@@ -141,6 +151,17 @@ public class InviteResponse extends DeclarativeWebScript
{ {
this.personService = personService; this.personService = personService;
} }
/**
* Sets the namespaceService property
*
* @param namespaceService
* the namespace service to set
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
@@ -230,37 +251,28 @@ public class InviteResponse extends DeclarativeWebScript
private void acceptInvite(Map<String, Object> model, String inviteId, private void acceptInvite(Map<String, Object> model, String inviteId,
String inviteeUserName, String siteShortName) String inviteeUserName, String siteShortName)
{ {
// get workflow ID from invite ID (of which the value is actually // complete the wf:invitePendingTask task because the invitation has been accepted
// just the ID of the invite workflow instance) completeInviteTask(QName.createQName(WF_TASK_INVITE_PENDING, this.namespaceService), WF_TRANSITION_ACCEPT);
String workflowId = inviteId;
// get workflow paths associated with workflow ID // TODO glen dot johnson at alfresco dot com - farm the code that follows (up until adding properties onto
List<WorkflowPath> wfPaths = this.workflowService // the model) out into workflow action class that gets run when task wf:acceptInviteTask
.getWorkflowPaths(workflowId); // is completed by this web script
// throw web script exception if there is not at least one workflow path
// associated with this workflow ID
if ((wfPaths == null) || (wfPaths.size() == 0))
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR,
"There are no workflow paths associated with workflow ID: "
+ workflowId);
}
// get workflow path ID for path matching workflow ID
WorkflowPath wfPath = wfPaths.get(0);
String wfPathID = wfPath.id;
this.workflowService.signal(wfPathID, TRANSITION_ACCEPT);
// enable invitee person's user account because he/she has accepted the // enable invitee person's user account because he/she has accepted the
// site invitation // site invitation
this.mutableAuthenticationDao.setEnabled(inviteeUserName, true); this.mutableAuthenticationDao.setEnabled(inviteeUserName, true);
// Add Invitee to Site as "Site Collaborator" role // Add Invitee to Site as "Site Collaborator" role
RunAsWork<Boolean> setSiteMembershipWorker = new InviteResponse.SetSiteMembershipWorker( RunAsWork<Boolean> setSiteMembershipWorker = new InviteResponse.SetSiteMembershipWorker(
siteShortName, inviteeUserName, SiteModel.SITE_COLLABORATOR); siteShortName, inviteeUserName, SiteModel.SITE_COLLABORATOR);
AuthenticationUtil.runAs(setSiteMembershipWorker, USER_ADMIN); 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
completeInviteTask(QName.createQName(WF_TASK_ACCEPT_INVITE, this.namespaceService), WF_TRANSITION_ACCEPT_INVITE_END);
// add model properties for template to render // add model properties for template to render
model.put(MODEL_PROP_KEY_RESPONSE, RESPONSE_ACCEPT); model.put(MODEL_PROP_KEY_RESPONSE, RESPONSE_ACCEPT);
@@ -284,34 +296,58 @@ public class InviteResponse extends DeclarativeWebScript
private void rejectInvite(Map<String, Object> model, String inviteId, private void rejectInvite(Map<String, Object> model, String inviteId,
String inviteeUserName, String siteShortName) String inviteeUserName, String siteShortName)
{ {
// get workflow ID from invite ID (of which the value is actually // complete the wf:invitePendingTask task because the invitation has been accepted
// just the ID of the invite workflow instance) completeInviteTask(QName.createQName(WF_TASK_INVITE_PENDING, this.namespaceService), WF_TRANSITION_REJECT);
String workflowId = inviteId;
// get workflow paths associated with workflow ID // TODO glen dot johnson at alfresco dot com - farm the code that follows (up until adding properties onto
List<WorkflowPath> wfPaths = this.workflowService // the model) out into workflow action class that gets run when task wf:rejectInviteTask
.getWorkflowPaths(workflowId); // is completed by this web script
// throw web script exception if there is not at least one workflow path
// associated with this workflow ID
if ((wfPaths == null) || (wfPaths.size() == 0))
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR,
"There are no workflow paths associated with workflow ID: "
+ workflowId);
}
// get workflow path ID for path matching workflow ID
WorkflowPath wfPath = wfPaths.get(0);
String wfPathID = wfPath.id;
this.workflowService.signal(wfPathID, TRANSITION_REJECT);
// delete the person created for invitee // delete the person created for invitee
this.personService.deletePerson(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
completeInviteTask(QName.createQName(WF_TASK_REJECT_INVITE, this.namespaceService), WF_TRANSITION_REJECT_INVITE_END);
// add model properties for template to render // add model properties for template to render
model.put(MODEL_PROP_KEY_RESPONSE, RESPONSE_REJECT); model.put(MODEL_PROP_KEY_RESPONSE, RESPONSE_REJECT);
model.put(MODEL_PROP_KEY_SITE_SHORT_NAME, siteShortName); model.put(MODEL_PROP_KEY_SITE_SHORT_NAME, siteShortName);
} }
/**
* Complete the specified Invite Workflow Task and follow the given
* transition upon completing the task
*
* @param fullTaskName qualified name of invite workflow task to complete
* @param transitionId the task transition to take on completion of
* the task (or null, for the default transition)
*/
private void completeInviteTask(QName fullTaskName, String transitionId)
{
// create workflow task query
WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery();
// find incomplete invite workflow tasks with given task name
wfTaskQuery.setActive(Boolean.TRUE);
wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS);
wfTaskQuery.setTaskName(fullTaskName);
// set process name to "wf:invite" so that only
// invite workflow instances are considered by this query
wfTaskQuery.setProcessName(QName.createQName("wf:invite", this.namespaceService));
// query for invite workflow tasks with the constructed query
List<WorkflowTask> wf_invite_tasks = this.workflowService
.queryTasks(wfTaskQuery);
// end all tasks found with this name
for (WorkflowTask workflowTask : wf_invite_tasks)
{
this.workflowService.endTask(workflowTask.id, transitionId);
}
}
} }

View File

@@ -33,8 +33,8 @@ import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyMap; import org.alfresco.util.PropertyMap;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.Status; import org.alfresco.web.scripts.Status;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@@ -52,7 +52,6 @@ public class InviteServiceTest extends BaseWebScriptTest
private AuthenticationComponent authenticationComponent; private AuthenticationComponent authenticationComponent;
private PersonService personService; private PersonService personService;
private SiteService siteService; private SiteService siteService;
private TransactionService transactionService;
private static final String USER_ADMIN = "admin"; private static final String USER_ADMIN = "admin";
private static final String USER_INVITER = "InviterUser"; private static final String USER_INVITER = "InviterUser";
@@ -60,7 +59,6 @@ public class InviteServiceTest extends BaseWebScriptTest
private static final String INVITEE_LASTNAME = "InviteeLastName"; private static final String INVITEE_LASTNAME = "InviteeLastName";
private static final String INVITEE_EMAIL = "inviteeFN.inviteeLN@email123.com"; private static final String INVITEE_EMAIL = "inviteeFN.inviteeLN@email123.com";
private static final String SITE_SHORT_NAME_INVITE = "InviteSiteShortName"; private static final String SITE_SHORT_NAME_INVITE = "InviteSiteShortName";
private static final String GROUP_EMAIL_CONTRIBUTORS = "EMAIL_CONTRIBUTORS";
private static final String URL_INVITE_SERVICE = "/api/invite"; private static final String URL_INVITE_SERVICE = "/api/invite";
private static final String URL_INVITERSP_SERVICE = "/api/inviteresponse"; private static final String URL_INVITERSP_SERVICE = "/api/inviteresponse";
@@ -88,8 +86,6 @@ public class InviteServiceTest extends BaseWebScriptTest
.getApplicationContext().getBean("PersonService"); .getApplicationContext().getBean("PersonService");
this.siteService = (SiteService) getServer().getApplicationContext() this.siteService = (SiteService) getServer().getApplicationContext()
.getBean("siteService"); .getBean("siteService");
this.transactionService = (TransactionService) getServer().getApplicationContext()
.getBean("transactionService");
// set current user as admin for various setup operations needing admin rights // set current user as admin for various setup operations needing admin rights
this.authenticationComponent.setCurrentUser(USER_ADMIN); this.authenticationComponent.setCurrentUser(USER_ADMIN);
@@ -197,7 +193,8 @@ public class InviteServiceTest extends BaseWebScriptTest
// Inviter sends invitation to Invitee to join a Site // Inviter sends invitation to Invitee to join a Site
String startInviteUrl = URL_INVITE_SERVICE + "/" + INVITE_ACTION_START String startInviteUrl = URL_INVITE_SERVICE + "/" + INVITE_ACTION_START
+ "?inviteeFirstName=" + inviteeFirstName + "&inviteeLastName=" + inviteeLastName + "?inviteeFirstName=" + inviteeFirstName + "&inviteeLastName=" + inviteeLastName
+ "&inviteeEmail=" + inviteeEmail + "&siteShortName=" + siteShortName; + "&inviteeEmail=" + URLEncoder.encode(inviteeEmail) + "&siteShortName=" + siteShortName;
MockHttpServletResponse response = getRequest(startInviteUrl, expectedStatus); MockHttpServletResponse response = getRequest(startInviteUrl, expectedStatus);
JSONObject result = new JSONObject(response.getContentAsString()); JSONObject result = new JSONObject(response.getContentAsString());
@@ -313,6 +310,17 @@ public class InviteServiceTest extends BaseWebScriptTest
+ SITE_SHORT_NAME_INVITE; + SITE_SHORT_NAME_INVITE;
MockHttpServletResponse response = getRequest(acceptInviteUrl, MockHttpServletResponse response = getRequest(acceptInviteUrl,
Status.STATUS_OK); Status.STATUS_OK);
//
// test that invitation represented by invite ID (of invitation started above)
// is no longer pending (as a result of the invitation having being accepted)
//
// get pending invite matching inviteId from invite started above
JSONArray getInvitesResult = getInvitesByInviteId(inviteId, Status.STATUS_OK);
// there should no longer be any invites identified by invite ID pending
assertEquals(getInvitesResult.length(), 0);
} }
public void testRejectInvite() throws Exception public void testRejectInvite() throws Exception
@@ -335,6 +343,17 @@ public class InviteServiceTest extends BaseWebScriptTest
+ SITE_SHORT_NAME_INVITE; + SITE_SHORT_NAME_INVITE;
MockHttpServletResponse response = getRequest(rejectInviteUrl, MockHttpServletResponse response = getRequest(rejectInviteUrl,
Status.STATUS_OK); Status.STATUS_OK);
//
// test that invite represented by invite ID (of invitation started above)
// is no longer pending (as a result of the invitation having being rejected)
//
// get pending invite matching inviteId from invite started above
JSONArray getInvitesResult = getInvitesByInviteId(inviteId, Status.STATUS_OK);
// there should no longer be any invites identified by invite ID pending
assertEquals(getInvitesResult.length(), 0);
} }
public void testGetInvitesByInviteId() throws Exception public void testGetInvitesByInviteId() throws Exception