From 63bf4b13559b3ce66bbdba50870cb943dd215acc Mon Sep 17 00:00:00 2001 From: Glen Johnson Date: Wed, 9 Jul 2008 11:21:17 +0000 Subject: [PATCH] Latest drop of Java-backed version of Invite Web Scripts for (invite.get [start, cancel], inviteresponse.get [accept, reject], invites.get [pending]) - to take over from JavaScript version of these web scripts to allow secure running under admin authority git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9697 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repository/invite/invites.get.desc.xml | 10 + .../repo/web/scripts/invite/Invite.java | 367 ++++++++++++++++++ .../repo/web/scripts/invite/InviteInfo.java | 88 +++++ .../web/scripts/invite/InviteResponse.java | 237 +++++++++++ .../repo/web/scripts/invite/Invites.java | 200 ++++++++++ 5 files changed, 902 insertions(+) create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/invite/invites.get.desc.xml create mode 100644 source/java/org/alfresco/repo/web/scripts/invite/Invite.java create mode 100644 source/java/org/alfresco/repo/web/scripts/invite/InviteInfo.java create mode 100644 source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java create mode 100644 source/java/org/alfresco/repo/web/scripts/invite/Invites.java diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/invite/invites.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/invite/invites.get.desc.xml new file mode 100644 index 0000000000..9aee4d3286 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/invite/invites.get.desc.xml @@ -0,0 +1,10 @@ + + Invites + Returns pending invites filtered by Inviter user name, Invitee user name & Site short name + /api/invites?inviterUserName={inviterUserName}&inviteeUserName={inviteeUserName?}&siteShortName={siteShortName?} + /api/invites?inviterUserName={inviterUserName?}&inviteeUserName={inviteeUserName}&siteShortName={siteShortName?} + /api/invites?inviterUserName={inviterUserName?}&inviteeUserName={inviteeUserName?}&siteShortName={siteShortName} + + user + required + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/invite/Invite.java b/source/java/org/alfresco/repo/web/scripts/invite/Invite.java new file mode 100644 index 0000000000..3db87012f3 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/invite/Invite.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.web.scripts.invite; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.MutableAuthenticationDao; +import org.alfresco.repo.security.authentication.PasswordGenerator; +import org.alfresco.repo.security.authentication.UserNameGenerator; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowPath; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.scripts.DeclarativeWebScript; +import org.alfresco.web.scripts.Status; +import org.alfresco.web.scripts.WebScriptException; +import org.alfresco.web.scripts.WebScriptRequest; + +/** + * Web Script invoked by a Site Manager (Inviter) to either send + * (action='start') an invitation to a another person (Invitee) to join a Site + * as a Site Collaborator, or to cancel (action='cancel') a pending invitation + * that has already been sent out + * + * @author glen dot johnson at alfresco dot com + */ +public class Invite extends DeclarativeWebScript +{ + private static final String WORKFLOW_DEFINITION_NAME = "jbpm$wf:invite"; + private static final String ACTION_START = "start"; + private static final String ACTION_CANCEL = "cancel"; + private static final String TRANSITION_SEND_INVITE = "sendInvite"; + + private static final String MODEL_PROP_KEY_ACTION = "action"; + private static final String MODEL_PROP_KEY_WORKFLOW_ID = "workflowId"; + private static final String MODEL_PROP_KEY_INVITEE_USER_NAME = "inviteeUserName"; + private static final String MODEL_PROP_KEY_SITE_SHORT_NAME = "siteShortName"; + + // URL request parameter names + private static final String PARAM_INVITEE_EMAIL = "inviteeEmail"; + private static final String PARAM_SITE_SHORT_NAME = "siteShortName"; + private static final String PARAM_WORKFLOW_ID = "workflowId"; + + // workflow properties + public static final String WF_PROP_INVITER_USER_NAME = "wf:inviterUserName"; + public static final String WF_PROP_INVITEE_USER_NAME = "wf:inviteeUserName"; + public static final String WF_PROP_SITE_SHORT_NAME = "wf:siteShortName"; + private static final String WF_PROP_INVITEE_GEN_PASSWORD = "wf:inviteeGenPassword"; + + // services + private WorkflowService workflowService; + private PersonService personService; + private AuthenticationService authenticationService; + private MutableAuthenticationDao mutableAuthenticationDao; + + // user name and password generation beans + private UserNameGenerator usernameGenerator; + private PasswordGenerator passwordGenerator; + + /** + * Sets the workflowService property + * + * @param workflowService + * the workflow service to set + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + /** + * Set the personService property + * + * @param personService + * the person service to set + */ + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + /** + * Set the authenticationService property + * + * @param authenticationService + * the authentication service to set + */ + public void setAuthenticationService( + AuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + /** + * Set the mutable authentication DAO + * + * @param mutableAuthenticationDao + * Mutable Authentication DAO + */ + public void setMutableAuthenticationDao( + MutableAuthenticationDao mutableAuthenticationDao) + { + this.mutableAuthenticationDao = mutableAuthenticationDao; + } + + /** + * Set the user name generator service + * + * @param userNameGenerator + * the user name generator + */ + public void setUserNameGenerator(UserNameGenerator userNameGenerator) + { + this.usernameGenerator = userNameGenerator; + } + + /** + * Set the password generator service + * + * @param passwordGenerator + * the password generator + */ + public void setPasswordGenerator(PasswordGenerator passwordGenerator) + { + this.passwordGenerator = passwordGenerator; + } + + /* + * (non-Javadoc) + * + * @see + * org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco + * .web.scripts.WebScriptRequest, + * org.alfresco.web.scripts.WebScriptResponse) + */ + @Override + protected Map executeImpl(WebScriptRequest req, + Status status) + { + // initialise model to pass on for template to render + Map model = new HashMap(); + + // extract action string from URL + String servicePath = req.getServicePath(); + String action = null; + int actionStartIndex = servicePath.lastIndexOf("/") + 1; + if (actionStartIndex <= servicePath.length() - 1) + { + action = servicePath.substring(actionStartIndex, servicePath + .length()); + } + + // check that the action has been provided on the URL + // and that URL parameters have been provided + if ((action == null) || (action.length() == 0)) + { + // handle action not provided on URL + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Action has not been provided in URL"); + } + + // handle no parameters given on URL + if ((req.getParameterNames() == null) || (req.getParameterNames().length == 0)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "No parameters have been provided on URL"); + } + + // handle action 'start' + if (action.equals(ACTION_START)) + { + // check for 'inviteeEmail' parameter not provided + String inviteeEmail = req.getParameter(PARAM_INVITEE_EMAIL); + if ((inviteeEmail == null) || (inviteeEmail.length() == 0)) + { + // handle inviteeEmail URL parameter not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "'inviteeEmail' parameter " + + "has not been provided in URL for action '" + + ACTION_START + "'"); + } + + // check for 'siteShortName' parameter not provided + String siteShortName = req.getParameter(PARAM_SITE_SHORT_NAME); + if ((siteShortName == null) || (siteShortName.length() == 0)) + { + // handle siteShortName URL parameter not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "'siteShortName' parameter " + + "has not been provided in URL for action '" + + ACTION_START + "'"); + } + + // process action 'start' with provided parameters + startInvite(model, inviteeEmail, siteShortName); + } + // else handle if provided 'action' is 'cancel' + else if (action.equals(ACTION_CANCEL)) + { + // check for 'workflowId' parameter not provided + String workflowId = req.getParameter(PARAM_WORKFLOW_ID); + if ((workflowId == null) || (workflowId.length() == 0)) + { + // handle workflowId URL parameter not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "'workflowId' parameter has " + + "not been provided in URL for action '" + + ACTION_CANCEL + "'"); + } + + // process action 'cancel' with provided parameters + cancelInvite(model, workflowId); + } + // handle action not recognised + else + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Action, '" + + action + "', " + + "provided in URL has not been recognised."); + } + + return model; + } + + /** + * Starts the Invite workflow + * + * @param model + * model to add objects to, which will be passed to the template + * for rendering + * @param inviteeEmail + * email address of invitee + * @param siteShortName + * short name of site that the invitee is being invited to by the + * inviter + * + */ + private void startInvite(Map model, String inviteeEmail, + String siteShortName) + { + WorkflowDefinition wfDefinition = this.workflowService + .getDefinitionByName(WORKFLOW_DEFINITION_NAME); + + // handle workflow definition does not exist + if (wfDefinition == null) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, + "Workflow definition " + "for name " + + WORKFLOW_DEFINITION_NAME + " does not exist"); + } + + char[] generatedPassword = null; + + // generate user name + String inviteeUserName = usernameGenerator.generateUserName(); + + // create person if user name does not already exist + if (!this.personService.personExists(inviteeUserName)) + { + Map properties = new HashMap(); + + properties.put(ContentModel.PROP_USERNAME, inviteeUserName); + properties.put(ContentModel.PROP_EMAIL, inviteeEmail); + + this.personService.createPerson(properties); + } else + { + throw new WebScriptException( + Status.STATUS_INTERNAL_SERVER_ERROR, + "When trying to create a user account for Invitee with generated user name, " + + inviteeUserName + + ", a person was found who already has that user name"); + } + + // create invitee person with generated user name and password, and with + // a disabled user account (with a generated password) + + // generate password + generatedPassword = passwordGenerator.generatePassword().toCharArray(); + + // create account for person with generated userName and + // password + mutableAuthenticationDao.createUser(inviteeUserName, generatedPassword); + mutableAuthenticationDao.setEnabled(inviteeUserName, false); + + // create workflow properties + Map workflowProps = new HashMap( + 4); + workflowProps.put(QName.createQName(WF_PROP_INVITER_USER_NAME), + this.authenticationService.getCurrentUserName()); + workflowProps.put(QName.createQName(WF_PROP_INVITEE_USER_NAME), + inviteeUserName); + workflowProps.put(QName.createQName(WF_PROP_INVITEE_GEN_PASSWORD), + generatedPassword); + workflowProps.put(QName.createQName(WF_PROP_SITE_SHORT_NAME), siteShortName); + + // start the workflow + WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition + .getId(), workflowProps); + String workflowId = wfPath.instance.id; + + // send out the invite + this.workflowService.signal(wfPath.id, TRANSITION_SEND_INVITE); + + // add model properties for template to render + model.put(MODEL_PROP_KEY_ACTION, ACTION_START); + model.put(MODEL_PROP_KEY_WORKFLOW_ID, workflowId); + model.put(MODEL_PROP_KEY_INVITEE_USER_NAME, inviteeUserName); + model.put(MODEL_PROP_KEY_SITE_SHORT_NAME, siteShortName); + } + + /** + * Cancels pending invite. Note that only the Inviter should cancel the + * pending invite. + * + * @param model + * model to add objects to, which will be passed to the template + * for rendering + * @param workflowId + * workflow id of the invite process that inviter wishes to + * cancel + */ + private void cancelInvite(Map model, String workflowId) + { + // handle workflow instance for given workflow ID does not exist + if ((workflowId == null) || (workflowId.length() == 0)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Workflow instance for given " + "workflow ID " + + workflowId + " does not exist"); + } + + // cancel the workflow + this.workflowService.cancelWorkflow(workflowId); + + // add model properties for template to render + model.put(MODEL_PROP_KEY_ACTION, ACTION_CANCEL); + model.put(MODEL_PROP_KEY_WORKFLOW_ID, workflowId); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/invite/InviteInfo.java b/source/java/org/alfresco/repo/web/scripts/invite/InviteInfo.java new file mode 100644 index 0000000000..4d49047294 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/invite/InviteInfo.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.web.scripts.invite; + +/** + * Holds properties pertaining to an invitation that has been sent out by a Site Manager (Inviter) + * to another person (Invitee) to join his/her Site + * + * @author glen dot johnson at alfresco dot com + */ +public class InviteInfo +{ + // private instances to hold property values + private String inviterUserName; + private String inviteeUserName; + private String siteShortName; + private String inviteId; + + public InviteInfo(String inviterUserName, String inviteeUserName, String siteShortName, String inviteId) + { + this.inviterUserName = inviterUserName; + this.inviteeUserName = inviteeUserName; + this.siteShortName = siteShortName; + this.inviteId = inviteId; + } + + /** + * Gets the inviter user name + * + * @return the inviterUserName + */ + public String getInviterUserName() + { + return inviterUserName; + } + + /** + * Gets the invitee user name + * + * @return the inviteeUserName + */ + public String getInviteeUserName() + { + return inviteeUserName; + } + + /** + * Gets the site short name + * + * @return the siteShortName + */ + public String getSiteShortName() + { + return siteShortName; + } + + /** + * Gets the invite ID + * + * @return the inviteId + */ + public String getInviteId() + { + return inviteId; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java b/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java new file mode 100644 index 0000000000..ad248888a9 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.web.scripts.invite; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.security.authentication.MutableAuthenticationDao; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.site.SiteService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.web.scripts.DeclarativeWebScript; +import org.alfresco.web.scripts.Status; +import org.alfresco.web.scripts.WebScriptException; +import org.alfresco.web.scripts.WebScriptRequest; + +/** + * Web Script invoked by Invitee to either accept (response='accept') an + * invitation from a Site Manager (Inviter) to join a Site as a Site + * Collaborator, or to reject (response='reject') an invitation that has + * already been sent out + * + * @author glen dot johnson at alfresco dot com + */ +public class InviteResponse extends DeclarativeWebScript +{ + private static final String RESPONSE_ACCEPT = "accept"; + private static final String RESPONSE_REJECT = "reject"; + private static final String TRANSITION_ACCEPT = "accept"; + private static final String TRANSITION_REJECT = "reject"; + private static final String MODEL_PROP_KEY_RESPONSE = "response"; + private static final String MODEL_PROP_KEY_SITE_SHORT_NAME = "siteShortName"; + + // properties for services + private WorkflowService workflowService; + private MutableAuthenticationDao mutableAuthenticationDao; + private SiteService siteService; + private PersonService personService; + + /** + * Sets the workflow service property + * + * @param workflowService + * the workflow service instance assign to the property + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + /** + * Sets the mutableAuthenticationDao service property + * + * @param mutableAuthenticationDao + * the MutableAuthenticationDao service to set + */ + public void setMutableAuthenticationDao( + MutableAuthenticationDao mutableAuthenticationDao) + { + this.mutableAuthenticationDao = mutableAuthenticationDao; + } + + /** + * Sets the siteService property + * + * @param siteService + * the siteService to set + */ + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + /** + * Sets the personService property + * + * @param personService + * the person service to set + */ + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + /* + * (non-Javadoc) + * + * @see + * org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco + * .web.scripts.WebScriptRequest, + * org.alfresco.web.scripts.WebScriptResponse) + */ + @Override + protected Map executeImpl(WebScriptRequest req, + Status status) + { + // initialise model to pass on for template to render + Map model = new HashMap(); + + // get the URL parameter values + String workflowId = req.getParameter("workflowId"); + String inviteeUserName = req.getParameter("inviteeUserName"); + String siteShortName = req.getParameter("siteShortName"); + + // get the invite response value + String response = req.getExtensionPath(); + + // check that response has been provided + if ((response == null) || (response.length() == 0)) + { + // handle response not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "response has not been provided as part of URL."); + } + // check that workflow id URL parameter has been provided + else if ((workflowId == null) || (workflowId.length() == 0)) + { + // handle workflow id not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "workflow id parameter has not been provided in the URL."); + } + // check that inviteeUserName URL parameter has been provided + else if ((inviteeUserName == null) || (inviteeUserName.length() == 0)) + { + // handle inviteeUserName not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "inviteeUserName parameter has not been provided in the URL."); + } + // check that siteShortName URL parameter has been provided + else if ((siteShortName == null) || (siteShortName.length() == 0)) + { + // handle siteShortName not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "siteShortName parameter has not been provided in the URL."); + } else + { + // process response + if (response.equals(RESPONSE_ACCEPT)) + { + acceptInvite(model, workflowId, inviteeUserName, siteShortName); + } else if (response.equals(RESPONSE_REJECT)) + { + rejectInvite(model, workflowId, inviteeUserName, siteShortName); + } else + { + /* handle unrecognised response */ + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "response, " + response + + ", provided in URL has not been recognised."); + } + } + + return model; + } + + /** + * Processes 'accept' response from invitee + * + * @param model + * model to add objects to, which will be passed to the template + * for rendering + * @param workflowId + * string id of invite process workflow instance + * @param inviteeUserName + * string user name of invitee + * @param siteShortName + * string short name of site for which invitee is accepting + * invitation to join + */ + private void acceptInvite(Map model, String workflowId, + String inviteeUserName, String siteShortName) + { + this.workflowService.signal(workflowId, TRANSITION_ACCEPT); + + // enable invitee person's user account because he/she has accepted the + // site invitation + this.mutableAuthenticationDao.setEnabled(inviteeUserName, true); + + // Add Invitee to Site as "Site Collaborator" role + this.siteService.setMembership(siteShortName, inviteeUserName, + SiteModel.SITE_COLLABORATOR); + + // add model properties for template to render + model.put(MODEL_PROP_KEY_RESPONSE, RESPONSE_ACCEPT); + model.put(MODEL_PROP_KEY_SITE_SHORT_NAME, siteShortName); + } + + /** + * Processes 'reject' invite response from invitee + * + * @param model + * model to add objects to, which will be passed to the template + * for rendering + * @param workflowId + * string id of invite process workflow instance + * @param inviteeUserName + * string user name of invitee + * @param siteShortName + * string short name of site for which invitee is rejecting + * invitation to join + */ + private void rejectInvite(Map model, String workflowId, + String inviteeUserName, String siteShortName) + { + this.workflowService.signal(workflowId, TRANSITION_REJECT); + + // delete the person created for invitee + this.personService.deletePerson(inviteeUserName); + + // add model properties for template to render + model.put(MODEL_PROP_KEY_RESPONSE, RESPONSE_REJECT); + model.put(MODEL_PROP_KEY_SITE_SHORT_NAME, siteShortName); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/invite/Invites.java b/source/java/org/alfresco/repo/web/scripts/invite/Invites.java new file mode 100644 index 0000000000..e6aa489ece --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/invite/Invites.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.web.scripts.invite; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.cmr.workflow.WorkflowTaskQuery; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.scripts.DeclarativeWebScript; +import org.alfresco.web.scripts.Status; +import org.alfresco.web.scripts.WebScriptException; +import org.alfresco.web.scripts.WebScriptRequest; + +/** + * Web Script which returns either + * (1) Site invitations pending against a given + * person (user name). i.e. including both invitations which have been sent + * by that person (inviter) which have not been responded to (accepted or rejected) + * by the recipient (invitee), and also invitations which have been received by that + * person, but which he/she hasn't responded to yet. + * (2) Invitations pending against a given site (site short name) + * invoked by a Site Manager (Inviter) to either send + * (action='start') an invitation to a another person (Invitee) to join a Site + * as a Site Collaborator, or to cancel (action='cancel') a pending invitation + * that has already been sent out + * + * @author glen dot johnson at alfresco dot com + */ +public class Invites extends DeclarativeWebScript +{ + // request parameter names + private static final String PARAM_INVITER_USER_NAME = "inviterUserName"; + private static final String PARAM_INVITEE_USER_NAME = "inviteeUserName"; + private static final String PARAM_SITE_SHORT_NAME = "siteShortName"; + + // service instances + private WorkflowService workflowService; + + // invite process definition name + private static final QName WF_INVITE_PROCESS_DEFINITION_QNAME = QName.createQName("wf:invite"); + + // model key names + private static final String MODEL_KEY_NAME_INVITES = "invites"; + + /** + * Set the workflow service property + * + * @param workflowService the workflow service to set + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + /* + * (non-Javadoc) + * + * @see + * org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco + * .web.scripts.WebScriptRequest, + * org.alfresco.web.scripts.WebScriptResponse) + */ + @Override + protected Map executeImpl(WebScriptRequest req, + Status status) + { + // initialise model to pass on for template to render + Map model = new HashMap(); + // Get parameter names + String[] paramNames = req.getParameterNames(); + + // handle no parameters given on URL + if ((paramNames == null) || (paramNames.length == 0)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "No parameters have been provided on URL"); + } + + // get URL request parameters + + String inviterUserName = req.getParameter(PARAM_INVITER_USER_NAME); + // check for 'inviterUserName' parameter not provided + if ((inviterUserName == null) || (inviterUserName.length() == 0)) + { + // handle inviterUserName URL parameter not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "'inviterUserName' parameter has not been provided in URL"); + } + + String inviteeUserName = req.getParameter(PARAM_INVITEE_USER_NAME); + // check for 'inviteeUserName' parameter not provided + if ((inviteeUserName == null) || (inviteeUserName.length() == 0)) + { + // handle inviteeUserName URL parameter not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "'inviteeUserName' parameter has not been provided in URL"); + } + + String siteShortName = req.getParameter(PARAM_SITE_SHORT_NAME); + // check for 'siteShortName' parameter not provided + if ((siteShortName == null) || (siteShortName.length() == 0)) + { + // handle siteShortName URL parameter not provided + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "'siteShortName' parameter has not been provided in URL"); + } + + // query for workflow tasks by given parameters + // create workflow task query + WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); + + // query only active workflows + wfTaskQuery.setActive(Boolean.TRUE); + + // create the query properties from the invite URL request parameters + // - because this web script class will terminate if no invite URL request + // - parameters are set, at least one of these query properties will always be set + final HashMap wfQueryProps = new HashMap(3, 1.0f); + if (inviterUserName != null) + { + wfQueryProps.put(QName.createQName(Invite.WF_PROP_INVITER_USER_NAME), inviterUserName); + } + if (inviteeUserName != null) + { + wfQueryProps.put(QName.createQName(Invite.WF_PROP_INVITER_USER_NAME), inviteeUserName); + } + if (siteShortName != null) + { + wfQueryProps.put(QName.createQName(Invite.WF_PROP_INVITER_USER_NAME), siteShortName); + } + + // set workflow task query parameters + wfTaskQuery.setProcessCustomProps(wfQueryProps); + + // set process name to "wf:invite" so that only tasks associated with invite workflow instances + // are returned by query + wfTaskQuery.setProcessName(WF_INVITE_PROCESS_DEFINITION_QNAME); + + // query for invite workflow tasks + List wf_invite_tasks = this.workflowService.queryTasks(wfTaskQuery); + + // InviteInfo List to place onto model + List inviteInfoList = new ArrayList(); + + // Put InviteInfo object (containing workflow path properties + // wf:inviteUserName, wf:inviterUserName, wf:siteShortName, + // and invite id property (from workflow instance id)) + // for each invite workflow task returned by the query + // onto model (that is passed onto the template for rendering) + for (WorkflowTask workflowTask : wf_invite_tasks) + { + // get wf:inviterUserName, wf:inviteeUserName, wf:siteShortName + // properties from workflow path associated with workflow task + Map pathProperties = this.workflowService.getPathProperties(workflowTask.path.id); + String inviterUserNameProp = (String)pathProperties.get(Invite.WF_PROP_INVITER_USER_NAME); + String inviteeUserNameProp = (String)pathProperties.get(Invite.WF_PROP_INVITEE_USER_NAME); + String siteShortNameProp = (String)pathProperties.get(Invite.WF_PROP_SITE_SHORT_NAME); + + // get workflow instance id (associated with workflow task) to place as "inviteId" onto model + String workflowId = workflowTask.path.instance.id; + + // create and add InviteInfo to inviteInfoList + InviteInfo inviteInfo = new InviteInfo(inviterUserNameProp, inviteeUserNameProp, siteShortNameProp, workflowId); + inviteInfoList.add(inviteInfo); + } + + // put the list of invite infos onto model to be passed onto template for rendering + model.put(MODEL_KEY_NAME_INVITES, inviteInfoList); + + return model; + } +}