From 60d6dd8cd714f163dd49081cbbf8e33f6db1f46c Mon Sep 17 00:00:00 2001 From: N Smith Date: Tue, 26 Jan 2010 13:38:28 +0000 Subject: [PATCH] Merged V3.2 to HEAD Merged in r17325. Fixing ETHREEOH-3030 Moved some behaviour out of Javascript embedded in nomination-invitation-processdefinition.xml into a Java class SendInviteAction. Added tests to ensure whitespace and special characters are handled properly. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18303 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- ...invitation-nominated_processdefinition.xml | 43 +- .../invitation/InvitationServiceImpl.java | 2466 ++++++++--------- .../invitation/InvitationServiceImplTest.java | 1550 +++++------ .../WorkflowModelNominatedInvitation.java | 17 +- .../repo/invitation/site/InviteSender.java | 255 ++ .../invitation/site/InviteSenderTest.java | 332 +++ .../invitation/site/SendInviteAction.java | 99 + 7 files changed, 2629 insertions(+), 2133 deletions(-) create mode 100644 source/java/org/alfresco/repo/invitation/site/InviteSender.java create mode 100644 source/java/org/alfresco/repo/invitation/site/InviteSenderTest.java create mode 100644 source/java/org/alfresco/repo/invitation/site/SendInviteAction.java diff --git a/config/alfresco/workflow/invitation-nominated_processdefinition.xml b/config/alfresco/workflow/invitation-nominated_processdefinition.xml index 8093a7b5bd..2869a168fe 100644 --- a/config/alfresco/workflow/invitation-nominated_processdefinition.xml +++ b/config/alfresco/workflow/invitation-nominated_processdefinition.xml @@ -3,7 +3,7 @@ + name="inwf:invitation-nominated"> @@ -12,46 +12,7 @@ - - - + diff --git a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java index 508c1f475e..df89764b11 100644 --- a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java +++ b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java @@ -22,6 +22,7 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ + package org.alfresco.repo.invitation; import java.io.Serializable; @@ -33,7 +34,6 @@ import java.util.Map; import java.util.Set; import org.alfresco.model.ContentModel; -import org.alfresco.repo.invitation.site.InviteHelper; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; @@ -58,8 +58,8 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowException; import org.alfresco.service.cmr.workflow.WorkflowInstance; @@ -71,55 +71,51 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; -import org.springframework.extensions.surf.util.PropertyCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.PropertyCheck; /** * Implementation of invitation service. * * @see org.alfresco.service.cmr.invitation.Invitation - * * @author mrogers - * */ public class InvitationServiceImpl implements InvitationService, NodeServicePolicies.BeforeDeleteNodePolicy { - private static final Log logger = LogFactory - .getLog(InvitationServiceImpl.class); - - /** - * Services - */ - private WorkflowService workflowService; - private PersonService personService; - private SiteService siteService; - private MutableAuthenticationService authenticationService; - private PermissionService permissionService; - private NamespaceService namespaceService; - private NodeService nodeService; - // user name and password generation beans - private UserNameGenerator usernameGenerator; - private PasswordGenerator passwordGenerator; + private static final Log logger = LogFactory.getLog(InvitationServiceImpl.class); + + /** + * Services + */ + private WorkflowService workflowService; + private PersonService personService; + private SiteService siteService; + private MutableAuthenticationService authenticationService; + private PermissionService permissionService; + private NamespaceService namespaceService; + private NodeService nodeService; + // user name and password generation beans + private UserNameGenerator usernameGenerator; + private PasswordGenerator passwordGenerator; private PolicyComponent policyComponent; - // maximum number of tries to generate a invitee user name which - // does not already belong to an existing person - public static final int MAX_NUM_INVITEE_USER_NAME_GEN_TRIES = 10; - - private int maxUserNameGenRetries = MAX_NUM_INVITEE_USER_NAME_GEN_TRIES; - + // maximum number of tries to generate a invitee user name which + // does not already belong to an existing person + public static final int MAX_NUM_INVITEE_USER_NAME_GEN_TRIES = 10; + + private int maxUserNameGenRetries = MAX_NUM_INVITEE_USER_NAME_GEN_TRIES; + /** * Set the policy component * - * @param policyComponent policy component + * @param policyComponent policy component */ public void setPolicyComponent(PolicyComponent policyComponent) { this.policyComponent = policyComponent; } - - + /** * Checks that all necessary properties and services have been provided. */ @@ -136,306 +132,162 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli PropertyCheck.mandatory(this, "UserNameGenerator", usernameGenerator); PropertyCheck.mandatory(this, "PasswordGenerator", passwordGenerator); PropertyCheck.mandatory(this, "PolicyComponent", policyComponent); - + // - this.policyComponent.bindClassBehaviour( - QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"), - SiteModel.TYPE_SITE, - new JavaBehaviour(this, "beforeDeleteNode")); + this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"), + SiteModel.TYPE_SITE, new JavaBehaviour(this, "beforeDeleteNode")); } - - /** - * Get the names of the workflows which are managed by the invitation service - * @return the workflows which are managed by the invitation service - */ - public List getInvitationServiceWorkflowNames() - { - List ret = new ArrayList(3); - ret.add(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); - ret.add(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); - // old deprecated invitation workflow. - ret.add("jbpm$wf:invite"); - return ret; - } - /** - * Start the invitation process for a NominatedInvitation - * - * @param inviteeUserName Alfresco user name of the invitee - * @param Invitation - * @param ResourceType resourceType - * @param resourceName - * @param inviteeRole - * @param serverPath - * @param acceptUrl - * @param rejectUrl - * - * @return the nominated invitation which will contain the invitationId and - * ticket which will uniqely identify this invitation for the rest - * of the workflow. - * - * @throws InvitationException - * @throws InvitationExceptionUserError - * @throws InvitationExceptionForbidden - */ - public NominatedInvitation inviteNominated(String inviteeUserName, - Invitation.ResourceType resourceType, - String resourceName, - String inviteeRole, - String serverPath, - String acceptUrl, - String rejectUrl) - { - // inviteeUserName was specified - NodeRef person = this.personService.getPerson(inviteeUserName); - - Serializable firstNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_FIRSTNAME); - Serializable lastNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_LASTNAME); - Serializable emailVal = this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL); - String firstName = DefaultTypeConverter.INSTANCE.convert( - String.class, firstNameVal); - String lastName = DefaultTypeConverter.INSTANCE.convert( - String.class, lastNameVal); - String email = DefaultTypeConverter.INSTANCE.convert( - String.class, emailVal); + /** + * Get the names of the workflows which are managed by the invitation + * service + * + * @return the workflows which are managed by the invitation service + */ + public List getInvitationServiceWorkflowNames() + { + List ret = new ArrayList(3); + ret.add(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); + ret.add(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); + // old deprecated invitation workflow. + ret.add("jbpm$wf:invite"); + return ret; + } - return inviteNominated(firstName, lastName, email, - inviteeUserName, resourceType, resourceName, inviteeRole, - serverPath, acceptUrl, rejectUrl); - } - - /** - * Start the invitation process for a NominatedInvitation - * - * @param inviteeFirstName - * @param inviteeLastName - * @param inviteeEmail - * @param inviteeUserName - * optional Alfresco user name of the invitee, null if not on - * system. - * @param Invitation - * .ResourceType resourceType - * @param resourceName - * @param inviteeRole - * @param serverPath - * @param acceptUrl - * @param rejectUrl - * - * @return the nominated invitation which will contain the invitationId and - * ticket which will uniqely identify this invitation for the rest - * of the workflow. - * - * @throws InvitationException - * @throws InvitationExceptionUserError - * @throws InvitationExceptionForbidden - */ - public NominatedInvitation inviteNominated( - String inviteeFirstName, - String inviteeLastName, - String inviteeEmail, - Invitation.ResourceType resourceType, - String resourceName, - String inviteeRole, - String serverPath, - String acceptUrl, - String rejectUrl) - { - return inviteNominated(inviteeFirstName, - inviteeLastName, - inviteeEmail, - null, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl); - } + /** + * Start the invitation process for a NominatedInvitation + * + * @param inviteeUserName Alfresco user name of the invitee + * @param Invitation + * @param ResourceType resourceType + * @param resourceName + * @param inviteeRole + * @param serverPath + * @param acceptUrl + * @param rejectUrl + * @return the nominated invitation which will contain the invitationId and + * ticket which will uniqely identify this invitation for the rest + * of the workflow. + * @throws InvitationException + * @throws InvitationExceptionUserError + * @throws InvitationExceptionForbidden + */ + public NominatedInvitation inviteNominated(String inviteeUserName, Invitation.ResourceType resourceType, + String resourceName, String inviteeRole, String serverPath, String acceptUrl, String rejectUrl) + { + // inviteeUserName was specified + NodeRef person = this.personService.getPerson(inviteeUserName); + + Serializable firstNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_FIRSTNAME); + Serializable lastNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_LASTNAME); + Serializable emailVal = this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL); + String firstName = DefaultTypeConverter.INSTANCE.convert(String.class, firstNameVal); + String lastName = DefaultTypeConverter.INSTANCE.convert(String.class, lastNameVal); + String email = DefaultTypeConverter.INSTANCE.convert(String.class, emailVal); + + return inviteNominated(firstName, lastName, email, inviteeUserName, resourceType, resourceName, inviteeRole, + serverPath, acceptUrl, rejectUrl); + } + + /** + * Start the invitation process for a NominatedInvitation + * + * @param inviteeFirstName + * @param inviteeLastName + * @param inviteeEmail + * @param inviteeUserName optional Alfresco user name of the invitee, null + * if not on system. + * @param Invitation .ResourceType resourceType + * @param resourceName + * @param inviteeRole + * @param serverPath + * @param acceptUrl + * @param rejectUrl + * @return the nominated invitation which will contain the invitationId and + * ticket which will uniqely identify this invitation for the rest + * of the workflow. + * @throws InvitationException + * @throws InvitationExceptionUserError + * @throws InvitationExceptionForbidden + */ + public NominatedInvitation inviteNominated(String inviteeFirstName, String inviteeLastName, String inviteeEmail, + Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String serverPath, + String acceptUrl, String rejectUrl) + { + return inviteNominated(inviteeFirstName, inviteeLastName, inviteeEmail, null, resourceType, resourceName, + inviteeRole, serverPath, acceptUrl, rejectUrl); + } // Temporary method - private NominatedInvitation inviteNominated(String inviteeFirstName, - String inviteeLastName, - String inviteeEmail, - String inviteeUserName, - Invitation.ResourceType resourceType, - String resourceName, - String inviteeRole, - String serverPath, - String acceptUrl, - String rejectUrl) - { - // Validate the request + private NominatedInvitation inviteNominated(String inviteeFirstName, String inviteeLastName, String inviteeEmail, + String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole, + String serverPath, String acceptUrl, String rejectUrl) + { + // Validate the request - // Check resource exists + // Check resource exists - if (resourceType == Invitation.ResourceType.WEB_SITE) - { - return startNominatedInvite(inviteeFirstName, inviteeLastName, inviteeEmail, - inviteeUserName, resourceType, resourceName, inviteeRole, - serverPath, acceptUrl, rejectUrl); - } + if (resourceType == Invitation.ResourceType.WEB_SITE) + { + return startNominatedInvite(inviteeFirstName, inviteeLastName, inviteeEmail, inviteeUserName, resourceType, + resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + } - throw new InvitationException("unknown resource type"); - } + throw new InvitationException("unknown resource type"); + } - /** - * Start the invitation process for a ModeratedInvitation - * - * @param comments - * why does the invitee want access to the resource ? - * @param inviteeUserName - * who is to be invited - * @param Invitation - * .ResourceType resourceType what resource type ? - * @param resourceName - * which resource - * @param inviteeRole - * which role ? - */ - public ModeratedInvitation inviteModerated(String inviteeComments, - String inviteeUserName, Invitation.ResourceType resourceType, - String resourceName, String inviteeRole) - { - if (resourceType == Invitation.ResourceType.WEB_SITE) - { - return startModeratedInvite(inviteeComments, inviteeUserName, resourceType, - resourceName, inviteeRole); - } - throw new InvitationException("unknown resource type"); - } + /** + * Start the invitation process for a ModeratedInvitation + * + * @param comments why does the invitee want access to the resource ? + * @param inviteeUserName who is to be invited + * @param Invitation .ResourceType resourceType what resource type ? + * @param resourceName which resource + * @param inviteeRole which role ? + */ + public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, + Invitation.ResourceType resourceType, String resourceName, String inviteeRole) + { + if (resourceType == Invitation.ResourceType.WEB_SITE) + { + return startModeratedInvite(inviteeComments, inviteeUserName, resourceType, resourceName, inviteeRole); + } + throw new InvitationException("unknown resource type"); + } - /** - * Invitee accepts this invitation - * - * Nominated Invitaton process only - * - * @param invitationId the invitation id - * @param ticket the ticket produced when creating the invitation. - */ - public Invitation accept(String invitationId, String ticket) { - Invitation invitation = getInvitation(invitationId); + /** + * Invitee accepts this invitation Nominated Invitaton process only + * + * @param invitationId the invitation id + * @param ticket the ticket produced when creating the invitation. + */ + public Invitation accept(String invitationId, String ticket) + { + Invitation invitation = getInvitation(invitationId); - if (invitation instanceof NominatedInvitation) { + if (invitation instanceof NominatedInvitation) + { - // Check invitationId and ticket match - if (ticket == null - || (!ticket.equals(((NominatedInvitation) invitation) - .getTicket()))) { - throw new InvitationException( - "Response to invite has supplied an invalid ticket. The response to the " - + "invitation could thus not be processed"); - } - - /** - * Nominated invitation complete the wf:invitePendingTask along the - * 'accept' transition because the invitation has been accepted - */ - - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set the given invite ID as the workflow process ID in the workflow query - wfTaskQuery.setProcessId(invitationId); - - // find incomplete invite workflow tasks with given task name - wfTaskQuery.setActive(Boolean.TRUE); - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - - // set process name to "wf:invite" so that only - // invite workflow instances are considered by this query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks with the constructed query - List wf_invite_tasks = workflowService - .queryTasks(wfTaskQuery); - - if(wf_invite_tasks.size() == 0) + // Check invitationId and ticket match + if (ticket == null || (!ticket.equals(((NominatedInvitation) invitation).getTicket()))) { - Object objs[] = { invitationId }; - throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); + throw new InvitationException("Response to invite has supplied an invalid ticket. The response to the " + + "invitation could thus not be processed"); } - - // end all tasks found with this name - for (WorkflowTask workflowTask : wf_invite_tasks) - { - workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_ACCEPT); - } - return invitation; - } - throw new InvitationException( - "State error, cannot call accept a moderated invitation"); + /** + * Nominated invitation complete the wf:invitePendingTask along the + * 'accept' transition because the invitation has been accepted + */ - } - - /** - * Moderator approves this invitation - * - * @param request the request to approve - * @param reason comments about the acceptance - */ - public Invitation approve(String invitationId, String reason) { - Invitation invitation = getInvitation(invitationId); - if(invitation instanceof ModeratedInvitation) - { - // Check approver is a site manager - String approverUserName = this.authenticationService.getCurrentUserName(); - checkManagerRole(approverUserName, invitation.getResourceType(), invitation.getResourceName()); - - WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); - - // Current Review Moderated Tasks - wfModeratedTaskQuery.setActive(Boolean.TRUE); - wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); - wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); - wfModeratedTaskQuery.setProcessId(invitationId); - - // query for invite review tasks - List wf_moderated_tasks = this.workflowService - .queryTasks(wfModeratedTaskQuery); - - for (WorkflowTask workflowTask : wf_moderated_tasks) - { - Map wfReviewProps = new HashMap(); - wfReviewProps.put(ContentModel.PROP_OWNER, approverUserName); - wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); - workflowService.updateTask(workflowTask.id, wfReviewProps, null, null); - workflowService.endTask(workflowTask.id, WorkflowModelModeratedInvitation.WF_TRANSITION_APPROVE); - } - } - else - { - throw new InvitationException("State error, cannot call approve on this type of invitation" + invitation.getClass().getName()); - } - return invitation; - - } - - /** - * User or moderator rejects this request - * - * @param invitationId - * @param reason - * , optional reason for rejection - */ - public Invitation reject(String invitationId, String reason) { - Invitation invitation = getInvitation(invitationId); - - if (invitation instanceof NominatedInvitation) { - - /** - * Nominated invitation complete the wf:invitePendingTask along the - * 'reject' transition because the invitation has been rejected - */ - // create workflow task query + // create workflow task query WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set the given invite ID as the workflow process ID in the workflow query + + // set the given invite ID as the workflow process ID in the + // workflow query wfTaskQuery.setProcessId(invitationId); - // find incomplete invite workflow tasks with given task name + // find incomplete invite workflow tasks with given task name wfTaskQuery.setActive(Boolean.TRUE); wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); @@ -445,848 +297,925 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); // query for invite workflow tasks with the constructed query - List wf_invite_tasks = workflowService - .queryTasks(wfTaskQuery); - - if(wf_invite_tasks.size() == 0) + List wf_invite_tasks = workflowService.queryTasks(wfTaskQuery); + + if (wf_invite_tasks.size() == 0) { Object objs[] = { invitationId }; - throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); + throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); } - - // end all tasks found with this name + + // end all tasks found with this name for (WorkflowTask workflowTask : wf_invite_tasks) { - workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_REJECT); + workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_ACCEPT); } - return invitation; - } - - if (invitation instanceof ModeratedInvitation) { - WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); - - // Check rejecter is a site manager and throw and exception if not - String rejecterUserName = this.authenticationService.getCurrentUserName(); - checkManagerRole(rejecterUserName, invitation.getResourceType(), invitation.getResourceName()); - - // Current Review Moderated Tasks - wfModeratedTaskQuery.setActive(Boolean.TRUE); - wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); - wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); - wfModeratedTaskQuery.setProcessId(invitationId); - - // query for invite review tasks - List wf_moderated_tasks = this.workflowService - .queryTasks(wfModeratedTaskQuery); - - for (WorkflowTask workflowTask : wf_moderated_tasks) - { - Map wfReviewProps = new HashMap(); - wfReviewProps.put(ContentModel.PROP_OWNER, rejecterUserName); - wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); - workflowService.updateTask(workflowTask.id, wfReviewProps, null, null); - this.workflowService.endTask(workflowTask.id, WorkflowModelModeratedInvitation.WF_TRANSITION_REJECT); - } - - return invitation; - } - - return invitation; - } - - /* - * cancel a pending request - */ - public Invitation cancel(String invitationId) { - Invitation invitation = getInvitation(invitationId); - - if (invitation instanceof NominatedInvitation) { - - // Check canceller is a site manager - String approverUserName = this.authenticationService.getCurrentUserName(); - checkManagerRole(approverUserName, invitation.getResourceType(), invitation.getResourceName()); - - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set the given invite ID as the workflow process ID in the workflow query - wfTaskQuery.setProcessId(invitationId); - - // find incomplete invite workflow tasks with given task name - wfTaskQuery.setActive(Boolean.TRUE); - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - - // set process name to "wf:invite" so that only - // invite workflow instances are considered by this query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks with the constructed query - List wf_invite_tasks = workflowService - .queryTasks(wfTaskQuery); - - // end all tasks found with this name - for (WorkflowTask workflowTask : wf_invite_tasks) - { - workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_CANCEL); - } - } - - if (invitation instanceof ModeratedInvitation) - { - // Moderated invitation may be cancelled by either a site manager or the invitee. - String currentUserName = this.authenticationService.getCurrentUserName(); - - if(!currentUserName.equals(((ModeratedInvitation) invitation).getInviteeUserName())) - { - checkManagerRole(currentUserName, invitation.getResourceType(), invitation.getResourceName()); - } - workflowService.cancelWorkflow(invitationId); - } - - return invitation; - } - - /** - * Get an invitation from its invitation id - *
- * - * Invitations are returned which may be in progress or completed. - * - * @throws InvitationExceptionNotFound the invitation does not exist. - * @throws InvitationExceptionUserError - * @return the invitation. - */ - public Invitation getInvitation(String invitationId) { - - validateInvitationId(invitationId); - - WorkflowInstance wi = null; - try - { - wi = workflowService.getWorkflowById(invitationId); - } - catch (WorkflowException we) - { - // Do nothing - } - - if (wi == null) { - Object objs[] = { invitationId }; - throw new InvitationExceptionNotFound("invitation.error.not_found", - objs); - } - String workflowName = wi.definition.getName(); - - if (workflowName - .equals(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME)) { - // This is a nominated invitation - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - wfTaskQuery.setProcessId(invitationId); - - // filter to find only the start task which contains the properties. - wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE); - - // query for invite workflow task associate - List inviteStartTasks = workflowService - .queryTasks(wfTaskQuery); - - // should also be 0 or 1 - if (inviteStartTasks.size() < 1) { - Object objs[] = { invitationId }; - throw new InvitationExceptionNotFound("invitation.error.not_found", - objs); - } else { - WorkflowTask task = inviteStartTasks.get(0); - NominatedInvitationImpl result = new NominatedInvitationImpl( - task.properties); - result.setSentInviteDate(task.path.instance.startDate); - result.setInviteId(invitationId); - return result; - } - } - if (workflowName - .equals(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME)) { - // This is a moderated invitation - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - wfTaskQuery.setProcessId(invitationId); - - // filter to find only the start task which contains the properties. - wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); - wfTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_START_TASK); - - List inviteStartTasks = workflowService.queryTasks(wfTaskQuery); - - // should also be 0 or 1 - if (inviteStartTasks.size() < 1) { - // No start task - workflow may have been completed - Object objs[] = { invitationId }; - throw new InvitationExceptionNotFound("invitation.error.not_found", - objs); - } else { - WorkflowTask task = inviteStartTasks.get(0); - ModeratedInvitationImpl result = new ModeratedInvitationImpl( - task.properties); - result.setInviteId(invitationId); - return result; - } - } - - // Unknown workflow type here - return null; - } - - /** - * list Invitations for a specific person/invitee - * - * @param invitee - * alfresco user id of person being invited - */ - public List listPendingInvitationsForInvitee(String invitee) { - InvitationSearchCriteriaImpl crit = new InvitationSearchCriteriaImpl(); - crit.setInvitationType(InvitationSearchCriteria.InvitationType.ALL); - crit.setInvitee(invitee); - return searchInvitation(crit); - } - - /** - * list Invitations for a specific resource - * - * @param resourceType - * @param resourceName - */ - public List listPendingInvitationsForResource( - Invitation.ResourceType resourceType, String resourceName) { - InvitationSearchCriteriaImpl crit = new InvitationSearchCriteriaImpl(); - crit.setInvitationType(InvitationSearchCriteria.InvitationType.ALL); - crit.setResourceType(resourceType); - crit.setResourceName(resourceName); - return searchInvitation(crit); - } - - /** - * This is the general search invitation method - * - * @param criteria - * @return the list of invitations - */ - public List searchInvitation(InvitationSearchCriteria criteria) { - - List ret = new ArrayList(); - - InvitationSearchCriteria.InvitationType toSearch = criteria.getInvitationType(); - - /** - * Nominated search below - */ - if(toSearch == InvitationSearchCriteria.InvitationType.ALL || toSearch == InvitationSearchCriteria.InvitationType.NOMINATED) - { - // query for nominated workflow tasks by given parameters - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - HashMap wfNominatedQueryProps = new HashMap(10, - 1.0f); - - if (criteria.getInviter() != null) - { - wfNominatedQueryProps.put( - WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME, - criteria.getInviter()); - } - if (criteria.getInvitee() != null) - { - wfNominatedQueryProps.put( - WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME, - criteria.getInvitee()); - } - if (criteria.getResourceType() != null) - { - wfNominatedQueryProps.put( - WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE, - criteria.getResourceType().toString()); - } - if (criteria.getResourceName() != null) - { - wfNominatedQueryProps.put( - WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME, - criteria.getResourceName()); - } - - // set workflow task query parameters - wfTaskQuery.setProcessCustomProps(wfNominatedQueryProps); - - // query only active workflows - wfTaskQuery.setActive(Boolean.TRUE); - - // pick up the pending task - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks - List wf_invite_tasks = this.workflowService - .queryTasks(wfTaskQuery); - - for (WorkflowTask workflowTask : wf_invite_tasks) { - // get workflow instance (ID) that pendingInvite task (in query - // result set) - - String workflowId = workflowTask.path.instance.id; - //TODO ALFCOM-2597 workflowTask.properties does not contain custom process values - // NominatedInvitationImpl result = new NominatedInvitationImpl(workflowTask.properties); - // result.setInviteId(workflowId); - // ret.add(result); - - Invitation result = getInvitation(workflowId); - - // TODO ALFCOM-2598 records are being returned that do not match properties - Setkeys = wfNominatedQueryProps.keySet(); - boolean crap = false; - for(QName key : keys) - { - if(key.equals(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME)) - { - Object val1 = wfNominatedQueryProps.get(key); - Object val2 = ((NominatedInvitation)result).getInviteeUserName(); - if (!val1.equals(val2)) - { - // Uh oh ... crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - if(key.equals(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME)) - { - Object val1 = wfNominatedQueryProps.get(key); - Object val2 = result.getResourceName(); - if (!val1.equals(val2)) - { - // Uh oh ... crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - if(key.equals(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE)) - { - Object val1 = wfNominatedQueryProps.get(key); - Object val2 = result.getResourceType().toString(); - if (!val1.equals(val2)) - { - - // Uh oh ... crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - } - - if(!crap) - { - ret.add(result); - } - } - } - - /** - * Moderated search below - */ - if(toSearch == InvitationSearchCriteria.InvitationType.ALL || toSearch == InvitationSearchCriteria.InvitationType.MODERATED) - { - // This is a moderated search - WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); - // workflow query properties - HashMap wfQueryModeratedProps = new HashMap(3, 1.0f); - - if (criteria.getInvitee() != null) - { - wfQueryModeratedProps.put( - WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME, - criteria.getInvitee()); - } - if (criteria.getResourceType() != null) - { - wfQueryModeratedProps.put( - WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE, - criteria.getResourceType().toString()); - } - if (criteria.getResourceName() != null) - { - wfQueryModeratedProps.put( - WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME, - criteria.getResourceName()); - } - - // set workflow task query parameters - wfModeratedTaskQuery.setProcessCustomProps(wfQueryModeratedProps); - - // Current Review Moderated Tasks - wfModeratedTaskQuery.setActive(Boolean.TRUE); - wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); - wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); - - // query for invite workflow tasks - List wf_moderated_tasks = this.workflowService - .queryTasks(wfModeratedTaskQuery); - - for (WorkflowTask workflowTask : wf_moderated_tasks) - { - // Add moderated invitations - String workflowId = workflowTask.path.instance.id; - ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowTask.properties); - - // TODO ALFCOM-2598 records are being returned that do not match properties - Setkeys = wfQueryModeratedProps.keySet(); - boolean crap = false; - for(QName key : keys) - { - Object val1 = wfQueryModeratedProps.get(key); - Object val2 = workflowTask.properties.get(key); - if(!val1.equals(val2)) - { - // crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - //TODO END ALFCOM-2598 Work-around - - result.setInviteId(workflowId); - if(!crap) - { - ret.add(result); - } - } - } - - // End moderated invitation - - return ret; - } - - // Implementation methods below - - - /** - * Set the workflow service - * - * @param workflowService - */ - public void setWorkflowService(WorkflowService workflowService) { - this.workflowService = workflowService; - } - - /** - * @return the workflow service - */ - public WorkflowService getWorkflowService() { - return workflowService; - } - - public void setPersonService(PersonService personService) { - this.personService = personService; - } - - public PersonService getPersonService() { - return personService; - } - - public void setSiteService(SiteService siteService) { - this.siteService = siteService; - } - - public SiteService getSiteService() { - return siteService; - } - - public void setAuthenticationService( - MutableAuthenticationService authenticationService) { - this.authenticationService = authenticationService; - } - - public MutableAuthenticationService getAuthenticationService() { - return authenticationService; - } - - public void setUserNameGenerator(UserNameGenerator usernameGenerator) { - this.usernameGenerator = usernameGenerator; - } - - public UserNameGenerator getUserNameGenerator() { - return usernameGenerator; - } - - public void setPasswordGenerator(PasswordGenerator passwordGenerator) { - this.passwordGenerator = passwordGenerator; - } - - public PasswordGenerator getPasswordGenerator() { - return passwordGenerator; - } - - public void setNamespaceService(NamespaceService namespaceService) { - this.namespaceService = namespaceService; - } - - public NamespaceService getNamespaceService() { - return namespaceService; - } - - public void setPermissionService(PermissionService permissionService) { - this.permissionService = permissionService; - } - - public PermissionService getPermissionService() { - return permissionService; - } - - public void setNodeService(NodeService nodeService) { - this.nodeService = nodeService; - } - - public NodeService getNodeService() { - return nodeService; - } - - /** - * Creates a person for the invitee with a generated user name. - * - * @param inviteeFirstName - * first name of invitee - * @param inviteeLastName - * last name of invitee - * @param inviteeEmail - * email address of invitee - * @return invitee user name - */ - private String createInviteePerson(String inviteeFirstName, - String inviteeLastName, String inviteeEmail) { - // Attempt to generate user name for invitee - // which does not belong to an existing person - // Tries up to MAX_NUM_INVITEE_USER_NAME_GEN_TRIES - // at which point a web script exception is thrown - String inviteeUserName = null; - int i = 0; - do { - inviteeUserName = usernameGenerator.generateUserName(inviteeFirstName, inviteeLastName, inviteeEmail, i); - i++; - } while (this.personService.personExists(inviteeUserName) - && (i < getMaxUserNameGenRetries())); - - // if after 10 tries is not able to generate a user name for a - // person who doesn't already exist, then throw a web script exception - if (this.personService.personExists(inviteeUserName)) { - - logger.debug("Failed - unable to generate username for invitee."); - - Object[] objs = { inviteeFirstName, inviteeLastName, inviteeEmail }; - throw new InvitationException( - "invitation.invite.unable_generate_id", objs); - } - - // create a person node for the invitee with generated invitee user name - // and other provided person property values - final Map properties = new HashMap(); - properties.put(ContentModel.PROP_USERNAME, inviteeUserName); - properties.put(ContentModel.PROP_FIRSTNAME, inviteeFirstName); - properties.put(ContentModel.PROP_LASTNAME, inviteeLastName); - properties.put(ContentModel.PROP_EMAIL, inviteeEmail); - - final String finalUserName = inviteeUserName; - AuthenticationUtil.runAs(new RunAsWork() { - public Object doWork() throws Exception { - NodeRef person = personService.createPerson(properties); - permissionService.setPermission(person, finalUserName, - PermissionService.ALL_PERMISSIONS, true); - - return null; - } - - }, AuthenticationUtil.getSystemUserName()); - - return inviteeUserName; - } - - /** - * Creates a disabled user account for the given invitee user name with a - * generated password - * - * @param inviteeUserName - * @return password generated for invitee user account - */ - private String createInviteeDisabledAccount(String inviteeUserName) { - // generate password using password generator - char[] generatedPassword = passwordGenerator.generatePassword() - .toCharArray(); - - // create disabled user account for invitee user name with generated password + return invitation; + } + throw new InvitationException("State error, cannot call accept a moderated invitation"); + + } + + /** + * Moderator approves this invitation + * + * @param request the request to approve + * @param reason comments about the acceptance + */ + public Invitation approve(String invitationId, String reason) + { + Invitation invitation = getInvitation(invitationId); + if (invitation instanceof ModeratedInvitation) + { + // Check approver is a site manager + String approverUserName = this.authenticationService.getCurrentUserName(); + checkManagerRole(approverUserName, invitation.getResourceType(), invitation.getResourceName()); + + WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); + + // Current Review Moderated Tasks + wfModeratedTaskQuery.setActive(Boolean.TRUE); + wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); + wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); + wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); + wfModeratedTaskQuery.setProcessId(invitationId); + + // query for invite review tasks + List wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery); + + for (WorkflowTask workflowTask : wf_moderated_tasks) + { + Map wfReviewProps = new HashMap(); + wfReviewProps.put(ContentModel.PROP_OWNER, approverUserName); + wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); + workflowService.updateTask(workflowTask.id, wfReviewProps, null, null); + workflowService.endTask(workflowTask.id, WorkflowModelModeratedInvitation.WF_TRANSITION_APPROVE); + } + } + else + { + throw new InvitationException("State error, cannot call approve on this type of invitation" + + invitation.getClass().getName()); + } + return invitation; + + } + + /** + * User or moderator rejects this request + * + * @param invitationId + * @param reason , optional reason for rejection + */ + public Invitation reject(String invitationId, String reason) + { + Invitation invitation = getInvitation(invitationId); + + if (invitation instanceof NominatedInvitation) + { + + /** + * Nominated invitation complete the wf:invitePendingTask along the + * 'reject' transition because the invitation has been rejected + */ + // create workflow task query + WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); + + // set the given invite ID as the workflow process ID in the + // workflow query + wfTaskQuery.setProcessId(invitationId); + + // find incomplete invite workflow tasks with given task name + wfTaskQuery.setActive(Boolean.TRUE); + wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); + wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); + + // set process name to "wf:invite" so that only + // invite workflow instances are considered by this query + wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); + + // query for invite workflow tasks with the constructed query + List wf_invite_tasks = workflowService.queryTasks(wfTaskQuery); + + if (wf_invite_tasks.size() == 0) + { + Object objs[] = { invitationId }; + throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); + } + + // end all tasks found with this name + for (WorkflowTask workflowTask : wf_invite_tasks) + { + workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_REJECT); + } + + return invitation; + } + + if (invitation instanceof ModeratedInvitation) + { + WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); + + // Check rejecter is a site manager and throw and exception if not + String rejecterUserName = this.authenticationService.getCurrentUserName(); + checkManagerRole(rejecterUserName, invitation.getResourceType(), invitation.getResourceName()); + + // Current Review Moderated Tasks + wfModeratedTaskQuery.setActive(Boolean.TRUE); + wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); + wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); + wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); + wfModeratedTaskQuery.setProcessId(invitationId); + + // query for invite review tasks + List wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery); + + for (WorkflowTask workflowTask : wf_moderated_tasks) + { + Map wfReviewProps = new HashMap(); + wfReviewProps.put(ContentModel.PROP_OWNER, rejecterUserName); + wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); + workflowService.updateTask(workflowTask.id, wfReviewProps, null, null); + this.workflowService.endTask(workflowTask.id, WorkflowModelModeratedInvitation.WF_TRANSITION_REJECT); + } + + return invitation; + } + + return invitation; + } + + /* + * cancel a pending request + */ + public Invitation cancel(String invitationId) + { + Invitation invitation = getInvitation(invitationId); + + if (invitation instanceof NominatedInvitation) + { + + // Check canceller is a site manager + String approverUserName = this.authenticationService.getCurrentUserName(); + checkManagerRole(approverUserName, invitation.getResourceType(), invitation.getResourceName()); + + // create workflow task query + WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); + + // set the given invite ID as the workflow process ID in the + // workflow query + wfTaskQuery.setProcessId(invitationId); + + // find incomplete invite workflow tasks with given task name + wfTaskQuery.setActive(Boolean.TRUE); + wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); + wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); + + // set process name to "wf:invite" so that only + // invite workflow instances are considered by this query + wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); + + // query for invite workflow tasks with the constructed query + List wf_invite_tasks = workflowService.queryTasks(wfTaskQuery); + + // end all tasks found with this name + for (WorkflowTask workflowTask : wf_invite_tasks) + { + workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_CANCEL); + } + } + + if (invitation instanceof ModeratedInvitation) + { + // Moderated invitation may be cancelled by either a site manager or + // the invitee. + String currentUserName = this.authenticationService.getCurrentUserName(); + + if (!currentUserName.equals(((ModeratedInvitation) invitation).getInviteeUserName())) + { + checkManagerRole(currentUserName, invitation.getResourceType(), invitation.getResourceName()); + } + workflowService.cancelWorkflow(invitationId); + } + + return invitation; + } + + /** + * Get an invitation from its invitation id
+ * Invitations are returned which may be in progress or completed. + * + * @throws InvitationExceptionNotFound the invitation does not exist. + * @throws InvitationExceptionUserError + * @return the invitation. + */ + public Invitation getInvitation(String invitationId) + { + + validateInvitationId(invitationId); + + WorkflowInstance wi = null; + try + { + wi = workflowService.getWorkflowById(invitationId); + } + catch (WorkflowException we) + { + // Do nothing + } + + if (wi == null) + { + Object objs[] = { invitationId }; + throw new InvitationExceptionNotFound("invitation.error.not_found", objs); + } + String workflowName = wi.definition.getName(); + + if (workflowName.equals(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME)) + { + // This is a nominated invitation + WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); + wfTaskQuery.setProcessId(invitationId); + + // filter to find only the start task which contains the properties. + wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); + wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE); + + // query for invite workflow task associate + List inviteStartTasks = workflowService.queryTasks(wfTaskQuery); + + // should also be 0 or 1 + if (inviteStartTasks.size() < 1) + { + Object objs[] = { invitationId }; + throw new InvitationExceptionNotFound("invitation.error.not_found", objs); + } + else + { + WorkflowTask task = inviteStartTasks.get(0); + NominatedInvitationImpl result = new NominatedInvitationImpl(task.properties); + result.setSentInviteDate(task.path.instance.startDate); + result.setInviteId(invitationId); + return result; + } + } + if (workflowName.equals(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME)) + { + // This is a moderated invitation + WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); + wfTaskQuery.setProcessId(invitationId); + + // filter to find only the start task which contains the properties. + wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); + wfTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_START_TASK); + + List inviteStartTasks = workflowService.queryTasks(wfTaskQuery); + + // should also be 0 or 1 + if (inviteStartTasks.size() < 1) + { + // No start task - workflow may have been completed + Object objs[] = { invitationId }; + throw new InvitationExceptionNotFound("invitation.error.not_found", objs); + } + else + { + WorkflowTask task = inviteStartTasks.get(0); + ModeratedInvitationImpl result = new ModeratedInvitationImpl(task.properties); + result.setInviteId(invitationId); + return result; + } + } + + // Unknown workflow type here + return null; + } + + /** + * list Invitations for a specific person/invitee + * + * @param invitee alfresco user id of person being invited + */ + public List listPendingInvitationsForInvitee(String invitee) + { + InvitationSearchCriteriaImpl crit = new InvitationSearchCriteriaImpl(); + crit.setInvitationType(InvitationSearchCriteria.InvitationType.ALL); + crit.setInvitee(invitee); + return searchInvitation(crit); + } + + /** + * list Invitations for a specific resource + * + * @param resourceType + * @param resourceName + */ + public List listPendingInvitationsForResource(Invitation.ResourceType resourceType, String resourceName) + { + InvitationSearchCriteriaImpl crit = new InvitationSearchCriteriaImpl(); + crit.setInvitationType(InvitationSearchCriteria.InvitationType.ALL); + crit.setResourceType(resourceType); + crit.setResourceName(resourceName); + return searchInvitation(crit); + } + + /** + * This is the general search invitation method + * + * @param criteria + * @return the list of invitations + */ + public List searchInvitation(InvitationSearchCriteria criteria) + { + + List ret = new ArrayList(); + + InvitationSearchCriteria.InvitationType toSearch = criteria.getInvitationType(); + + /** + * Nominated search below + */ + if (toSearch == InvitationSearchCriteria.InvitationType.ALL + || toSearch == InvitationSearchCriteria.InvitationType.NOMINATED) + { + // query for nominated workflow tasks by given parameters + WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); + + HashMap wfNominatedQueryProps = new HashMap(10, 1.0f); + + if (criteria.getInviter() != null) + { + wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME, criteria + .getInviter()); + } + if (criteria.getInvitee() != null) + { + wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME, criteria + .getInvitee()); + } + if (criteria.getResourceType() != null) + { + wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE, criteria + .getResourceType().toString()); + } + if (criteria.getResourceName() != null) + { + wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME, criteria + .getResourceName()); + } + + // set workflow task query parameters + wfTaskQuery.setProcessCustomProps(wfNominatedQueryProps); + + // query only active workflows + wfTaskQuery.setActive(Boolean.TRUE); + + // pick up the pending task + wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); + wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); + wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); + + // query for invite workflow tasks + List wf_invite_tasks = this.workflowService.queryTasks(wfTaskQuery); + + for (WorkflowTask workflowTask : wf_invite_tasks) + { + // get workflow instance (ID) that pendingInvite task (in query + // result set) + + String workflowId = workflowTask.path.instance.id; + // TODO ALFCOM-2597 workflowTask.properties does not contain + // custom process values + // NominatedInvitationImpl result = new + // NominatedInvitationImpl(workflowTask.properties); + // result.setInviteId(workflowId); + // ret.add(result); + + Invitation result = getInvitation(workflowId); + + // TODO ALFCOM-2598 records are being returned that do not match + // properties + Set keys = wfNominatedQueryProps.keySet(); + boolean crap = false; + for (QName key : keys) + { + if (key.equals(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME)) + { + Object val1 = wfNominatedQueryProps.get(key); + Object val2 = ((NominatedInvitation) result).getInviteeUserName(); + if (!val1.equals(val2)) + { + // Uh oh ... crap detected + crap = true; + logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); + break; + } + } + if (key.equals(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME)) + { + Object val1 = wfNominatedQueryProps.get(key); + Object val2 = result.getResourceName(); + if (!val1.equals(val2)) + { + // Uh oh ... crap detected + crap = true; + logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); + break; + } + } + if (key.equals(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE)) + { + Object val1 = wfNominatedQueryProps.get(key); + Object val2 = result.getResourceType().toString(); + if (!val1.equals(val2)) + { + + // Uh oh ... crap detected + crap = true; + logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); + break; + } + } + } + + if (!crap) + { + ret.add(result); + } + } + } + + /** + * Moderated search below + */ + if (toSearch == InvitationSearchCriteria.InvitationType.ALL + || toSearch == InvitationSearchCriteria.InvitationType.MODERATED) + { + // This is a moderated search + WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); + // workflow query properties + HashMap wfQueryModeratedProps = new HashMap(3, 1.0f); + + if (criteria.getInvitee() != null) + { + wfQueryModeratedProps.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME, criteria + .getInvitee()); + } + if (criteria.getResourceType() != null) + { + wfQueryModeratedProps.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE, criteria + .getResourceType().toString()); + } + if (criteria.getResourceName() != null) + { + wfQueryModeratedProps.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME, criteria + .getResourceName()); + } + + // set workflow task query parameters + wfModeratedTaskQuery.setProcessCustomProps(wfQueryModeratedProps); + + // Current Review Moderated Tasks + wfModeratedTaskQuery.setActive(Boolean.TRUE); + wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); + wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); + wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); + + // query for invite workflow tasks + List wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery); + + for (WorkflowTask workflowTask : wf_moderated_tasks) + { + // Add moderated invitations + String workflowId = workflowTask.path.instance.id; + ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowTask.properties); + + // TODO ALFCOM-2598 records are being returned that do not match + // properties + Set keys = wfQueryModeratedProps.keySet(); + boolean crap = false; + for (QName key : keys) + { + Object val1 = wfQueryModeratedProps.get(key); + Object val2 = workflowTask.properties.get(key); + if (!val1.equals(val2)) + { + // crap detected + crap = true; + logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); + break; + } + } + // TODO END ALFCOM-2598 Work-around + + result.setInviteId(workflowId); + if (!crap) + { + ret.add(result); + } + } + } + + // End moderated invitation + + return ret; + } + + // Implementation methods below + + /** + * Set the workflow service + * + * @param workflowService + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + /** + * @return the workflow service + */ + public WorkflowService getWorkflowService() + { + return workflowService; + } + + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + public PersonService getPersonService() + { + return personService; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public SiteService getSiteService() + { + return siteService; + } + + public void setAuthenticationService(MutableAuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + public MutableAuthenticationService getAuthenticationService() + { + return authenticationService; + } + + public void setUserNameGenerator(UserNameGenerator usernameGenerator) + { + this.usernameGenerator = usernameGenerator; + } + + public UserNameGenerator getUserNameGenerator() + { + return usernameGenerator; + } + + public void setPasswordGenerator(PasswordGenerator passwordGenerator) + { + this.passwordGenerator = passwordGenerator; + } + + public PasswordGenerator getPasswordGenerator() + { + return passwordGenerator; + } + + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + public NamespaceService getNamespaceService() + { + return namespaceService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public PermissionService getPermissionService() + { + return permissionService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public NodeService getNodeService() + { + return nodeService; + } + + /** + * Creates a person for the invitee with a generated user name. + * + * @param inviteeFirstName first name of invitee + * @param inviteeLastName last name of invitee + * @param inviteeEmail email address of invitee + * @return invitee user name + */ + private String createInviteePerson(String inviteeFirstName, String inviteeLastName, String inviteeEmail) + { + // Attempt to generate user name for invitee + // which does not belong to an existing person + // Tries up to MAX_NUM_INVITEE_USER_NAME_GEN_TRIES + // at which point a web script exception is thrown + String inviteeUserName = null; + int i = 0; + do + { + inviteeUserName = usernameGenerator.generateUserName(inviteeFirstName, inviteeLastName, inviteeEmail, i); + i++; + } while (this.personService.personExists(inviteeUserName) && (i < getMaxUserNameGenRetries())); + + // if after 10 tries is not able to generate a user name for a + // person who doesn't already exist, then throw a web script exception + if (this.personService.personExists(inviteeUserName)) + { + + logger.debug("Failed - unable to generate username for invitee."); + + Object[] objs = { inviteeFirstName, inviteeLastName, inviteeEmail }; + throw new InvitationException("invitation.invite.unable_generate_id", objs); + } + + // create a person node for the invitee with generated invitee user name + // and other provided person property values + final Map properties = new HashMap(); + properties.put(ContentModel.PROP_USERNAME, inviteeUserName); + properties.put(ContentModel.PROP_FIRSTNAME, inviteeFirstName); + properties.put(ContentModel.PROP_LASTNAME, inviteeLastName); + properties.put(ContentModel.PROP_EMAIL, inviteeEmail); + + final String finalUserName = inviteeUserName; + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + NodeRef person = personService.createPerson(properties); + permissionService.setPermission(person, finalUserName, PermissionService.ALL_PERMISSIONS, true); + + return null; + } + + }, AuthenticationUtil.getSystemUserName()); + + return inviteeUserName; + } + + /** + * Creates a disabled user account for the given invitee user name with a + * generated password + * + * @param inviteeUserName + * @return password generated for invitee user account + */ + private String createInviteeDisabledAccount(String inviteeUserName) + { + // generate password using password generator + char[] generatedPassword = passwordGenerator.generatePassword().toCharArray(); + + // create disabled user account for invitee user name with generated + // password this.authenticationService.createAuthentication(inviteeUserName, generatedPassword); this.authenticationService.setAuthenticationEnabled(inviteeUserName, false); - return String.valueOf(generatedPassword); - } + return String.valueOf(generatedPassword); + } - /** - * Moderated invitation implementation - * - * @param inviteeComments - * @param inviteeUserName - * @param resourceType - * @param resourceName - * @param inviteeRole - * @return the new moderated invitation - */ - private ModeratedInvitation startModeratedInvite(String inviteeComments, - String inviteeUserName, Invitation.ResourceType resourceType, - String resourceName, String inviteeRole) - { + /** + * Moderated invitation implementation + * + * @param inviteeComments + * @param inviteeUserName + * @param resourceType + * @param resourceName + * @param inviteeRole + * @return the new moderated invitation + */ + private ModeratedInvitation startModeratedInvite(String inviteeComments, String inviteeUserName, + Invitation.ResourceType resourceType, String resourceName, String inviteeRole) + { - // Get invitee person NodeRef to add as assignee - NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); - - siteService.getSite(resourceName); + // Get invitee person NodeRef to add as assignee + NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); - if (siteService.isMember(resourceName, inviteeUserName)) { - if (logger.isDebugEnabled()) - logger - .debug("Failed - invitee user is already a member of the site."); + siteService.getSite(resourceName); - Object objs[] = { inviteeUserName, "", resourceName }; - throw new InvitationExceptionUserError( - "invitation.invite.already_member", objs); - } - - String roleGroup = siteService.getSiteRoleGroup(resourceName, - SiteModel.SITE_MANAGER); - - NodeRef wfPackage = this.workflowService.createPackage(null); + if (siteService.isMember(resourceName, inviteeUserName)) + { + if (logger.isDebugEnabled()) + logger.debug("Failed - invitee user is already a member of the site."); - Map workflowProps = new HashMap( - 16); - workflowProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); - workflowProps.put(WorkflowModel.ASSOC_ASSIGNEE, inviteeNodeRef); - workflowProps.put( - WorkflowModelModeratedInvitation.ASSOC_GROUP_ASSIGNEE, - roleGroup); - workflowProps.put( - WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS, - inviteeComments); - workflowProps.put( - WorkflowModelModeratedInvitation.WF_PROP_INVITEE_ROLE, - inviteeRole); - workflowProps.put( - WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME, - inviteeUserName); - workflowProps.put( - WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME, - resourceName); - workflowProps.put( - WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE, - resourceType.toString()); + Object objs[] = { inviteeUserName, "", resourceName }; + throw new InvitationExceptionUserError("invitation.invite.already_member", objs); + } - // get the moderated workflow + String roleGroup = siteService.getSiteRoleGroup(resourceName, SiteModel.SITE_MANAGER); - WorkflowDefinition wfDefinition = this.workflowService - .getDefinitionByName(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); - if (wfDefinition == null) { - // handle workflow definition does not exist - Object objs[] = { WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.noworkflow", objs); - } + NodeRef wfPackage = this.workflowService.createPackage(null); - // start the workflow - WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition - .getId(), workflowProps); + Map workflowProps = new HashMap(16); + workflowProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); + workflowProps.put(WorkflowModel.ASSOC_ASSIGNEE, inviteeNodeRef); + workflowProps.put(WorkflowModelModeratedInvitation.ASSOC_GROUP_ASSIGNEE, roleGroup); + workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS, inviteeComments); + workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_ROLE, inviteeRole); + workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME, inviteeUserName); + workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME, resourceName); + workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE, resourceType.toString()); - String workflowId = wfPath.instance.id; - String wfPathId = wfPath.id; - List wfTasks = this.workflowService - .getTasksForWorkflowPath(wfPathId); + // get the moderated workflow - // throw an exception if no tasks where found on the workflow path - if (wfTasks.size() == 0) - { - Object objs[] = { WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.notasks", objs); - } + WorkflowDefinition wfDefinition = this.workflowService + .getDefinitionByName(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); + if (wfDefinition == null) + { + // handle workflow definition does not exist + Object objs[] = { WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME }; + throw new InvitationException("invitation.error.noworkflow", objs); + } - try { - WorkflowTask wfStartTask = wfTasks.get(0); - this.workflowService.endTask(wfStartTask.id, null); - } catch (RuntimeException err) { - if (logger.isDebugEnabled()) - logger.debug("Failed - caught error during Invite workflow transition: " - + err.getMessage()); - throw err; - } + // start the workflow + WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition.getId(), workflowProps); - ModeratedInvitationImpl result = new ModeratedInvitationImpl( - workflowProps); - result.setInviteId(workflowId); - return result; - } + String workflowId = wfPath.instance.id; + String wfPathId = wfPath.id; + List wfTasks = this.workflowService.getTasksForWorkflowPath(wfPathId); - /** - * Starts the Invite workflow - * - * @param inviteeFirstName - * first name of invitee - * @param inviteeLastNamme - * last name of invitee - * @param inviteeEmail - * email address of invitee - * @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 NominatedInvitation startNominatedInvite( - String inviteeFirstName, - String inviteeLastName, - String inviteeEmail, - String inviteeUserName, - Invitation.ResourceType resourceType, - String siteShortName, - String inviteeSiteRole, - String serverPath, - String acceptUrl, - String rejectUrl) { - - // get the inviter user name (the name of user web script is executed - // under) - String inviterUserName = this.authenticationService - .getCurrentUserName(); - - checkManagerRole(inviterUserName, resourceType, siteShortName); + // throw an exception if no tasks where found on the workflow path + if (wfTasks.size() == 0) + { + Object objs[] = { WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME }; + throw new InvitationException("invitation.error.notasks", objs); + } - if (logger.isDebugEnabled()) { - logger.debug("startInvite() inviterUserName=" + inviterUserName - + " inviteeUserName=" + inviteeUserName - + " inviteeFirstName=" + inviteeFirstName - + " inviteeLastName=" + inviteeLastName + " inviteeEmail=" - + inviteeEmail + " siteShortName=" + siteShortName - + " inviteeSiteRole=" + inviteeSiteRole); - } - // - // if we have not explicitly been passed an existing user's user name - // then .... - // - // if a person already exists who has the given invitee email address - // - // 1) obtain invitee user name from first person found having the - // invitee email address, first name and last name - // 2) handle error conditions - - // (invitee already has an invitation in progress for the given site, - // or he/she is already a member of the given site - // - if (inviteeUserName == null || inviteeUserName.trim().length() == 0) { - - inviteeUserName = null; - - Set peopleWithInviteeEmail = this.personService - .getPeopleFilteredByProperty(ContentModel.PROP_EMAIL, - inviteeEmail); - - if (peopleWithInviteeEmail.size() > 0) { - // get person already existing who has the given - // invitee email address - for(NodeRef personRef : peopleWithInviteeEmail) - { - Serializable firstNameVal = this.getNodeService().getProperty(personRef, ContentModel.PROP_FIRSTNAME); - Serializable lastNameVal = this.getNodeService().getProperty(personRef, ContentModel.PROP_LASTNAME); - - String personFirstName = DefaultTypeConverter.INSTANCE.convert( - String.class, firstNameVal); - String personLastName = DefaultTypeConverter.INSTANCE.convert( - String.class, lastNameVal); - - if(personFirstName != null && personFirstName.equalsIgnoreCase(inviteeFirstName)) - { - if(personLastName != null && personLastName.equalsIgnoreCase(inviteeLastName)) - { - // got a match on email, lastname, firstname - // get invitee user name of that person - Serializable userNamePropertyVal = this.getNodeService() - .getProperty(personRef, ContentModel.PROP_USERNAME); - inviteeUserName = DefaultTypeConverter.INSTANCE.convert( - String.class, userNamePropertyVal); + try + { + WorkflowTask wfStartTask = wfTasks.get(0); + this.workflowService.endTask(wfStartTask.id, null); + } + catch (RuntimeException err) + { + if (logger.isDebugEnabled()) + logger.debug("Failed - caught error during Invite workflow transition: " + err.getMessage()); + throw err; + } - if (logger.isDebugEnabled()) - { - logger.debug("not explictly passed username - found matching email, resolved inviteeUserName=" - + inviteeUserName); - } - } - } - } - } - - if(inviteeUserName == null ) - { - // else there are no existing people who have the given invitee - // email address so create new person - inviteeUserName = createInviteePerson(inviteeFirstName, - inviteeLastName, - inviteeEmail); + ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowProps); + result.setInviteId(workflowId); + return result; + } - if (logger.isDebugEnabled()) - { - logger.debug("not explictly passed username - created new person, inviteeUserName=" - + inviteeUserName); - } - } - } - else - { - //TODO MER - Is the code block neccessary - seems to do nothing ? - // inviteeUserName was specified - NodeRef person = this.personService.getPerson(inviteeUserName); - - //TODO - Serializable firstNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_FIRSTNAME); - Serializable lastNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_LASTNAME); - Serializable emailVal = this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL); - firstNameVal = DefaultTypeConverter.INSTANCE.convert( - String.class, firstNameVal); - lastNameVal = DefaultTypeConverter.INSTANCE.convert( - String.class, lastNameVal); - emailVal = DefaultTypeConverter.INSTANCE.convert( - String.class, emailVal); - } + /** + * Starts the Invite workflow + * + * @param inviteeFirstName first name of invitee + * @param inviteeLastNamme last name of invitee + * @param inviteeEmail email address of invitee + * @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 NominatedInvitation startNominatedInvite(String inviteeFirstName, String inviteeLastName, + String inviteeEmail, String inviteeUserName, Invitation.ResourceType resourceType, + String siteShortName, String inviteeSiteRole, String serverPath, String acceptUrl, String rejectUrl) + { - /** - * throw exception if person is already a member of the given site - */ - if (this.siteService.isMember(siteShortName, inviteeUserName)) { - if (logger.isDebugEnabled()) - logger - .debug("Failed - invitee user is already a member of the site."); + // get the inviter user name (the name of user web script is executed + // under) + String inviterUserName = this.authenticationService.getCurrentUserName(); - Object objs[] = { inviteeUserName, inviteeEmail, siteShortName }; - throw new InvitationExceptionUserError( - "invitation.invite.already_member", objs); - } + checkManagerRole(inviterUserName, resourceType, siteShortName); - // - // If a user account does not already exist for invitee user name - // then create a disabled user account for the invitee. - // Hold a local reference to generated password if disabled invitee - // account - // is created, otherwise if a user account already exists for invitee - // user name, then local reference to invitee password will be "null" - // + if (logger.isDebugEnabled()) + { + logger.debug("startInvite() inviterUserName=" + inviterUserName + " inviteeUserName=" + inviteeUserName + + " inviteeFirstName=" + inviteeFirstName + " inviteeLastName=" + inviteeLastName + + " inviteeEmail=" + inviteeEmail + " siteShortName=" + siteShortName + " inviteeSiteRole=" + + inviteeSiteRole); + } + // + // if we have not explicitly been passed an existing user's user name + // then .... + // + // if a person already exists who has the given invitee email address + // + // 1) obtain invitee user name from first person found having the + // invitee email address, first name and last name + // 2) handle error conditions - + // (invitee already has an invitation in progress for the given site, + // or he/she is already a member of the given site + // + if (inviteeUserName == null || inviteeUserName.trim().length() == 0) + { + + inviteeUserName = null; + + Set peopleWithInviteeEmail = this.personService.getPeopleFilteredByProperty( + ContentModel.PROP_EMAIL, inviteeEmail); + + if (peopleWithInviteeEmail.size() > 0) + { + // get person already existing who has the given + // invitee email address + for (NodeRef personRef : peopleWithInviteeEmail) + { + Serializable firstNameVal = this.getNodeService().getProperty(personRef, + ContentModel.PROP_FIRSTNAME); + Serializable lastNameVal = this.getNodeService().getProperty(personRef, ContentModel.PROP_LASTNAME); + + String personFirstName = DefaultTypeConverter.INSTANCE.convert(String.class, firstNameVal); + String personLastName = DefaultTypeConverter.INSTANCE.convert(String.class, lastNameVal); + + if (personFirstName != null && personFirstName.equalsIgnoreCase(inviteeFirstName)) + { + if (personLastName != null && personLastName.equalsIgnoreCase(inviteeLastName)) + { + // got a match on email, lastname, firstname + // get invitee user name of that person + Serializable userNamePropertyVal = this.getNodeService().getProperty(personRef, + ContentModel.PROP_USERNAME); + inviteeUserName = DefaultTypeConverter.INSTANCE.convert(String.class, userNamePropertyVal); + + if (logger.isDebugEnabled()) + { + logger + .debug("not explictly passed username - found matching email, resolved inviteeUserName=" + + inviteeUserName); + } + } + } + } + } + + if (inviteeUserName == null) + { + // else there are no existing people who have the given invitee + // email address so create new person + inviteeUserName = createInviteePerson(inviteeFirstName, inviteeLastName, inviteeEmail); + + if (logger.isDebugEnabled()) + { + logger.debug("not explictly passed username - created new person, inviteeUserName=" + + inviteeUserName); + } + } + } + else + { + // TODO MER - Is the code block neccessary - seems to do nothing ? + // inviteeUserName was specified + NodeRef person = this.personService.getPerson(inviteeUserName); + + // TODO + Serializable firstNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_FIRSTNAME); + Serializable lastNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_LASTNAME); + Serializable emailVal = this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL); + firstNameVal = DefaultTypeConverter.INSTANCE.convert(String.class, firstNameVal); + lastNameVal = DefaultTypeConverter.INSTANCE.convert(String.class, lastNameVal); + emailVal = DefaultTypeConverter.INSTANCE.convert(String.class, emailVal); + } + + /** + * throw exception if person is already a member of the given site + */ + if (this.siteService.isMember(siteShortName, inviteeUserName)) + { + if (logger.isDebugEnabled()) + logger.debug("Failed - invitee user is already a member of the site."); + + Object objs[] = { inviteeUserName, inviteeEmail, siteShortName }; + throw new InvitationExceptionUserError("invitation.invite.already_member", objs); + } + + // + // If a user account does not already exist for invitee user name + // then create a disabled user account for the invitee. + // Hold a local reference to generated password if disabled invitee + // account + // is created, otherwise if a user account already exists for invitee + // user name, then local reference to invitee password will be "null" + // final String initeeUserNameFinal = inviteeUserName; String inviteePassword = AuthenticationUtil.runAs(new RunAsWork() { @@ -1302,24 +1231,25 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli } }, AuthenticationUtil.getSystemUserName()); - // create a ticket for the invite - this is used - String inviteTicket = GUID.generate(); + // create a ticket for the invite - this is used + String inviteTicket = GUID.generate(); - // - // Start the invite workflow with inviter, invitee and site properties - // + // + // Start the invite workflow with inviter, invitee and site properties + // - WorkflowDefinition wfDefinition = this.workflowService - .getDefinitionByName(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); + WorkflowDefinition wfDefinition = this.workflowService + .getDefinitionByName(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); - if (wfDefinition == null) { - // handle workflow definition does not exist - Object objs[] = { WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.noworkflow", objs); - } + if (wfDefinition == null) + { + // handle workflow definition does not exist + Object objs[] = { WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME }; + throw new InvitationException("invitation.error.noworkflow", objs); + } - // Get invitee person NodeRef to add as assignee - NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); + // Get invitee person NodeRef to add as assignee + NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); SiteInfo siteInfo = this.siteService.getSite(siteShortName); String siteDescription = siteInfo.getDescription(); @@ -1331,7 +1261,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli { siteDescription = siteDescription.substring(0, 255); } - // create workflow properties Map workflowProps = new HashMap(16); workflowProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME, inviterUserName); @@ -1351,165 +1280,150 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli workflowProps.put(WorkflowModelNominatedInvitation.WF_PROP_REJECT_URL, rejectUrl); workflowProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITE_TICKET, inviteTicket); - // start the workflow - WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition - .getId(), workflowProps); + // start the workflow + WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition.getId(), workflowProps); - // - // complete invite workflow start task to send out the invite email - // + // + // complete invite workflow start task to send out the invite email + // - // get the workflow tasks - String workflowId = wfPath.instance.id; - String wfPathId = wfPath.id; - List wfTasks = this.workflowService - .getTasksForWorkflowPath(wfPathId); + // get the workflow tasks + String workflowId = wfPath.instance.id; + String wfPathId = wfPath.id; + List wfTasks = this.workflowService.getTasksForWorkflowPath(wfPathId); - // throw an exception if no tasks where found on the workflow path - if (wfTasks.size() == 0) { - Object objs[] = { WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.notasks", objs); - } + // throw an exception if no tasks where found on the workflow path + if (wfTasks.size() == 0) + { + Object objs[] = { WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME }; + throw new InvitationException("invitation.error.notasks", objs); + } - // - // first task in workflow task list (there should only be one) - // associated - // with the workflow path id (above) should be "wf:inviteToSiteTask", - // otherwise - // throw web script exception - // - String wfTaskName = wfTasks.get(0).name; - QName wfTaskNameQName = QName.createQName(wfTaskName, - this.namespaceService); - QName inviteToSiteTaskQName = WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE; - if (!wfTaskNameQName.equals(inviteToSiteTaskQName)) { - Object objs[] = { - wfPathId, - WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE }; - throw new InvitationException("invitation.error.wrong_first_task", - objs); - } + // + // first task in workflow task list (there should only be one) + // associated + // with the workflow path id (above) should be "wf:inviteToSiteTask", + // otherwise + // throw web script exception + // + String wfTaskName = wfTasks.get(0).name; + QName wfTaskNameQName = QName.createQName(wfTaskName, this.namespaceService); + QName inviteToSiteTaskQName = WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE; + if (!wfTaskNameQName.equals(inviteToSiteTaskQName)) + { + Object objs[] = { wfPathId, WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE }; + throw new InvitationException("invitation.error.wrong_first_task", objs); + } - // get "inviteToSite" task - WorkflowTask wfStartTask = wfTasks.get(0); + // get "inviteToSite" task + WorkflowTask wfStartTask = wfTasks.get(0); - // attach empty package to start task, end it and follow with transition - // that sends out the invite - if (logger.isDebugEnabled()) - logger - .debug("Starting Invite workflow task by attaching empty package..."); - NodeRef wfPackage = this.workflowService.createPackage(null); - Map wfTaskProps = new HashMap( - 1, 1.0f); - wfTaskProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); + // attach empty package to start task, end it and follow with transition + // that sends out the invite + if (logger.isDebugEnabled()) + logger.debug("Starting Invite workflow task by attaching empty package..."); + NodeRef wfPackage = this.workflowService.createPackage(null); + Map wfTaskProps = new HashMap(1, 1.0f); + wfTaskProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); + wfTaskProps.put(WorkflowModel.PROP_WORKFLOW_INSTANCE_ID, workflowId); - if (logger.isDebugEnabled()) - logger.debug("Updating Invite workflow task..."); - this.workflowService - .updateTask(wfStartTask.id, wfTaskProps, null, null); + if (logger.isDebugEnabled()) + logger.debug("Updating Invite workflow task..."); + this.workflowService.updateTask(wfStartTask.id, wfTaskProps, null, null); - if (logger.isDebugEnabled()) - logger.debug("Transitioning Invite workflow task..."); - try { - this.workflowService.endTask(wfStartTask.id, - WorkflowModelNominatedInvitation.WF_TRANSITION_SEND_INVITE); - } catch (RuntimeException err) { - if (logger.isDebugEnabled()) - logger - .debug("Failed - caught error during Invite workflow transition: " - + err.getMessage()); - throw err; - } + if (logger.isDebugEnabled()) + logger.debug("Transitioning Invite workflow task..."); + try + { + this.workflowService.endTask(wfStartTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_SEND_INVITE); + } + catch (RuntimeException err) + { + if (logger.isDebugEnabled()) + logger.debug("Failed - caught error during Invite workflow transition: " + err.getMessage()); + throw err; + } - NominatedInvitationImpl result = new NominatedInvitationImpl( - workflowProps); - result.setTicket(inviteTicket); - result.setInviteId(workflowId); - result.setSentInviteDate(new Date()); - return result; - } - - - /** - * Check that the specified user has manager role over the resource. - * @param userId - * @throws InvitationException - */ - private void checkManagerRole(String userId, Invitation.ResourceType resourceType, String siteShortName) - { - // if inviter is not the site manager then throw web script exception - String inviterRole = this.siteService.getMembersRole(siteShortName, - userId); - if ((inviterRole == null) - || (inviterRole.equals(SiteModel.SITE_MANAGER) == false)) { + NominatedInvitationImpl result = new NominatedInvitationImpl(workflowProps); + result.setTicket(inviteTicket); + result.setInviteId(workflowId); + result.setSentInviteDate(new Date()); + return result; + } - Object objs[] = { userId, siteShortName }; - throw new InvitationExceptionForbidden( - "invitation.invite.not_site_manager", objs); - } - } - - /** - * Validator for invitationId - * @param invitationId - */ - private void validateInvitationId(String invitationId) - { - final String ID_SEPERATOR_REGEX = "\\$"; + /** + * Check that the specified user has manager role over the resource. + * + * @param userId + * @throws InvitationException + */ + private void checkManagerRole(String userId, Invitation.ResourceType resourceType, String siteShortName) + { + // if inviter is not the site manager then throw web script exception + String inviterRole = this.siteService.getMembersRole(siteShortName, userId); + if ((inviterRole == null) || (inviterRole.equals(SiteModel.SITE_MANAGER) == false)) + { + + Object objs[] = { userId, siteShortName }; + throw new InvitationExceptionForbidden("invitation.invite.not_site_manager", objs); + } + } + + /** + * Validator for invitationId + * + * @param invitationId + */ + private void validateInvitationId(String invitationId) + { + final String ID_SEPERATOR_REGEX = "\\$"; String[] parts = invitationId.split(ID_SEPERATOR_REGEX); if (parts.length != 2) { - Object objs[] = { invitationId }; - throw new InvitationExceptionUserError("invitation.error.invalid_inviteId_format", objs); + Object objs[] = { invitationId }; + throw new InvitationExceptionUserError("invitation.error.invalid_inviteId_format", objs); } - } + } - /** - * Maximum number of attempts to generate a user name - * @param maxUserNameGenRetries - */ - private void setMaxUserNameGenRetries(int maxUserNameGenRetries) { - this.maxUserNameGenRetries = maxUserNameGenRetries; - } + private int getMaxUserNameGenRetries() + { + return maxUserNameGenRetries; + } - private int getMaxUserNameGenRetries() { - return maxUserNameGenRetries; - } + /** + * NodeServicePolicies.BeforeDeleteNodePolicy Called immediatly prior to + * deletion of a web site. + */ + public void beforeDeleteNode(NodeRef nodeRef) + { + logger.debug("beforeDeleteNode"); - /** - * NodeServicePolicies.BeforeDeleteNodePolicy - * - * Called immediatly prior to deletion of a web site. - */ - public void beforeDeleteNode(NodeRef nodeRef) - { - logger.debug("beforeDeleteNode"); - - final NodeRef siteRef = nodeRef; - - // Run as system user + final NodeRef siteRef = nodeRef; + + // Run as system user AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { public Object doWork() throws Exception { - QName type = nodeService.getType(siteRef); - if(type.equals(SiteModel.TYPE_SITE)) - { - // this is a web site being deleted. - String siteName = (String)nodeService.getProperty(siteRef, ContentModel.PROP_NAME); - if(siteName != null) - { - logger.debug("Invitation service delete node fired " + type + ", " +siteName); - List invitations = listPendingInvitationsForResource(Invitation.ResourceType.WEB_SITE, siteName); - for(Invitation invitation : invitations) - { - logger.debug("cancel workflow " + invitation.getInviteId()); - workflowService.cancelWorkflow(invitation.getInviteId()); - } - } - } - return null; + QName type = nodeService.getType(siteRef); + if (type.equals(SiteModel.TYPE_SITE)) + { + // this is a web site being deleted. + String siteName = (String) nodeService.getProperty(siteRef, ContentModel.PROP_NAME); + if (siteName != null) + { + logger.debug("Invitation service delete node fired " + type + ", " + siteName); + List invitations = listPendingInvitationsForResource( + Invitation.ResourceType.WEB_SITE, siteName); + for (Invitation invitation : invitations) + { + logger.debug("cancel workflow " + invitation.getInviteId()); + workflowService.cancelWorkflow(invitation.getInviteId()); + } + } + } + return null; } }, AuthenticationUtil.SYSTEM_USER_NAME); - } + } } diff --git a/source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java b/source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java index 0e35deb0f4..4f21b52948 100644 --- a/source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java +++ b/source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java @@ -22,6 +22,7 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ + package org.alfresco.repo.invitation; import java.util.Date; @@ -45,95 +46,84 @@ import org.alfresco.util.BaseAlfrescoSpringTest; import org.alfresco.util.PropertyMap; /** - * * Unit tests of Invitation Service - * */ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest { - private SiteService siteService; + private SiteService siteService; private AuthenticationComponent authenticationComponent; private PersonService personService; private InvitationService invitationService; - + private final String SITE_SHORT_NAME_INVITE = "InvitationTest"; private final String SITE_SHORT_NAME_RED = "InvitationTestRed"; private final String SITE_SHORT_NAME_BLUE = "InvitationTestBlue"; public static String PERSON_FIRSTNAME = "InvitationFirstName123"; + public static String PERSON_FIRSTNAME_SPACES = "Invitation First\tName\n1\r2\r\n3"; public static String PERSON_LASTNAME = "InvitationLastName123"; + public static String PERSON_LASTNAME_SPACES = "Invitation Last\tName\n1\r2\r\n3"; public static String PERSON_JOBTITLE = "JobTitle123"; public static String PERSON_ORG = "Organisation123"; - + public static String USER_MANAGER = "InvitationServiceManagerOne"; public static String USER_ONE = "InvitationServiceAlice"; public static String USER_TWO = "InvitationServiceBob"; public static String USER_EVE = "InvitationServiceEve"; - public static String USER_ONE_FIRSTNAME = "One" ; + public static String USER_ONE_FIRSTNAME = "One"; public static String USER_ONE_LASTNAME = "Test"; public static String USER_ONE_EMAIL = USER_ONE + "@alfrescotesting.com"; - - + /** * Called during the transaction setup */ protected void onSetUpInTransaction() throws Exception { super.onSetUpInTransaction(); - this.invitationService = (InvitationService) this.applicationContext.getBean("InvitationService"); this.siteService = (SiteService) this.applicationContext.getBean("SiteService"); this.personService = (PersonService) this.applicationContext.getBean("PersonService"); - this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent"); - - // TODO MER 20/11/2009 Bodge - turn off email sending to prevent errors during unit testing + this.authenticationComponent = (AuthenticationComponent) this.applicationContext + .getBean("authenticationComponent"); + + // TODO MER 20/11/2009 Bodge - turn off email sending to prevent errors + // during unit testing // (or sending out email by accident from tests) - MailActionExecuter mail = (MailActionExecuter)this.applicationContext.getBean("mail"); + MailActionExecuter mail = (MailActionExecuter) this.applicationContext.getBean("mail"); mail.setTestMode(true); - + createPerson(USER_MANAGER, USER_MANAGER + "@alfrescotesting.com", PERSON_FIRSTNAME, PERSON_LASTNAME); - createPerson(USER_ONE, USER_ONE_EMAIL,USER_ONE_FIRSTNAME, USER_ONE_LASTNAME); + createPerson(USER_ONE, USER_ONE_EMAIL, USER_ONE_FIRSTNAME, USER_ONE_LASTNAME); createPerson(USER_TWO, USER_TWO + "@alfrescotesting.com", PERSON_FIRSTNAME, PERSON_LASTNAME); createPerson(USER_EVE, USER_EVE + "@alfrescotesting.com", PERSON_FIRSTNAME, PERSON_LASTNAME); - + this.authenticationComponent.setCurrentUser(USER_MANAGER); - - SiteInfo siteInfo = siteService.getSite(SITE_SHORT_NAME_INVITE); - if (siteInfo == null) - { - siteService.createSite("InviteSitePreset", - SITE_SHORT_NAME_INVITE, - "InviteSiteTitle", - "InviteSiteDescription", - SiteVisibility.MODERATED); - } - - SiteInfo siteInfoRed = siteService.getSite(SITE_SHORT_NAME_RED); - if (siteInfoRed == null) - { - siteService.createSite("InviteSiteRed", - SITE_SHORT_NAME_RED, - "InviteSiteTitle", - "InviteSiteDescription", - SiteVisibility.MODERATED); - } - SiteInfo siteInfoBlue = siteService.getSite(SITE_SHORT_NAME_BLUE); - if (siteInfoBlue == null) - { - siteService.createSite("InviteSiteBlue", - SITE_SHORT_NAME_BLUE, - "InviteSiteTitle", - "InviteSiteDescription", - SiteVisibility.MODERATED); - } - - + + SiteInfo siteInfo = siteService.getSite(SITE_SHORT_NAME_INVITE); + if (siteInfo == null) + { + siteService.createSite("InviteSitePreset", SITE_SHORT_NAME_INVITE, "InviteSiteTitle", + "InviteSiteDescription", SiteVisibility.MODERATED); + } + + SiteInfo siteInfoRed = siteService.getSite(SITE_SHORT_NAME_RED); + if (siteInfoRed == null) + { + siteService.createSite("InviteSiteRed", SITE_SHORT_NAME_RED, "InviteSiteTitle", "InviteSiteDescription", + SiteVisibility.MODERATED); + } + SiteInfo siteInfoBlue = siteService.getSite(SITE_SHORT_NAME_BLUE); + if (siteInfoBlue == null) + { + siteService.createSite("InviteSiteBlue", SITE_SHORT_NAME_BLUE, "InviteSiteTitle", "InviteSiteDescription", + SiteVisibility.MODERATED); + } } - + protected void onTearDownInTransaction() throws Exception { super.onTearDownInTransaction(); - this.authenticationComponent.setSystemUserAsCurrentUser(); + this.authenticationComponent.setSystemUserAsCurrentUser(); siteService.deleteSite(SITE_SHORT_NAME_INVITE); siteService.deleteSite(SITE_SHORT_NAME_RED); siteService.deleteSite(SITE_SHORT_NAME_BLUE); @@ -142,19 +132,19 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest deletePersonByUserName(USER_EVE); deletePersonByUserName(USER_MANAGER); } - - /* - * end of setup now for some real tests + + /* + * end of setup now for some real tests */ - + /** * */ public void testConfiguration() { - assertNotNull("Invitation service is null", invitationService); + assertNotNull("Invitation service is null", invitationService); } - + /** * Test nominated user - new user * @@ -162,826 +152,766 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest */ public void testNominatedInvitationNewUser() throws Exception { - Date startDate = new java.util.Date(); - - String inviteeFirstName = PERSON_FIRSTNAME; - String inviteeLastName = PERSON_LASTNAME; - String inviteeEmail = "123@alfrescotesting.com"; - String inviteeUserName = null; - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String serverPath = "wibble"; - String acceptUrl = "froob"; - String rejectUrl = "marshmallow"; - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - - NominatedInvitation nominatedInvitation = invitationService.inviteNominated( - inviteeFirstName, - inviteeLastName, - inviteeEmail, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - assertNotNull("nominated invitation is null", nominatedInvitation); - String inviteId = nominatedInvitation.getInviteId(); - assertEquals("first name wrong", inviteeFirstName, nominatedInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, nominatedInvitation.getInviteeLastName()); - assertEquals("email name wrong", inviteeEmail, nominatedInvitation.getInviteeEmail()); - - // Generated User Name should be returned - inviteeUserName = nominatedInvitation.getInviteeUserName(); - assertNotNull("generated user name is null", inviteeUserName); - // sentInviteDate should be set to today - { - Date sentDate = nominatedInvitation.getSentInviteDate(); - assertTrue("sentDate wrong - too early", sentDate.after(startDate)); - assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime()+ 1))); - } - - assertEquals("resource type name wrong", resourceType, nominatedInvitation.getResourceType()); - assertEquals("resource name wrong", resourceName, nominatedInvitation.getResourceName()); - assertEquals("role name wrong", inviteeRole, nominatedInvitation.getRoleName()); - assertEquals("server path wrong", serverPath, nominatedInvitation.getServerPath()); - assertEquals("accept URL wrong", acceptUrl, nominatedInvitation.getAcceptUrl()); - assertEquals("reject URL wrong", rejectUrl, nominatedInvitation.getRejectUrl()); - - /** - * Now we have an invitation get it and check the details have been returned correctly. - */ - { - NominatedInvitation invitation = (NominatedInvitation)invitationService.getInvitation(inviteId); - - assertNotNull("invitation is null", invitation); - assertEquals("invite id wrong", inviteId, invitation.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, invitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, invitation.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, invitation.getInviteeUserName()); - assertEquals("resource type name wrong", resourceType, invitation.getResourceType()); - assertEquals("resource name wrong", resourceName, invitation.getResourceName()); - assertEquals("role name wrong", inviteeRole, invitation.getRoleName()); - assertEquals("server path wrong", serverPath, invitation.getServerPath()); - assertEquals("accept URL wrong", acceptUrl, invitation.getAcceptUrl()); - assertEquals("reject URL wrong", rejectUrl, invitation.getRejectUrl()); + Date startDate = new java.util.Date(); - Date sentDate = invitation.getSentInviteDate(); - // sentInviteDate should be set to today - assertTrue("sentDate wrong too early", sentDate.after(startDate)); - assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime()+ 1))); - } - - /** - * Search for the new invitation - */ - List invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is empty", !invitations.isEmpty()); - - NominatedInvitation firstInvite = (NominatedInvitation)invitations.get(0); - assertEquals("invite id wrong", inviteId, firstInvite.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, firstInvite.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, firstInvite.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, firstInvite.getInviteeUserName()); - - /** - * Now accept the invitation - */ - NominatedInvitation acceptedInvitation = (NominatedInvitation)invitationService.accept(firstInvite.getInviteId(), firstInvite.getTicket()); - assertEquals("invite id wrong", firstInvite.getInviteId(), acceptedInvitation.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, acceptedInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, acceptedInvitation.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, acceptedInvitation.getInviteeUserName()); - - List it4 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is not empty", it4.isEmpty()); - - /** - * Now get the invitation that we accepted - */ - NominatedInvitation acceptedInvitation2 = (NominatedInvitation)invitationService.getInvitation(firstInvite.getInviteId()); + String inviteeFirstName = PERSON_FIRSTNAME; + String inviteeLastName = PERSON_LASTNAME; + String inviteeEmail = "123@alfrescotesting.com"; + String inviteeUserName = null; + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; + + this.authenticationComponent.setCurrentUser(USER_MANAGER); + + NominatedInvitation nominatedInvitation = invitationService.inviteNominated(inviteeFirstName, inviteeLastName, + inviteeEmail, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + assertNotNull("nominated invitation is null", nominatedInvitation); + String inviteId = nominatedInvitation.getInviteId(); + assertEquals("first name wrong", inviteeFirstName, nominatedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, nominatedInvitation.getInviteeLastName()); + assertEquals("email name wrong", inviteeEmail, nominatedInvitation.getInviteeEmail()); + + // Generated User Name should be returned + inviteeUserName = nominatedInvitation.getInviteeUserName(); + assertNotNull("generated user name is null", inviteeUserName); + // sentInviteDate should be set to today + { + Date sentDate = nominatedInvitation.getSentInviteDate(); + assertTrue("sentDate wrong - too early", sentDate.after(startDate)); + assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime() + 1))); + } + + assertEquals("resource type name wrong", resourceType, nominatedInvitation.getResourceType()); + assertEquals("resource name wrong", resourceName, nominatedInvitation.getResourceName()); + assertEquals("role name wrong", inviteeRole, nominatedInvitation.getRoleName()); + assertEquals("server path wrong", serverPath, nominatedInvitation.getServerPath()); + assertEquals("accept URL wrong", acceptUrl, nominatedInvitation.getAcceptUrl()); + assertEquals("reject URL wrong", rejectUrl, nominatedInvitation.getRejectUrl()); + + /** + * Now we have an invitation get it and check the details have been + * returned correctly. + */ + { + NominatedInvitation invitation = (NominatedInvitation) invitationService.getInvitation(inviteId); + + assertNotNull("invitation is null", invitation); + assertEquals("invite id wrong", inviteId, invitation.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, invitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, invitation.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, invitation.getInviteeUserName()); + assertEquals("resource type name wrong", resourceType, invitation.getResourceType()); + assertEquals("resource name wrong", resourceName, invitation.getResourceName()); + assertEquals("role name wrong", inviteeRole, invitation.getRoleName()); + assertEquals("server path wrong", serverPath, invitation.getServerPath()); + assertEquals("accept URL wrong", acceptUrl, invitation.getAcceptUrl()); + assertEquals("reject URL wrong", rejectUrl, invitation.getRejectUrl()); + + Date sentDate = invitation.getSentInviteDate(); + // sentInviteDate should be set to today + assertTrue("sentDate wrong too early", sentDate.after(startDate)); + assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime() + 1))); + } + + /** + * Search for the new invitation + */ + List invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is empty", !invitations.isEmpty()); + + NominatedInvitation firstInvite = (NominatedInvitation) invitations.get(0); + assertEquals("invite id wrong", inviteId, firstInvite.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, firstInvite.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, firstInvite.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, firstInvite.getInviteeUserName()); + + /** + * Now accept the invitation + */ + NominatedInvitation acceptedInvitation = (NominatedInvitation) invitationService.accept(firstInvite + .getInviteId(), firstInvite.getTicket()); + assertEquals("invite id wrong", firstInvite.getInviteId(), acceptedInvitation.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, acceptedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, acceptedInvitation.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, acceptedInvitation.getInviteeUserName()); + + List it4 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is not empty", it4.isEmpty()); + + /** + * Now get the invitation that we accepted + */ + NominatedInvitation acceptedInvitation2 = (NominatedInvitation) invitationService.getInvitation(firstInvite + .getInviteId()); assertNotNull("get after accept does not return", acceptedInvitation2); - - /** - * Now verify access control list - */ - String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - assertEquals("role name wrong", roleName, inviteeRole); - siteService.removeMembership(resourceName, inviteeUserName); + + /** + * Now verify access control list + */ + String roleName = siteService.getMembersRole(resourceName, inviteeUserName); + assertEquals("role name wrong", roleName, inviteeRole); + siteService.removeMembership(resourceName, inviteeUserName); } - + // TODO MER START /** * Test nominated user - new user who rejects invitation + * * @throws Exception */ public void testNominatedInvitationNewUserReject() throws Exception { - Date startDate = new java.util.Date(); - - String inviteeFirstName = PERSON_FIRSTNAME; - String inviteeLastName = PERSON_LASTNAME; - String inviteeEmail = "123@alfrescotesting.com"; - String inviteeUserName = null; - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String serverPath = "wibble"; - String acceptUrl = "froob"; - String rejectUrl = "marshmallow"; - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - - NominatedInvitation nominatedInvitation = invitationService.inviteNominated( - inviteeFirstName, - inviteeLastName, - inviteeEmail, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - assertNotNull("nominated invitation is null", nominatedInvitation); - String inviteId = nominatedInvitation.getInviteId(); - assertEquals("first name wrong", inviteeFirstName, nominatedInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, nominatedInvitation.getInviteeLastName()); - assertEquals("email name wrong", inviteeEmail, nominatedInvitation.getInviteeEmail()); - - // Generated User Name should be returned - inviteeUserName = nominatedInvitation.getInviteeUserName(); - assertNotNull("generated user name is null", inviteeUserName); - // sentInviteDate should be set to today - { - Date sentDate = nominatedInvitation.getSentInviteDate(); - assertTrue("sentDate wrong - too early", sentDate.after(startDate)); - assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime()+ 1))); - } - - - /** - * Now reject the invitation - */ - NominatedInvitation rejectedInvitation = (NominatedInvitation)invitationService.reject(nominatedInvitation.getInviteId(), "dont want it"); - assertEquals("invite id wrong", nominatedInvitation.getInviteId(), rejectedInvitation.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, rejectedInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, rejectedInvitation.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, rejectedInvitation.getInviteeUserName()); - - List it4 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is not empty", it4.isEmpty()); - - /** - * Now verify access control list inviteeUserName should not exist - */ - String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - if(roleName != null) - { - fail("role has been set for a rejected user"); - } - - /** - * Now verify that the generated user has been removed - */ - if(personService.personExists(inviteeUserName)) - { - fail("generated user has not been cleaned up"); - } + Date startDate = new java.util.Date(); + + String inviteeFirstName = PERSON_FIRSTNAME; + String inviteeLastName = PERSON_LASTNAME; + String inviteeEmail = "123@alfrescotesting.com"; + String inviteeUserName = null; + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; + + this.authenticationComponent.setCurrentUser(USER_MANAGER); + + NominatedInvitation nominatedInvitation = invitationService.inviteNominated(inviteeFirstName, inviteeLastName, + inviteeEmail, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + assertNotNull("nominated invitation is null", nominatedInvitation); + assertEquals("first name wrong", inviteeFirstName, nominatedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, nominatedInvitation.getInviteeLastName()); + assertEquals("email name wrong", inviteeEmail, nominatedInvitation.getInviteeEmail()); + + // Generated User Name should be returned + inviteeUserName = nominatedInvitation.getInviteeUserName(); + assertNotNull("generated user name is null", inviteeUserName); + // sentInviteDate should be set to today + { + Date sentDate = nominatedInvitation.getSentInviteDate(); + assertTrue("sentDate wrong - too early", sentDate.after(startDate)); + assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime() + 1))); + } + + /** + * Now reject the invitation + */ + NominatedInvitation rejectedInvitation = (NominatedInvitation) invitationService.reject(nominatedInvitation + .getInviteId(), "dont want it"); + assertEquals("invite id wrong", nominatedInvitation.getInviteId(), rejectedInvitation.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, rejectedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, rejectedInvitation.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, rejectedInvitation.getInviteeUserName()); + + List it4 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is not empty", it4.isEmpty()); + + /** + * Now verify access control list inviteeUserName should not exist + */ + String roleName = siteService.getMembersRole(resourceName, inviteeUserName); + if (roleName != null) + { + fail("role has been set for a rejected user"); + } + + /** + * Now verify that the generated user has been removed + */ + if (personService.personExists(inviteeUserName)) + { + fail("generated user has not been cleaned up"); + } } - - - + // TODO MER END - - - + /** - * Test nominated user - new user - * - * Creates two separate users with two the same email address. + * Test nominated user - new user Creates two separate users with two the + * same email address. * * @throws Exception */ public void testNominatedInvitationNewUserSameEmails() throws Exception { - String inviteeAFirstName = "John"; - String inviteeALastName = "Smith"; - - String inviteeBFirstName = "Jane"; - String inviteeBLastName = "Smith"; - - String inviteeEmail = "123@alfrescotesting.com"; - String inviteeAUserName = null; - String inviteeBUserName = null; - - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String serverPath = "wibble"; - String acceptUrl = "froob"; - String rejectUrl = "marshmallow"; - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - - NominatedInvitation nominatedInvitationA = invitationService.inviteNominated( - inviteeAFirstName, - inviteeALastName, - inviteeEmail, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - assertNotNull("nominated invitation is null", nominatedInvitationA); - String inviteAId = nominatedInvitationA.getInviteId(); - assertEquals("first name wrong", inviteeAFirstName, nominatedInvitationA.getInviteeFirstName()); - assertEquals("last name wrong", inviteeALastName, nominatedInvitationA.getInviteeLastName()); - assertEquals("email name wrong", inviteeEmail, nominatedInvitationA.getInviteeEmail()); - - // Generated User Name should be returned - inviteeAUserName = nominatedInvitationA.getInviteeUserName(); - assertNotNull("generated user name is null", inviteeAUserName); - - NominatedInvitation nominatedInvitationB = invitationService.inviteNominated( - inviteeBFirstName, - inviteeBLastName, - inviteeEmail, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - assertNotNull("nominated invitation is null", nominatedInvitationB); - String inviteBId = nominatedInvitationB.getInviteId(); - assertEquals("first name wrong", inviteeBFirstName, nominatedInvitationB.getInviteeFirstName()); - assertEquals("last name wrong", inviteeBLastName, nominatedInvitationB.getInviteeLastName()); - assertEquals("email name wrong", inviteeEmail, nominatedInvitationB.getInviteeEmail()); - - // Generated User Name should be returned - inviteeBUserName = nominatedInvitationB.getInviteeUserName(); - assertNotNull("generated user name is null", inviteeBUserName); - assertFalse("generated user names are the same", inviteeAUserName.equals(inviteeBUserName)); - - /** - * Now accept the invitation - */ - NominatedInvitation acceptedInvitationA = (NominatedInvitation)invitationService.accept(inviteAId, nominatedInvitationA.getTicket()); - assertEquals("invite id wrong", inviteAId, acceptedInvitationA.getInviteId()); - assertEquals("first name wrong", inviteeAFirstName, acceptedInvitationA.getInviteeFirstName()); - assertEquals("last name wrong", inviteeALastName, acceptedInvitationA.getInviteeLastName()); - assertEquals("user name wrong", inviteeAUserName, acceptedInvitationA.getInviteeUserName()); - - NominatedInvitation acceptedInvitationB = (NominatedInvitation)invitationService.accept(inviteBId, nominatedInvitationB.getTicket()); - assertEquals("invite id wrong", inviteBId, acceptedInvitationB.getInviteId()); - assertEquals("first name wrong", inviteeBFirstName, acceptedInvitationB.getInviteeFirstName()); - assertEquals("last name wrong", inviteeBLastName, acceptedInvitationB.getInviteeLastName()); - assertEquals("user name wrong", inviteeBUserName, acceptedInvitationB.getInviteeUserName()); - - - /** - * Now verify access control list - */ - String roleNameA = siteService.getMembersRole(resourceName, inviteeAUserName); - assertEquals("role name wrong", roleNameA, inviteeRole); - String roleNameB = siteService.getMembersRole(resourceName, inviteeBUserName); - assertEquals("role name wrong", roleNameB, inviteeRole); - siteService.removeMembership(resourceName, inviteeAUserName); - siteService.removeMembership(resourceName, inviteeBUserName); + String inviteeAFirstName = "John"; + String inviteeALastName = "Smith"; + + String inviteeBFirstName = "Jane"; + String inviteeBLastName = "Smith"; + + String inviteeEmail = "123@alfrescotesting.com"; + String inviteeAUserName = null; + String inviteeBUserName = null; + + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; + + this.authenticationComponent.setCurrentUser(USER_MANAGER); + + NominatedInvitation nominatedInvitationA = invitationService.inviteNominated(inviteeAFirstName, + inviteeALastName, inviteeEmail, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, + rejectUrl); + + assertNotNull("nominated invitation is null", nominatedInvitationA); + String inviteAId = nominatedInvitationA.getInviteId(); + assertEquals("first name wrong", inviteeAFirstName, nominatedInvitationA.getInviteeFirstName()); + assertEquals("last name wrong", inviteeALastName, nominatedInvitationA.getInviteeLastName()); + assertEquals("email name wrong", inviteeEmail, nominatedInvitationA.getInviteeEmail()); + + // Generated User Name should be returned + inviteeAUserName = nominatedInvitationA.getInviteeUserName(); + assertNotNull("generated user name is null", inviteeAUserName); + + NominatedInvitation nominatedInvitationB = invitationService.inviteNominated(inviteeBFirstName, + inviteeBLastName, inviteeEmail, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, + rejectUrl); + + assertNotNull("nominated invitation is null", nominatedInvitationB); + String inviteBId = nominatedInvitationB.getInviteId(); + assertEquals("first name wrong", inviteeBFirstName, nominatedInvitationB.getInviteeFirstName()); + assertEquals("last name wrong", inviteeBLastName, nominatedInvitationB.getInviteeLastName()); + assertEquals("email name wrong", inviteeEmail, nominatedInvitationB.getInviteeEmail()); + + // Generated User Name should be returned + inviteeBUserName = nominatedInvitationB.getInviteeUserName(); + assertNotNull("generated user name is null", inviteeBUserName); + assertFalse("generated user names are the same", inviteeAUserName.equals(inviteeBUserName)); + + /** + * Now accept the invitation + */ + NominatedInvitation acceptedInvitationA = (NominatedInvitation) invitationService.accept(inviteAId, + nominatedInvitationA.getTicket()); + assertEquals("invite id wrong", inviteAId, acceptedInvitationA.getInviteId()); + assertEquals("first name wrong", inviteeAFirstName, acceptedInvitationA.getInviteeFirstName()); + assertEquals("last name wrong", inviteeALastName, acceptedInvitationA.getInviteeLastName()); + assertEquals("user name wrong", inviteeAUserName, acceptedInvitationA.getInviteeUserName()); + + NominatedInvitation acceptedInvitationB = (NominatedInvitation) invitationService.accept(inviteBId, + nominatedInvitationB.getTicket()); + assertEquals("invite id wrong", inviteBId, acceptedInvitationB.getInviteId()); + assertEquals("first name wrong", inviteeBFirstName, acceptedInvitationB.getInviteeFirstName()); + assertEquals("last name wrong", inviteeBLastName, acceptedInvitationB.getInviteeLastName()); + assertEquals("user name wrong", inviteeBUserName, acceptedInvitationB.getInviteeUserName()); + + /** + * Now verify access control list + */ + String roleNameA = siteService.getMembersRole(resourceName, inviteeAUserName); + assertEquals("role name wrong", roleNameA, inviteeRole); + String roleNameB = siteService.getMembersRole(resourceName, inviteeBUserName); + assertEquals("role name wrong", roleNameB, inviteeRole); + siteService.removeMembership(resourceName, inviteeAUserName); + siteService.removeMembership(resourceName, inviteeBUserName); } - /** - * Create a Nominated Invitation (for existing user, USER_ONE) - * read it. - * search for it - * cancel it - * search for it again (and fail to find it) - * Create a Nominated Invitation - * read it. - * search for it - * reject it - * Create a Nominated Invitation - * read it. - * accept it + * Test nominated user - new user with whitespace in name. Related to + * ETHREEOH-3030. + */ + public void testNominatedInvitationNewUserWhitespace() throws Exception + { + String inviteeFirstName = PERSON_FIRSTNAME_SPACES; + String inviteeLastName = PERSON_LASTNAME_SPACES; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeEmail = "123@alfrescotesting.com"; + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; + String expectedUserName = (inviteeFirstName + "_" + inviteeLastName).toLowerCase(); + + authenticationComponent.setCurrentUser(USER_MANAGER); + + NominatedInvitation nominatedInvitation = invitationService.inviteNominated(inviteeFirstName, inviteeLastName, + inviteeEmail, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + assertNotNull("nominated invitation is null", nominatedInvitation); + assertEquals("Wrong username!", expectedUserName, nominatedInvitation.getInviteeUserName()); + + String inviteId = nominatedInvitation.getInviteId(); + + // Now we have an invitation get it and check the details have been + // returned correctly. + NominatedInvitation invitation = (NominatedInvitation) invitationService.getInvitation(inviteId); + assertNotNull("invitation is null", invitation); + assertEquals("first name wrong", inviteeFirstName, invitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, invitation.getInviteeLastName()); + assertEquals("user name wrong", expectedUserName, invitation.getInviteeUserName()); + + // Now accept the invitation + NominatedInvitation acceptedInvitation = (NominatedInvitation) invitationService.accept(invitation + .getInviteId(), invitation.getTicket()); + + assertEquals("first name wrong", inviteeFirstName, acceptedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, acceptedInvitation.getInviteeLastName()); + assertEquals("user name wrong", expectedUserName, acceptedInvitation.getInviteeUserName()); + + // Now verify access control list + String roleName = siteService.getMembersRole(resourceName, expectedUserName); + assertEquals("role name wrong", roleName, inviteeRole); + siteService.removeMembership(resourceName, expectedUserName); + } + + /** + * Create a Nominated Invitation (for existing user, USER_ONE) read it. + * search for it cancel it search for it again (and fail to find it) Create + * a Nominated Invitation read it. search for it reject it Create a + * Nominated Invitation read it. accept it */ public void testNominatedInvitationExistingUser() throws Exception { - String inviteeUserName = USER_ONE; - String inviteeEmail = USER_ONE_EMAIL; - String inviteeFirstName = USER_ONE_FIRSTNAME; - String inviteeLastName = USER_ONE_LASTNAME; - - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String serverPath = "wibble"; - String acceptUrl = "froob"; - String rejectUrl = "marshmallow"; - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - - NominatedInvitation nominatedInvitation = invitationService.inviteNominated( - inviteeUserName, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - assertNotNull("nominated invitation is null", nominatedInvitation); - String inviteId = nominatedInvitation.getInviteId(); - assertEquals("user name wrong", inviteeUserName, nominatedInvitation.getInviteeUserName()); - assertEquals("resource type name wrong", resourceType, nominatedInvitation.getResourceType()); - assertEquals("resource name wrong", resourceName, nominatedInvitation.getResourceName()); - assertEquals("role name wrong", inviteeRole, nominatedInvitation.getRoleName()); - assertEquals("server path wrong", serverPath, nominatedInvitation.getServerPath()); - assertEquals("accept URL wrong", acceptUrl, nominatedInvitation.getAcceptUrl()); - assertEquals("reject URL wrong", rejectUrl, nominatedInvitation.getRejectUrl()); - - // These values should be read from the person record - assertEquals("first name wrong", inviteeFirstName, nominatedInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, nominatedInvitation.getInviteeLastName()); - assertEquals("email name wrong", inviteeEmail, nominatedInvitation.getInviteeEmail()); - - /** - * Now we have an invitation get it and check the details have been returned correctly. - */ - NominatedInvitation invitation = (NominatedInvitation)invitationService.getInvitation(inviteId); - - assertNotNull("invitation is null", invitation); - assertEquals("invite id wrong", inviteId, invitation.getInviteId()); - assertEquals("user name wrong", inviteeUserName, nominatedInvitation.getInviteeUserName()); - assertEquals("resource type name wrong", resourceType, invitation.getResourceType()); - assertEquals("resource name wrong", resourceName, invitation.getResourceName()); - assertEquals("role name wrong", inviteeRole, invitation.getRoleName()); - assertEquals("server path wrong", serverPath, invitation.getServerPath()); - assertEquals("accept URL wrong", acceptUrl, invitation.getAcceptUrl()); - assertEquals("reject URL wrong", rejectUrl, invitation.getRejectUrl()); - - // These values should have been read from the DB - assertEquals("first name wrong", inviteeFirstName, invitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, invitation.getInviteeLastName()); - assertEquals("email name wrong", inviteeEmail, invitation.getInviteeEmail()); + String inviteeUserName = USER_ONE; + String inviteeEmail = USER_ONE_EMAIL; + String inviteeFirstName = USER_ONE_FIRSTNAME; + String inviteeLastName = USER_ONE_LASTNAME; - /** - * Search for the new invitation - */ - List invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is empty", !invitations.isEmpty()); - - NominatedInvitation firstInvite = (NominatedInvitation)invitations.get(0); - assertEquals("invite id wrong", inviteId, firstInvite.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, firstInvite.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, firstInvite.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, firstInvite.getInviteeUserName()); - - /** - * Now cancel the invitation - */ - NominatedInvitation canceledInvitation = (NominatedInvitation)invitationService.cancel(inviteId); - assertEquals("invite id wrong", inviteId, canceledInvitation.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, canceledInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, canceledInvitation.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, canceledInvitation.getInviteeUserName()); - - /** - * Do the query again - should no longer find anything - */ - List it2 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is not empty", it2.isEmpty()); - - /** - * Now invite and reject - */ - NominatedInvitation secondInvite = invitationService.inviteNominated( - inviteeUserName, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - NominatedInvitation rejectedInvitation = (NominatedInvitation)invitationService.cancel(secondInvite.getInviteId()); - assertEquals("invite id wrong", secondInvite.getInviteId(), rejectedInvitation.getInviteId()); - assertEquals("user name wrong", inviteeUserName, rejectedInvitation.getInviteeUserName()); - - List it3 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is not empty", it3.isEmpty()); - - /** - * Now invite and accept - */ - NominatedInvitation thirdInvite = invitationService.inviteNominated( - inviteeUserName, - resourceType, - resourceName, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - - NominatedInvitation acceptedInvitation = (NominatedInvitation)invitationService.accept(thirdInvite.getInviteId(), thirdInvite.getTicket()); - assertEquals("invite id wrong", thirdInvite.getInviteId(), acceptedInvitation.getInviteId()); - assertEquals("first name wrong", inviteeFirstName, acceptedInvitation.getInviteeFirstName()); - assertEquals("last name wrong", inviteeLastName, acceptedInvitation.getInviteeLastName()); - assertEquals("user name wrong", inviteeUserName, acceptedInvitation.getInviteeUserName()); - - List it4 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is not empty", it4.isEmpty()); - - /** - * Now verify access control list - */ - String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - assertEquals("role name wrong", roleName, inviteeRole); - siteService.removeMembership(resourceName, inviteeUserName); + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; + + this.authenticationComponent.setCurrentUser(USER_MANAGER); + + NominatedInvitation nominatedInvitation = invitationService.inviteNominated(inviteeUserName, resourceType, + resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + assertNotNull("nominated invitation is null", nominatedInvitation); + String inviteId = nominatedInvitation.getInviteId(); + assertEquals("user name wrong", inviteeUserName, nominatedInvitation.getInviteeUserName()); + assertEquals("resource type name wrong", resourceType, nominatedInvitation.getResourceType()); + assertEquals("resource name wrong", resourceName, nominatedInvitation.getResourceName()); + assertEquals("role name wrong", inviteeRole, nominatedInvitation.getRoleName()); + assertEquals("server path wrong", serverPath, nominatedInvitation.getServerPath()); + assertEquals("accept URL wrong", acceptUrl, nominatedInvitation.getAcceptUrl()); + assertEquals("reject URL wrong", rejectUrl, nominatedInvitation.getRejectUrl()); + + // These values should be read from the person record + assertEquals("first name wrong", inviteeFirstName, nominatedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, nominatedInvitation.getInviteeLastName()); + assertEquals("email name wrong", inviteeEmail, nominatedInvitation.getInviteeEmail()); + + /** + * Now we have an invitation get it and check the details have been + * returned correctly. + */ + NominatedInvitation invitation = (NominatedInvitation) invitationService.getInvitation(inviteId); + + assertNotNull("invitation is null", invitation); + assertEquals("invite id wrong", inviteId, invitation.getInviteId()); + assertEquals("user name wrong", inviteeUserName, nominatedInvitation.getInviteeUserName()); + assertEquals("resource type name wrong", resourceType, invitation.getResourceType()); + assertEquals("resource name wrong", resourceName, invitation.getResourceName()); + assertEquals("role name wrong", inviteeRole, invitation.getRoleName()); + assertEquals("server path wrong", serverPath, invitation.getServerPath()); + assertEquals("accept URL wrong", acceptUrl, invitation.getAcceptUrl()); + assertEquals("reject URL wrong", rejectUrl, invitation.getRejectUrl()); + + // These values should have been read from the DB + assertEquals("first name wrong", inviteeFirstName, invitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, invitation.getInviteeLastName()); + assertEquals("email name wrong", inviteeEmail, invitation.getInviteeEmail()); + + /** + * Search for the new invitation + */ + List invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is empty", !invitations.isEmpty()); + + NominatedInvitation firstInvite = (NominatedInvitation) invitations.get(0); + assertEquals("invite id wrong", inviteId, firstInvite.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, firstInvite.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, firstInvite.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, firstInvite.getInviteeUserName()); + + /** + * Now cancel the invitation + */ + NominatedInvitation canceledInvitation = (NominatedInvitation) invitationService.cancel(inviteId); + assertEquals("invite id wrong", inviteId, canceledInvitation.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, canceledInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, canceledInvitation.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, canceledInvitation.getInviteeUserName()); + + /** + * Do the query again - should no longer find anything + */ + List it2 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is not empty", it2.isEmpty()); + + /** + * Now invite and reject + */ + NominatedInvitation secondInvite = invitationService.inviteNominated(inviteeUserName, resourceType, + resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + NominatedInvitation rejectedInvitation = (NominatedInvitation) invitationService.cancel(secondInvite + .getInviteId()); + assertEquals("invite id wrong", secondInvite.getInviteId(), rejectedInvitation.getInviteId()); + assertEquals("user name wrong", inviteeUserName, rejectedInvitation.getInviteeUserName()); + + List it3 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is not empty", it3.isEmpty()); + + /** + * Now invite and accept + */ + NominatedInvitation thirdInvite = invitationService.inviteNominated(inviteeUserName, resourceType, + resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + NominatedInvitation acceptedInvitation = (NominatedInvitation) invitationService.accept(thirdInvite + .getInviteId(), thirdInvite.getTicket()); + assertEquals("invite id wrong", thirdInvite.getInviteId(), acceptedInvitation.getInviteId()); + assertEquals("first name wrong", inviteeFirstName, acceptedInvitation.getInviteeFirstName()); + assertEquals("last name wrong", inviteeLastName, acceptedInvitation.getInviteeLastName()); + assertEquals("user name wrong", inviteeUserName, acceptedInvitation.getInviteeUserName()); + + List it4 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is not empty", it4.isEmpty()); + + /** + * Now verify access control list + */ + String roleName = siteService.getMembersRole(resourceName, inviteeUserName); + assertEquals("role name wrong", roleName, inviteeRole); + siteService.removeMembership(resourceName, inviteeUserName); } - + /** - * Create a moderated invitation - * Get it - * Search for it - * Cancel it - * - * Create a moderated invitation - * Reject the invitation - * - * Create a moderated invitation + * Create a moderated invitation Get it Search for it Cancel it Create a + * moderated invitation Reject the invitation Create a moderated invitation * Approve the invitation */ public void testModeratedInvitation() { - String inviteeUserName = USER_TWO; - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String comments = "please sir, let me in!"; - - this.authenticationComponent.setCurrentUser(USER_TWO); - ModeratedInvitation invitation = invitationService.inviteModerated(comments, - inviteeUserName, - resourceType, - resourceName, - inviteeRole); - - assertNotNull("moderated invitation is null", invitation); - String inviteId = invitation.getInviteId(); - assertEquals("user name wrong", inviteeUserName, invitation.getInviteeUserName()); - assertEquals("role name wrong", inviteeRole, invitation.getRoleName()); - assertEquals("comments", comments, invitation.getInviteeComments()); - assertEquals("resource type name wrong", resourceType, invitation.getResourceType()); - assertEquals("resource name wrong", resourceName, invitation.getResourceName()); - - /** - * Now we have an invitation get it and check the details have been returned correctly. - */ - ModeratedInvitation mi2 = (ModeratedInvitation)invitationService.getInvitation(inviteId); - assertEquals("invite id", inviteId, mi2.getInviteId()); - assertEquals("user name wrong", inviteeUserName, mi2.getInviteeUserName()); - assertEquals("role name wrong", inviteeRole, mi2.getRoleName()); - assertEquals("comments", comments, mi2.getInviteeComments()); - assertEquals("resource type name wrong", resourceType, mi2.getResourceType()); - assertEquals("resource name wrong", resourceName, mi2.getResourceName()); - - /** - * Search for the new invitation - */ - List invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("invitations is empty", !invitations.isEmpty()); - - ModeratedInvitation firstInvite = (ModeratedInvitation)invitations.get(0); - assertEquals("invite id wrong", inviteId, firstInvite.getInviteId()); - - /** - * Cancel the invitation - */ - ModeratedInvitation canceledInvitation = (ModeratedInvitation)invitationService.cancel(inviteId); - assertEquals("invite id wrong", inviteId, canceledInvitation.getInviteId()); - assertEquals("comments wrong", comments, canceledInvitation.getInviteeComments()); - - /** - * Should now be no invitation - */ - List inv2 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); - assertTrue("After cancel invitations is not empty", inv2.isEmpty()); + String inviteeUserName = USER_TWO; + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String comments = "please sir, let me in!"; - /** - * New invitation - */ - this.authenticationComponent.setCurrentUser(USER_TWO); - ModeratedInvitation invite2 = invitationService.inviteModerated(comments, - inviteeUserName, - resourceType, - resourceName, - inviteeRole); - - String secondInvite = invite2.getInviteId(); - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - invitationService.reject(secondInvite, "This is a test reject"); - - /** - * New invitation - */ - this.authenticationComponent.setCurrentUser(USER_TWO); - ModeratedInvitation invite3 = invitationService.inviteModerated(comments, - inviteeUserName, - resourceType, - resourceName, - inviteeRole); - - String thirdInvite = invite3.getInviteId(); - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - invitationService.approve(thirdInvite, "Welcome in"); - - /** - * Now verify access control list - */ - String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - assertEquals("role name wrong", roleName, inviteeRole); - siteService.removeMembership(resourceName, inviteeUserName); + this.authenticationComponent.setCurrentUser(USER_TWO); + ModeratedInvitation invitation = invitationService.inviteModerated(comments, inviteeUserName, resourceType, + resourceName, inviteeRole); + + assertNotNull("moderated invitation is null", invitation); + String inviteId = invitation.getInviteId(); + assertEquals("user name wrong", inviteeUserName, invitation.getInviteeUserName()); + assertEquals("role name wrong", inviteeRole, invitation.getRoleName()); + assertEquals("comments", comments, invitation.getInviteeComments()); + assertEquals("resource type name wrong", resourceType, invitation.getResourceType()); + assertEquals("resource name wrong", resourceName, invitation.getResourceName()); + + /** + * Now we have an invitation get it and check the details have been + * returned correctly. + */ + ModeratedInvitation mi2 = (ModeratedInvitation) invitationService.getInvitation(inviteId); + assertEquals("invite id", inviteId, mi2.getInviteId()); + assertEquals("user name wrong", inviteeUserName, mi2.getInviteeUserName()); + assertEquals("role name wrong", inviteeRole, mi2.getRoleName()); + assertEquals("comments", comments, mi2.getInviteeComments()); + assertEquals("resource type name wrong", resourceType, mi2.getResourceType()); + assertEquals("resource name wrong", resourceName, mi2.getResourceName()); + + /** + * Search for the new invitation + */ + List invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("invitations is empty", !invitations.isEmpty()); + + ModeratedInvitation firstInvite = (ModeratedInvitation) invitations.get(0); + assertEquals("invite id wrong", inviteId, firstInvite.getInviteId()); + + /** + * Cancel the invitation + */ + ModeratedInvitation canceledInvitation = (ModeratedInvitation) invitationService.cancel(inviteId); + assertEquals("invite id wrong", inviteId, canceledInvitation.getInviteId()); + assertEquals("comments wrong", comments, canceledInvitation.getInviteeComments()); + + /** + * Should now be no invitation + */ + List inv2 = invitationService.listPendingInvitationsForResource(resourceType, resourceName); + assertTrue("After cancel invitations is not empty", inv2.isEmpty()); + + /** + * New invitation + */ + this.authenticationComponent.setCurrentUser(USER_TWO); + ModeratedInvitation invite2 = invitationService.inviteModerated(comments, inviteeUserName, resourceType, + resourceName, inviteeRole); + + String secondInvite = invite2.getInviteId(); + + this.authenticationComponent.setCurrentUser(USER_MANAGER); + invitationService.reject(secondInvite, "This is a test reject"); + + /** + * New invitation + */ + this.authenticationComponent.setCurrentUser(USER_TWO); + ModeratedInvitation invite3 = invitationService.inviteModerated(comments, inviteeUserName, resourceType, + resourceName, inviteeRole); + + String thirdInvite = invite3.getInviteId(); + + this.authenticationComponent.setCurrentUser(USER_MANAGER); + invitationService.approve(thirdInvite, "Welcome in"); + + /** + * Now verify access control list + */ + String roleName = siteService.getMembersRole(resourceName, inviteeUserName); + assertEquals("role name wrong", roleName, inviteeRole); + siteService.removeMembership(resourceName, inviteeUserName); } - + /** * Test the approval of a moderated invitation */ public void testModeratedApprove() { - String inviteeUserName = USER_TWO; - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String comments = "please sir, let me in!"; - - /** - * New invitation from User TWO - */ - this.authenticationComponent.setCurrentUser(USER_TWO); - ModeratedInvitation invitation = invitationService.inviteModerated(comments, - inviteeUserName, - resourceType, - resourceName, - inviteeRole); - - String invitationId = invitation.getInviteId(); - - /** - * Negative test - * Attempt to approve without the necessary role - */ - try - { - invitationService.approve(invitationId, "No Way Hosea!"); - assertTrue("excetion not thrown", false); - - } - catch (Exception e) - { - // An exception should have been thrown - e.printStackTrace(); - System.out.println(e.toString()); - } - - /** - * Approve the invitation - */ - this.authenticationComponent.setCurrentUser(USER_MANAGER); - invitationService.approve(invitationId, "Come on in"); - - /** - * Now verify access control list contains user two - */ - String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - assertEquals("role name wrong", roleName, inviteeRole); - - /** - * Negative test - * attempt to approve an invitation that has aready been approved - */ - try - { - invitationService.approve(invitationId, "Have I not already done this?"); - assertTrue("duplicate approve excetion not thrown", false); - } - catch (Exception e) - { - // An exception should have been thrown - e.printStackTrace(); - System.out.println(e.toString()); - } - /** - * Negative test - * User is already a member of the site - */ - siteService.removeMembership(resourceName, inviteeUserName); + String inviteeUserName = USER_TWO; + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String comments = "please sir, let me in!"; + + /** + * New invitation from User TWO + */ + this.authenticationComponent.setCurrentUser(USER_TWO); + ModeratedInvitation invitation = invitationService.inviteModerated(comments, inviteeUserName, resourceType, + resourceName, inviteeRole); + + String invitationId = invitation.getInviteId(); + + /** + * Negative test Attempt to approve without the necessary role + */ + try + { + invitationService.approve(invitationId, "No Way Hosea!"); + assertTrue("excetion not thrown", false); + + } + catch (Exception e) + { + // An exception should have been thrown + e.printStackTrace(); + System.out.println(e.toString()); + } + + /** + * Approve the invitation + */ + this.authenticationComponent.setCurrentUser(USER_MANAGER); + invitationService.approve(invitationId, "Come on in"); + + /** + * Now verify access control list contains user two + */ + String roleName = siteService.getMembersRole(resourceName, inviteeUserName); + assertEquals("role name wrong", roleName, inviteeRole); + + /** + * Negative test attempt to approve an invitation that has aready been + * approved + */ + try + { + invitationService.approve(invitationId, "Have I not already done this?"); + assertTrue("duplicate approve excetion not thrown", false); + } + catch (Exception e) + { + // An exception should have been thrown + e.printStackTrace(); + System.out.println(e.toString()); + } + /** + * Negative test User is already a member of the site + */ + siteService.removeMembership(resourceName, inviteeUserName); } - + /** - * Tests of Moderated Reject + * Tests of Moderated Reject */ public void testModeratedReject() { - String inviteeUserName = USER_TWO; - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String resourceName = SITE_SHORT_NAME_INVITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String comments = "please sir, let me in!"; - - /** - * New invitation from User TWO - */ - this.authenticationComponent.setCurrentUser(USER_TWO); - ModeratedInvitation invitation = invitationService.inviteModerated(comments, - inviteeUserName, - resourceType, - resourceName, - inviteeRole); - - String invitationId = invitation.getInviteId(); - - /** - * Negative test - * Attempt to reject without the necessary role - */ - try - { - invitationService.reject(invitationId, "No Way Hosea!"); - assertTrue("excetion not thrown", false); - - } - catch (Exception e) - { - // An exception should have been thrown - e.printStackTrace(); - System.out.println(e.toString()); - } - - /** - * Reject the invitation - */ - this.authenticationComponent.setCurrentUser(USER_MANAGER); - invitationService.reject(invitationId, "Go away!"); - - /** - * Negative test - * attempt to approve an invitation that has been rejected - */ - try - { - invitationService.approve(invitationId, "Have I not rejected this?"); - assertTrue("rejected invitation not working", false); - } - catch (Exception e) - { - // An exception should have been thrown - e.printStackTrace(); - System.out.println(e.toString()); - } + String inviteeUserName = USER_TWO; + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String comments = "please sir, let me in!"; + + /** + * New invitation from User TWO + */ + this.authenticationComponent.setCurrentUser(USER_TWO); + ModeratedInvitation invitation = invitationService.inviteModerated(comments, inviteeUserName, resourceType, + resourceName, inviteeRole); + + String invitationId = invitation.getInviteId(); + + /** + * Negative test Attempt to reject without the necessary role + */ + try + { + invitationService.reject(invitationId, "No Way Hosea!"); + assertTrue("excetion not thrown", false); + + } + catch (Exception e) + { + // An exception should have been thrown + e.printStackTrace(); + System.out.println(e.toString()); + } + + /** + * Reject the invitation + */ + this.authenticationComponent.setCurrentUser(USER_MANAGER); + invitationService.reject(invitationId, "Go away!"); + + /** + * Negative test attempt to approve an invitation that has been rejected + */ + try + { + invitationService.approve(invitationId, "Have I not rejected this?"); + assertTrue("rejected invitation not working", false); + } + catch (Exception e) + { + // An exception should have been thrown + e.printStackTrace(); + System.out.println(e.toString()); + } } - + /** * Test search invitation */ public void testSearchInvitation() { - /** - * Make up a tree of invitations and then search - * - * Resource, User, Workflow - * 1) RED, One, Moderated - * 2) RED, One, Nominated - * 3) BLUE, One, Nominated - * 4) RED, Two, Moderated - * - */ - Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; - String inviteeRole = SiteModel.SITE_COLLABORATOR; - String comments = "please sir, let me in!"; - String serverPath = "wibble"; - String acceptUrl = "froob"; - String rejectUrl = "marshmallow"; - - this.authenticationComponent.setCurrentUser(USER_MANAGER); - ModeratedInvitation invitationOne = invitationService.inviteModerated(comments, - USER_ONE, - resourceType, - SITE_SHORT_NAME_RED, - inviteeRole); - - String oneId = invitationOne.getInviteId(); - NominatedInvitation invitationTwo = invitationService.inviteNominated( - USER_ONE, - resourceType, - SITE_SHORT_NAME_RED, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - String twoId = invitationTwo.getInviteId(); - - NominatedInvitation invitationThree = invitationService.inviteNominated( - USER_ONE, - resourceType, - SITE_SHORT_NAME_BLUE, - inviteeRole, - serverPath, - acceptUrl, - rejectUrl) ; - String threeId = invitationThree.getInviteId(); - - ModeratedInvitation invitationFour = invitationService.inviteModerated(comments, - USER_TWO, - resourceType, - SITE_SHORT_NAME_RED, - inviteeRole); - String fourId = invitationFour.getInviteId(); - - /** - * Search for invitations for BLUE - */ - List resOne = invitationService.listPendingInvitationsForResource(ResourceType.WEB_SITE, SITE_SHORT_NAME_BLUE); - assertEquals("blue invites not 1", 1, resOne.size()); - assertEquals("blue id wrong", threeId, resOne.get(0).getInviteId()); - - /** - * Search for invitations for RED - */ - List resTwo = invitationService.listPendingInvitationsForResource(ResourceType.WEB_SITE, SITE_SHORT_NAME_RED); - assertEquals("red invites not 3", 3, resTwo.size()); - - /** - * Search for invitations for USER_ONE - */ - List resThree = invitationService.listPendingInvitationsForInvitee(USER_ONE); - assertEquals("user one does not have 3 invitations", 3, resThree.size()); - - /** - * Search for invitations for USER_TWO - */ - List resFour = invitationService.listPendingInvitationsForInvitee(USER_TWO); - assertEquals("user two does not have 1 invitations", 1, resFour.size()); + /** + * Make up a tree of invitations and then search Resource, User, + * Workflow 1) RED, One, Moderated 2) RED, One, Nominated 3) BLUE, One, + * Nominated 4) RED, Two, Moderated + */ + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String comments = "please sir, let me in!"; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; - /** - * Search for user1's nominated invitations - */ - InvitationSearchCriteriaImpl crit1 = new InvitationSearchCriteriaImpl(); - crit1.setInvitee(USER_ONE); - crit1.setInvitationType(InvitationSearchCriteria.InvitationType.NOMINATED); + this.authenticationComponent.setCurrentUser(USER_MANAGER); + invitationService.inviteModerated(comments, USER_ONE, resourceType, SITE_SHORT_NAME_RED, inviteeRole); - List resFive = invitationService.searchInvitation(crit1); - assertEquals("user one does not have 2 nominated", 2, resFive.size()); + invitationService.inviteNominated(USER_ONE, resourceType, SITE_SHORT_NAME_RED, inviteeRole, serverPath, + acceptUrl, rejectUrl); + + NominatedInvitation invitationThree = invitationService.inviteNominated(USER_ONE, resourceType, + SITE_SHORT_NAME_BLUE, inviteeRole, serverPath, acceptUrl, rejectUrl); + String threeId = invitationThree.getInviteId(); + + invitationService.inviteModerated(comments, USER_TWO, resourceType, SITE_SHORT_NAME_RED, inviteeRole); + + /** + * Search for invitations for BLUE + */ + List resOne = invitationService.listPendingInvitationsForResource(ResourceType.WEB_SITE, + SITE_SHORT_NAME_BLUE); + assertEquals("blue invites not 1", 1, resOne.size()); + assertEquals("blue id wrong", threeId, resOne.get(0).getInviteId()); + + /** + * Search for invitations for RED + */ + List resTwo = invitationService.listPendingInvitationsForResource(ResourceType.WEB_SITE, + SITE_SHORT_NAME_RED); + assertEquals("red invites not 3", 3, resTwo.size()); + + /** + * Search for invitations for USER_ONE + */ + List resThree = invitationService.listPendingInvitationsForInvitee(USER_ONE); + assertEquals("user one does not have 3 invitations", 3, resThree.size()); + + /** + * Search for invitations for USER_TWO + */ + List resFour = invitationService.listPendingInvitationsForInvitee(USER_TWO); + assertEquals("user two does not have 1 invitations", 1, resFour.size()); + + /** + * Search for user1's nominated invitations + */ + InvitationSearchCriteriaImpl crit1 = new InvitationSearchCriteriaImpl(); + crit1.setInvitee(USER_ONE); + crit1.setInvitationType(InvitationSearchCriteria.InvitationType.NOMINATED); + + List resFive = invitationService.searchInvitation(crit1); + assertEquals("user one does not have 2 nominated", 2, resFive.size()); + + /** + * Search with an empty criteria - should find all open invitations + */ + InvitationSearchCriteria crit2 = new InvitationSearchCriteriaImpl(); + + invitationService.searchInvitation(crit2); + assertTrue("search everything returned 0 elements", resFive.size() > 0); - - /** - * Search with an empty criteria - should find all open invitations - */ - InvitationSearchCriteria crit2 = new InvitationSearchCriteriaImpl(); - - List resSix = invitationService.searchInvitation(crit2); - assertTrue("search everything returned 0 elements", resFive.size() > 0); - } - - + /** * */ public void testGetInvitation() { - try - { - /** - * Get an invitation that does not exist. - */ - invitationService.getInvitation("jbpm$99999999"); - fail("should have thrown an exception"); - } - catch (Exception e) - { - // should have gone here - } + try + { + /** + * Get an invitation that does not exist. + */ + invitationService.getInvitation("jbpm$99999999"); + fail("should have thrown an exception"); + } + catch (Exception e) + { + // should have gone here + } } - + private void createPerson(String userName, String emailAddress, String firstName, String lastName) { // if user with given user name doesn't already exist then create user if (this.authenticationService.authenticationExists(userName) == false) { // create user - this.authenticationService.createAuthentication(userName, - "password".toCharArray()); + this.authenticationService.createAuthentication(userName, "password".toCharArray()); } // if person node with given user name doesn't already exist then create @@ -1003,7 +933,7 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest } private void deletePersonByUserName(String userName) - { + { // delete person node associated with given user name // if one exists if (this.personService.personExists(userName)) diff --git a/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java b/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java index 900137f86d..bb0e8945e9 100644 --- a/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java +++ b/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java @@ -40,13 +40,13 @@ public interface WorkflowModelNominatedInvitation // workflow definition name public static final String WORKFLOW_DEFINITION_NAME = "jbpm$inwf:invitation-nominated"; - + // tasks public static final QName WF_INVITE_TASK_INVITE_TO_SITE = QName.createQName(NAMESPACE_URI, "inviteToSiteTask"); public static final QName WF_INVITE_TASK_INVITE_PENDING = QName.createQName(NAMESPACE_URI, "invitePendingTask"); public static final QName WF_TASK_ACCEPT_INVITE = QName.createQName(NAMESPACE_URI, "acceptInviteTask"); public static final QName WF_TASK_REJECT_INVITE = QName.createQName(NAMESPACE_URI, "rejectInviteTask"); - + // transition names public static final String WF_TRANSITION_SEND_INVITE = "sendInvite"; public static final String WF_TRANSITION_ACCEPT = "accept"; @@ -54,7 +54,7 @@ public interface WorkflowModelNominatedInvitation public static final String WF_TRANSITION_CANCEL = "cancel"; public static final String WF_TRANSITION_ACCEPT_INVITE_END = "end"; public static final String WF_TRANSITION_REJECT_INVITE_END = "end"; - + // workflow properties public static final QName WF_PROP_SERVER_PATH = QName.createQName(NAMESPACE_URI, "serverPath"); public static final QName WF_PROP_ACCEPT_URL = QName.createQName(NAMESPACE_URI, "acceptUrl"); @@ -71,7 +71,7 @@ public interface WorkflowModelNominatedInvitation public static final QName WF_PROP_RESOURCE_DESCRIPTION = QName.createQName(NAMESPACE_URI, "resourceDescription"); public static final QName WF_PROP_INVITEE_ROLE = QName.createQName(NAMESPACE_URI, "inviteeRole"); public static final QName WF_PROP_INVITEE_GEN_PASSWORD = QName.createQName(NAMESPACE_URI, "inviteeGenPassword"); - + // workflow execution context variable names public static final String wfVarInviteeUserName = "inwf_inviteeUserName"; public static final String wfVarInviterUserName = "inwf_inviterUserName"; @@ -80,6 +80,11 @@ public interface WorkflowModelNominatedInvitation public static final String wfVarResourceDescription = "inwf_resourceDescription"; public static final String wfVarResourceType = "inwf_resourceType"; public static final String wfVarWorkflowInstanceId = "workflowinstanceid"; - public static final String wfVarRole = "inwf_inviteeRole"; - + public static final String wfVarRole = "inwf_inviteeRole"; + public static final String wfVarInviteTicket = "inwf_inviteTicket"; + public static final String wfVarServerPath = "inwf_serverPath"; + public static final String wfVarAcceptUrl = "inwf_acceptUrl"; + public static final String wfVarRejectUrl = "inwf_rejectUrl"; + public static final String wfVarInviteeGenPassword = "inwf_inviteeGenPassword"; + } diff --git a/source/java/org/alfresco/repo/invitation/site/InviteSender.java b/source/java/org/alfresco/repo/invitation/site/InviteSender.java new file mode 100644 index 0000000000..a9c8a4a964 --- /dev/null +++ b/source/java/org/alfresco/repo/invitation/site/InviteSender.java @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2005-2009 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.invitation.site; + +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.*; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.executer.MailActionExecuter; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.search.SearcherException; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.invitation.InvitationException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.springframework.extensions.surf.util.ParameterCheck; +import org.springframework.extensions.surf.util.URLEncoder; + +/** + * This class is responsible for sending email invitations, allowing nominated + * user's to join a Site. + * + * @author Nick Smith + */ +public class InviteSender +{ + public static final String WF_INSTANCE_ID = "wf_instanceId"; + public static final String WF_PACKAGE = "wf_package"; + + private static final List expectedProperties = Arrays.asList(wfVarInviteeUserName,// + wfVarResourceName,// + wfVarInviterUserName,// + wfVarInviteeUserName,// + wfVarRole,// + wfVarInviteeGenPassword,// + wfVarResourceName,// + wfVarInviteTicket,// + wfVarServerPath,// + wfVarAcceptUrl,// + wfVarRejectUrl, WF_INSTANCE_ID,// + WF_PACKAGE); + + private final ActionService actionService; + private final NodeService nodeService; + private final PersonService personService; + private final SearchService searchService; + private final SiteService siteService; + private final TemplateService templateService; + private final Repository repository; + + public InviteSender(ServiceRegistry services, Repository repository) + { + this.actionService = services.getActionService(); + this.nodeService = services.getNodeService(); + this.personService = services.getPersonService(); + this.searchService = services.getSearchService(); + this.siteService = services.getSiteService(); + this.templateService = services.getTemplateService(); + this.repository = repository; + } + + /** + * Sends an invitation email. + * + * @param properties A Map containing the properties needed to send the + * email. + */ + public void sendMail(Map properties) + { + checkProperties(properties); + ParameterCheck.mandatory("Properties", properties); + NodeRef inviter = personService.getPerson(properties.get(wfVarInviterUserName)); + String inviteeName = properties.get(wfVarInviteeUserName); + NodeRef invitee = personService.getPerson(inviteeName); + Action mail = actionService.createAction(MailActionExecuter.NAME); + mail.setParameterValue(MailActionExecuter.PARAM_FROM, getEmail(inviter)); + mail.setParameterValue(MailActionExecuter.PARAM_TO, getEmail(invitee)); + mail.setParameterValue(MailActionExecuter.PARAM_SUBJECT, buildSubject(properties)); + String mailText = buildMailText(properties, inviter, invitee); + mail.setParameterValue(MailActionExecuter.PARAM_TEXT, mailText); + actionService.executeAction(mail, getWorkflowPackage(properties)); + } + + /** + * @param properties + */ + private void checkProperties(Map properties) + { + Set keys = properties.keySet(); + if (!keys.containsAll(expectedProperties)) + { + LinkedList missingProperties = new LinkedList(expectedProperties); + missingProperties.removeAll(keys); + throw new InvitationException("The following mandatory properties are missing:\n" + missingProperties); + } + } + + private String buildSubject(Map properties) + { + return "Invitation to join '" + getSiteName(properties) + "' site"; + } + + private String buildMailText(Map properties, NodeRef inviter, NodeRef invitee) + { + String template = getEmailTemplate(); + Map model = makeDefaultModel(); + Map args = buildArgs(properties, inviter, invitee); + model.put("args", args); + return templateService.processTemplate(template, model); + } + + private String getEmailTemplate() + { + NodeRef template = getEmailTemplateNodeRef(); + return template.toString(); + } + + private Map buildArgs(Map properties, NodeRef inviter, NodeRef invitee) + { + String params = buildUrlParamString(properties); + String serverPath = properties.get(wfVarServerPath); + String acceptLink = serverPath + properties.get(wfVarAcceptUrl) + params; + String rejectLink = serverPath + properties.get(wfVarRejectUrl) + params; + + Map args = new HashMap(); + args.put("inviteePersonRef", invitee.toString()); + args.put("inviterPersonRef", inviter.toString()); + args.put("siteName", getSiteName(properties)); + args.put("inviteeSiteRole", properties.get(wfVarRole)); + args.put("inviteeUserName", properties.get(wfVarInviteeUserName)); + args.put("inviteeGenPassword", properties.get(wfVarInviteeGenPassword)); + args.put("acceptLink", acceptLink); + args.put("rejectLink", rejectLink); + return args; + } + + private Map makeDefaultModel() + { + NodeRef person = repository.getPerson(); + NodeRef companyHome = repository.getCompanyHome(); + NodeRef userHome = repository.getUserHome(person); + Map model = templateService.buildDefaultModel(person, companyHome, userHome, null, null); + return model; + } + + private String getEmail(NodeRef person) + { + return (String) nodeService.getProperty(person, ContentModel.PROP_EMAIL); + } + + private NodeRef getWorkflowPackage(Map properties) + { + String packageRef = properties.get(WF_PACKAGE); + return new NodeRef(packageRef); + } + + private NodeRef getEmailTemplateNodeRef() + { + StoreRef spacesStore = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); + String query = " PATH:\"app:company_home/app:dictionary/app:email_templates/cm:invite/cm:invite-email.ftl\""; + + SearchParameters searchParams = new SearchParameters(); + searchParams.addStore(spacesStore); + searchParams.setLanguage(SearchService.LANGUAGE_LUCENE); + searchParams.setQuery(query); + + ResultSet results = null; + try + { + results = searchService.query(searchParams); + List nodeRefs = results.getNodeRefs(); + if (nodeRefs.size() == 1) + return nodeRefs.get(0); + else + throw new InvitationException("Cannot find the email templatte!"); + } + catch (SearcherException e) + { + throw new InvitationException("Cannot find the email templatte!", e); + } + finally + { + if (results != null) + results.close(); + } + } + + private String buildUrlParamString(Map properties) + { + StringBuilder params = new StringBuilder("?inviteId="); + params.append(properties.get(WF_INSTANCE_ID)); + params.append("&inviteeUserName="); + params.append(URLEncoder.encode(properties.get(wfVarInviteeUserName))); + params.append("&siteShortName="); + params.append(properties.get(wfVarResourceName)); + params.append("&inviteTicket="); + params.append(properties.get(wfVarInviteTicket)); + return params.toString(); + } + + private String getSiteName(Map properties) + { + String siteFullName = properties.get(wfVarResourceName); + SiteInfo site = siteService.getSite(siteFullName); + if (site == null) + throw new InvitationException("The site " + siteFullName + " could not be found."); + + String siteName = site.getShortName(); + String siteTitle = site.getTitle(); + if (siteTitle != null && siteTitle.length() > 0) + { + siteName = siteTitle; + } + return siteName; + } +} diff --git a/source/java/org/alfresco/repo/invitation/site/InviteSenderTest.java b/source/java/org/alfresco/repo/invitation/site/InviteSenderTest.java new file mode 100644 index 0000000000..41f3c22931 --- /dev/null +++ b/source/java/org/alfresco/repo/invitation/site/InviteSenderTest.java @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2005-2009 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.invitation.site; + +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.executer.MailActionExecuter; +import org.alfresco.repo.model.Repository; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.extensions.surf.util.URLEncoder; + +/** + * @author Nick Smith + */ +public class InviteSenderTest extends TestCase +{ + private static final StoreRef testStore = new StoreRef(StoreRef.PROTOCOL_TEST, "test"); + + private static final Person inviter = new Person("inviter"); + private static final Person invitee = new Person("invitee"); + private static final Person whitespaceInvitee = new Person("First Second\tthird\nFourth\r\nFifth"); + private static final Person specialCharInvitee = new Person("àâæçéèêëîïôœùûüÿñ"); + + private static final NodeRef template = new NodeRef(testStore, "template"); + + private static final String siteName = "Full Site Name"; + private static final String siteShortName = "Site Name"; + private static final String mailText = "Mail Text"; + + private static final String acceptUrl = "/accpet"; + private static final String rejectUrl = "/reject"; + private static final String role = "Role"; + private static final String password = "password"; + private static final String ticket = "Ticket"; + private static final String path = testStore + "/path"; + private static final String packageId = testStore + "/Package"; + private static final String instanceId = "InstanceId"; + + private Action mailAction = mock(Action.class); + private SiteInfo siteInfo = mock(SiteInfo.class); + private TemplateService templateService; + private InviteSender sender; + + public void testSendMailWorkingPath() throws Exception + { + Map properties = buildDefaultProperties(); + sender.sendMail(properties); + verify(mailAction).setParameterValue(eq(MailActionExecuter.PARAM_FROM), eq(inviter.email)); + verify(mailAction).setParameterValue(eq(MailActionExecuter.PARAM_TO), eq(invitee.email)); + verify(mailAction).setParameterValue(eq(MailActionExecuter.PARAM_SUBJECT), + eq("Invitation to join '" + siteShortName + "' site")); + + Map argsMap = getArgsMap(); + assertNotNull(argsMap); + assertEquals(siteShortName, argsMap.get("siteName")); + assertEquals(invitee.node.toString(), argsMap.get("inviteePersonRef")); + assertEquals(inviter.node.toString(), argsMap.get("inviterPersonRef")); + assertEquals(siteShortName, argsMap.get("siteName")); + assertEquals(role, argsMap.get("inviteeSiteRole")); + assertEquals(invitee.name, argsMap.get("inviteeUserName")); + assertEquals(password, argsMap.get("inviteeGenPassword")); + assertEquals( + "test://test/path/accpet?inviteId=InstanceId&inviteeUserName=invitee&siteShortName=Full Site Name&inviteTicket=Ticket", + argsMap.get("acceptLink")); + assertEquals( + "test://test/path/reject?inviteId=InstanceId&inviteeUserName=invitee&siteShortName=Full Site Name&inviteTicket=Ticket", + argsMap.get("rejectLink")); + } + + public void testSendMailWithWhitespaceUserName() throws Exception + { + Map properties = buildDefaultProperties(); + properties.put(wfVarInviteeUserName, whitespaceInvitee.name); + sender.sendMail(properties); + Map argsMap = getArgsMap(); + String acceptLink = argsMap.get("acceptLink"); + assertEquals( + "test://test/path/accpet?inviteId=InstanceId&inviteeUserName=First%20Second%09third%0aFourth%0d%0aFifth&siteShortName=Full Site Name&inviteTicket=Ticket", + acceptLink); + String rejectLink = argsMap.get("rejectLink"); + assertEquals( + "test://test/path/reject?inviteId=InstanceId&inviteeUserName=First%20Second%09third%0aFourth%0d%0aFifth&siteShortName=Full Site Name&inviteTicket=Ticket", + rejectLink); + } + + public void testSendMailWithSpecialCharUserName() throws Exception + { + Map properties = buildDefaultProperties(); + properties.put(wfVarInviteeUserName, specialCharInvitee.name); + sender.sendMail(properties); + Map argsMap = getArgsMap(); + String acceptLink = argsMap.get("acceptLink"); + assertEquals( + "test://test/path/accpet?inviteId=InstanceId&inviteeUserName=%c3%a0%c3%a2%c3%a6%c3%a7%c3%a9%c3%a8%c3%aa%c3%ab%c3%ae%c3%af%c3%b4%c5%93%c3%b9%c3%bb%c3%bc%c3%bf%c3%b1&siteShortName=Full Site Name&inviteTicket=Ticket", + acceptLink); + String rejectLink = argsMap.get("rejectLink"); + assertEquals( + "test://test/path/reject?inviteId=InstanceId&inviteeUserName=%c3%a0%c3%a2%c3%a6%c3%a7%c3%a9%c3%a8%c3%aa%c3%ab%c3%ae%c3%af%c3%b4%c5%93%c3%b9%c3%bb%c3%bc%c3%bf%c3%b1&siteShortName=Full Site Name&inviteTicket=Ticket", + rejectLink); + } + + private Map buildDefaultProperties() + { + Map properties = new HashMap(); + properties.put(wfVarResourceName, siteName); + properties.put(wfVarInviteeUserName, invitee.name); + properties.put(wfVarInviterUserName, inviter.name); + properties.put(wfVarAcceptUrl, acceptUrl); + properties.put(wfVarRejectUrl, rejectUrl); + properties.put(wfVarRole, role); + properties.put(wfVarInviteeGenPassword, password); + properties.put(wfVarInviteTicket, ticket); + properties.put(wfVarServerPath, path); + properties.put(InviteSender.WF_PACKAGE, packageId); + properties.put(InviteSender.WF_INSTANCE_ID, instanceId); + return properties; + } + + @SuppressWarnings("unchecked") + private Map getArgsMap() + { + ArgumentCaptor modelCaptor = ArgumentCaptor.forClass(Map.class); + verify(templateService).processTemplate(eq(template.toString()), modelCaptor.capture()); + Map model = modelCaptor.getValue(); + Map argsMap = (Map) model.get("args"); + return argsMap; + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + ServiceRegistry services = mockServices(); + Repository repository = mockRepository(); + sender = new InviteSender(services, repository); + } + + /** + * Mocks up a Repository that will return the inviter as the current user. + * + * @return + */ + private Repository mockRepository() + { + Repository repository = mock(Repository.class); + when(repository.getPerson()).thenReturn(inviter.node); + return repository; + } + + /** + * @return + */ + private ServiceRegistry mockServices() + { + ActionService mockActionService = mockActionService(); + NodeService mockNodeService = mockNodeService(); + PersonService mockPersonService = mockPersonService(); + SearchService mockSearchService = mockSearchService(); + SiteService mockSiteService = mockSiteService(); + TemplateService mockTemplateService = mockTemplateService(); + + ServiceRegistry services = mock(ServiceRegistry.class); + when(services.getActionService()).thenReturn(mockActionService); + when(services.getNodeService()).thenReturn(mockNodeService); + when(services.getPersonService()).thenReturn(mockPersonService); + when(services.getSearchService()).thenReturn(mockSearchService); + when(services.getSiteService()).thenReturn(mockSiteService); + when(services.getTemplateService()).thenReturn(mockTemplateService); + return services; + } + + /** + * Mocks up a TemplateService that returns an empty HashMap when + * buildDefaultModel() is called. + * + * @return + */ + private TemplateService mockTemplateService() + { + this.templateService = mock(TemplateService.class); + when(templateService.buildDefaultModel(inviter.node, null, null, null, null)).thenAnswer( + new Answer>() + { + public Map answer(InvocationOnMock invocation) throws Throwable + { + return new HashMap(); + } + }); + when(templateService.processTemplate(anyString(), any())).thenReturn(mailText); + return templateService; + } + + /** + * Mocks up a SiteService that returns appropriate SiteInfo. + * + * @return + */ + private SiteService mockSiteService() + { + SiteService siteService = mock(SiteService.class); + when(siteInfo.getShortName()).thenReturn(siteShortName); + when(siteService.getSite(siteName)).thenReturn(siteInfo); + return siteService; + } + + /** + * Mocks up a SearchService that will return the template NodeRef when + * queried. + * + * @return + */ + private SearchService mockSearchService() + { + SearchService searchService = mock(SearchService.class); + ResultSet results = mock(ResultSet.class); + List nodeRefs = Arrays.asList(template); + when(results.getNodeRefs()).thenReturn(nodeRefs); + when(searchService.query((SearchParameters) any())).thenReturn(results); + return searchService; + } + + /** + * Mocks up a PersonService that returns the correct NodeRef when given a + * user name. + * + * @return + */ + private PersonService mockPersonService() + { + PersonService personService = mock(PersonService.class); + when(personService.getPerson(inviter.name)).thenReturn(inviter.node); + when(personService.getPerson(invitee.name)).thenReturn(invitee.node); + when(personService.getPerson(whitespaceInvitee.name)).thenReturn(whitespaceInvitee.node); + when(personService.getPerson(specialCharInvitee.name)).thenReturn(specialCharInvitee.node); + return personService; + } + + /** + * Mocks up NodeService to return email adresses for inviter and invitee. + * + * @return + */ + private NodeService mockNodeService() + { + NodeService nodeService = mock(NodeService.class); + when(nodeService.getProperty(inviter.node, ContentModel.PROP_EMAIL)).thenReturn(inviter.email); + when(nodeService.getProperty(invitee.node, ContentModel.PROP_EMAIL)).thenReturn(invitee.email); + when(nodeService.getProperty(whitespaceInvitee.node, ContentModel.PROP_EMAIL)).thenReturn( + whitespaceInvitee.email); + when(nodeService.getProperty(specialCharInvitee.node, ContentModel.PROP_EMAIL)).thenReturn( + specialCharInvitee.email); + return nodeService; + } + + /** + * Mocks up an ActionService which returns the mailAction field when + * createAction() is called. + * + * @return ActionService + */ + private ActionService mockActionService() + { + ActionService actionService = mock(ActionService.class); + when(actionService.createAction(MailActionExecuter.NAME)).thenReturn(mailAction); + return actionService; + } + + private static class Person + { + public final String name; + public final String email; + public final NodeRef node; + + public Person(String name) + { + this.name = name; + String encName = URLEncoder.encode(name); + this.email = encName + "@test.com"; + this.node = new NodeRef(testStore, encName); + } + + } +} diff --git a/source/java/org/alfresco/repo/invitation/site/SendInviteAction.java b/source/java/org/alfresco/repo/invitation/site/SendInviteAction.java new file mode 100644 index 0000000000..b937f2eae5 --- /dev/null +++ b/source/java/org/alfresco/repo/invitation/site/SendInviteAction.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2005-2009 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.invitation.site; + +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.*; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.jscript.ScriptNode; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.namespace.NamespaceService; +import org.jbpm.graph.exe.ExecutionContext; +import org.springframework.beans.factory.BeanFactory; + +public class SendInviteAction extends JBPMSpringActionHandler +{ + // TODO Select Version Id. + private static final long serialVersionUID = 8133039174866049136L; + + private InviteSender inviteSender; + private NamespaceService namespaceService; + + @Override + protected void initialiseHandler(BeanFactory factory) + { + Repository repository = (Repository) factory.getBean("repositoryHelper"); + ServiceRegistry services = (ServiceRegistry) factory.getBean(ServiceRegistry.SERVICE_REGISTRY); + inviteSender = new InviteSender(services, repository); + namespaceService = services.getNamespaceService(); + } + + public void execute(final ExecutionContext context) throws Exception + { + + Collection propertyNames = Arrays.asList(wfVarInviteeUserName,// + wfVarResourceName,// + wfVarInviterUserName,// + wfVarInviteeUserName,// + wfVarRole,// + wfVarInviteeGenPassword,// + wfVarResourceName,// + wfVarInviteTicket,// + wfVarServerPath,// + wfVarAcceptUrl,// + wfVarRejectUrl, + InviteSender.WF_INSTANCE_ID); + Map properties = makePropertiesFromContext(context, propertyNames); + + String packageName = WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService).replace(":", "_"); + ScriptNode packageNode = (ScriptNode) context.getVariable(packageName); + String packageRef = packageNode.getNodeRef().toString(); + properties.put(InviteSender.WF_PACKAGE, packageRef); + + String instanceName=WorkflowModel.PROP_WORKFLOW_INSTANCE_ID.toPrefixString(namespaceService).replace(":", "_"); + String instanceId = (String) context.getVariable(instanceName); + properties.put(InviteSender.WF_INSTANCE_ID, instanceId); + inviteSender.sendMail(properties); + } + + private Map makePropertiesFromContext(ExecutionContext context, Collection propertyNames) + { + Map props = new HashMap(); + for (String name : propertyNames) + { + String value = (String) context.getVariable(name); + props.put(name, value); + } + return props; + } +}