diff --git a/packaging/war/src/main/webapp/images/logo/workspace.png b/packaging/war/src/main/webapp/images/logo/workspace.png new file mode 100644 index 0000000000..26c01ad48e Binary files /dev/null and b/packaging/war/src/main/webapp/images/logo/workspace.png differ diff --git a/remote-api/src/main/java/org/alfresco/rest/api/SiteMembershipRequests.java b/remote-api/src/main/java/org/alfresco/rest/api/SiteMembershipRequests.java index fa6892b1df..45609fcab0 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/SiteMembershipRequests.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/SiteMembershipRequests.java @@ -45,15 +45,25 @@ public interface SiteMembershipRequests /** * Create a site membership request for the user 'inviteeId' - * @param inviteeId the site inviteee id + * @param inviteeId the site invite id * @param siteInvite the site invite * @return SiteMembershipRequest */ SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite); + + /** + * Create a site membership request for the user 'inviteeId' + * @param inviteeId the site invitee id + * @param siteInvite the site invite + * @param client the client name which is registered to send emails + * @param workspacePath path of workspace deployed location + * @return SiteMembershipRequest + */ + SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite, final String client, final String workspacePath); /** * Update the site membership request for inviteeId and site - * @param inviteeId the site inviteee id + * @param inviteeId the site invite id * @param siteInvite the site invite * @return the updated siteMembershipRequest */ @@ -62,7 +72,7 @@ public interface SiteMembershipRequests /** * Cancel site membership request for invitee and site. * - * @param inviteeId the site inviteee id + * @param inviteeId the site invite id * @param siteId the site id */ void cancelSiteMembershipRequest(String inviteeId, String siteId); @@ -70,7 +80,7 @@ public interface SiteMembershipRequests /** * Get the site membership request for inviteeId and siteId, if it exists. * - * @param inviteeId the site inviteee id + * @param inviteeId the site invite id * @param siteId the site id * @return the site membership request */ @@ -79,7 +89,7 @@ public interface SiteMembershipRequests /** * Get a paged list of site membership requests for inviteeId. * - * @param inviteeId the site inviteee id + * @param inviteeId the site invite id * @param paging paging information * @return a paged list of site membership requests */ diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java index 6cc008c731..218f8697a6 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java @@ -158,9 +158,9 @@ public class SiteMembershipRequestsImpl implements SiteMembershipRequests } private SiteMembershipRequest inviteToModeratedSite(final String message, final String inviteeId, final String siteId, - final String inviteeRole) + final String inviteeRole, final String clientName, final String workspacePath) { - ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole); + ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole, clientName, workspacePath); SiteMembershipRequest ret = new SiteMembershipRequest(); ret.setId(siteId); @@ -270,7 +270,74 @@ public class SiteMembershipRequestsImpl implements SiteMembershipRequests if(siteVisibility.equals(SiteVisibility.MODERATED)) { - request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole); + request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole, null, null); + } + else if(siteVisibility.equals(SiteVisibility.PUBLIC)) + { + request = inviteToPublicSite(siteInfo, message, inviteeId, inviteeRole); + } + else + { + // note: security, no indication that this is a private site + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + + return request; + } + + @Override + public SiteMembershipRequest createSiteMembershipRequest(String inviteeId, SiteMembershipRequest siteInvite, String client, String workspacePath) { + SiteMembershipRequest request = null; + + inviteeId = people.validatePerson(inviteeId, true); + + // Note that the order of error checking is important. The server first needs to check for the status 404 + // conditions before checking for status 400 conditions. Otherwise the server is open to a probing attack. + String siteId = siteInvite.getId(); + final SiteInfo siteInfo = sites.validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + final SiteVisibility siteVisibility = siteInfo.getVisibility(); + + if(siteVisibility.equals(SiteVisibility.PRIVATE)) + { + // note: security, no indication that this is a private site + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + + // Is the invitee already a member of the site? + boolean isMember = siteService.isMember(siteId, inviteeId); + if(isMember) + { + // yes + throw new InvalidArgumentException(inviteeId + " is already a member of site " + siteId); + } + + // Is there an outstanding site invite request for the (invitee, site)? + Invitation invitation = getSiteInvitation(inviteeId, siteId); + if(invitation != null) + { + // yes + throw new InvalidArgumentException(inviteeId + " is already invited to site " + siteId); + } + + final String inviteeRole = DEFAULT_ROLE; + String message = siteInvite.getMessage(); + if(message == null) + { + // the invitation service ignores null messages so convert to an empty message. + message = ""; + } + + if(siteVisibility.equals(SiteVisibility.MODERATED)) + { + request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole, client, workspacePath);; } else if(siteVisibility.equals(SiteVisibility.PUBLIC)) { diff --git a/remote-api/src/main/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java b/remote-api/src/main/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java index 3d7c018e26..3537cbc5f3 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.rest.api.people; import java.util.ArrayList; @@ -73,7 +73,14 @@ RelationshipResourceAction.Create, RelationshipResourceAc List result = new ArrayList(invites.size()); for(SiteMembershipRequest invite : invites) { - SiteMembershipRequest siteInvite = siteMembershipRequests.createSiteMembershipRequest(personId, invite); + SiteMembershipRequest siteInvite = null; + String client = parameters.getParameter("client"); + String workspacePath = parameters.getParameter("workspacePath"); + if(client != null) { + siteInvite = siteMembershipRequests.createSiteMembershipRequest(personId, invite, client, workspacePath); + } else { + siteInvite = siteMembershipRequests.createSiteMembershipRequest(personId, invite); + } result.add(siteInvite); } return result; diff --git a/repository/src/main/java/org/alfresco/repo/invitation/InvitationImpl.java b/repository/src/main/java/org/alfresco/repo/invitation/InvitationImpl.java index 803a68d46f..5b638ff0f9 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/InvitationImpl.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/InvitationImpl.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.invitation; import java.io.Serializable; @@ -42,6 +42,7 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType; public static final String ROLE_KEY = "role"; public static final String CREATED_AT = "createdAt"; public static final String MODIFIED_AT = "modifiedAt"; + public static final String CLIENT_NAME = "clientName"; /** * Unique reference for this invitation @@ -72,6 +73,8 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType; private final Date modifiedAt; + private final Date clientName; + public InvitationImpl(Map props) { this.inviteId = (String)props.get(ID_KEY); @@ -82,6 +85,7 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType; this.resourceType = type==null ? ResourceType.WEB_SITE : ResourceType.valueOf(type); this.createdAt = (Date)props.get(CREATED_AT); this.modifiedAt = (Date)props.get(MODIFIED_AT); + this.clientName = (Date)props.get(CLIENT_NAME); } /** @@ -122,6 +126,11 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType; { return inviteeUserName; } + + public Date getClientName() + { + return clientName; + } public abstract InvitationType getInvitationType(); } diff --git a/repository/src/main/java/org/alfresco/repo/invitation/InvitationServiceImpl.java b/repository/src/main/java/org/alfresco/repo/invitation/InvitationServiceImpl.java index aa3872bb71..41562d8ba2 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/InvitationServiceImpl.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/InvitationServiceImpl.java @@ -1,119 +1,120 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.invitation; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarAcceptUrl; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteTicket; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeGenPassword; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeUserName; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviterUserName; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRejectUrl; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRole; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.action.executer.MailActionExecuter; -import org.alfresco.repo.admin.SysAdminParams; -import org.alfresco.repo.i18n.MessageService; -import org.alfresco.repo.invitation.activiti.SendNominatedInviteDelegate; -import org.alfresco.repo.invitation.site.InviteModeratedSender; -import org.alfresco.repo.invitation.site.InviteNominatedSender; -import org.alfresco.repo.invitation.site.InviteSender; -import org.alfresco.repo.jscript.ScriptNode; -import org.alfresco.repo.model.Repository; -import org.alfresco.repo.node.NodeServicePolicies; -import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy; -import org.alfresco.repo.policy.JavaBehaviour; -import org.alfresco.repo.policy.PolicyComponent; -import org.alfresco.repo.security.authentication.AuthenticationException; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.security.authentication.PasswordGenerator; -import org.alfresco.repo.security.authentication.UserNameGenerator; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.transaction.TransactionalResourceHelper; -import org.alfresco.repo.workflow.CancelWorkflowActionExecuter; -import org.alfresco.repo.workflow.WorkflowModel; -import org.alfresco.repo.workflow.activiti.ActivitiConstants; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.action.Action; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.invitation.Invitation; -import org.alfresco.service.cmr.invitation.Invitation.ResourceType; -import org.alfresco.service.cmr.invitation.InvitationException; -import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; -import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; -import org.alfresco.service.cmr.invitation.InvitationExceptionUserError; -import org.alfresco.service.cmr.invitation.InvitationSearchCriteria; -import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; -import org.alfresco.service.cmr.invitation.InvitationService; -import org.alfresco.service.cmr.invitation.ModeratedInvitation; -import org.alfresco.service.cmr.invitation.NominatedInvitation; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.TemplateService; -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.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.workflow.WorkflowAdminService; -import org.alfresco.service.cmr.workflow.WorkflowDefinition; -import org.alfresco.service.cmr.workflow.WorkflowException; -import org.alfresco.service.cmr.workflow.WorkflowPath; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.cmr.workflow.WorkflowTask; -import org.alfresco.service.cmr.workflow.WorkflowTaskQuery; -import org.alfresco.service.cmr.workflow.WorkflowTaskState; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.GUID; -import org.alfresco.util.PropertyCheck; -import org.alfresco.util.UrlUtil; -import org.alfresco.util.collections.CollectionUtils; -import org.alfresco.util.collections.Function; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.surf.util.I18NUtil; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarAcceptUrl; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteTicket; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeGenPassword; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeUserName; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviterUserName; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRejectUrl; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRole; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.executer.MailActionExecuter; +import org.alfresco.repo.admin.SysAdminParams; +import org.alfresco.repo.client.config.ClientAppConfig; +import org.alfresco.repo.i18n.MessageService; +import org.alfresco.repo.invitation.activiti.SendNominatedInviteDelegate; +import org.alfresco.repo.invitation.site.InviteModeratedSender; +import org.alfresco.repo.invitation.site.InviteNominatedSender; +import org.alfresco.repo.invitation.site.InviteSender; +import org.alfresco.repo.jscript.ScriptNode; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.node.NodeServicePolicies; +import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy; +import org.alfresco.repo.policy.JavaBehaviour; +import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.security.authentication.PasswordGenerator; +import org.alfresco.repo.security.authentication.UserNameGenerator; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.transaction.TransactionalResourceHelper; +import org.alfresco.repo.workflow.CancelWorkflowActionExecuter; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.Invitation.ResourceType; +import org.alfresco.service.cmr.invitation.InvitationException; +import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; +import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; +import org.alfresco.service.cmr.invitation.InvitationExceptionUserError; +import org.alfresco.service.cmr.invitation.InvitationSearchCriteria; +import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; +import org.alfresco.service.cmr.invitation.InvitationService; +import org.alfresco.service.cmr.invitation.ModeratedInvitation; +import org.alfresco.service.cmr.invitation.NominatedInvitation; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.TemplateService; +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.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.workflow.WorkflowAdminService; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowException; +import org.alfresco.service.cmr.workflow.WorkflowPath; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.cmr.workflow.WorkflowTaskQuery; +import org.alfresco.service.cmr.workflow.WorkflowTaskState; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; +import org.alfresco.util.PropertyCheck; +import org.alfresco.util.UrlUtil; +import org.alfresco.util.collections.CollectionUtils; +import org.alfresco.util.collections.Function; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; /** * Implementation of invitation service. @@ -138,14 +139,16 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli wfVarServerPath,// wfVarAcceptUrl,// wfVarRejectUrl, - InviteNominatedSender.WF_INSTANCE_ID); - - private static final List SEND_INVITE_MODERATED_PROP_NAMES = Arrays.asList( - WorkflowModelModeratedInvitation.wfVarInviteeUserName, - WorkflowModelModeratedInvitation.wfVarInviteeRole, - WorkflowModelModeratedInvitation.wfVarResourceName, - WorkflowModelModeratedInvitation.bpmGroupAssignee, - WorkflowModelModeratedInvitation.wfVarResourceType); + InviteNominatedSender.WF_INSTANCE_ID); + + private static final List SEND_INVITE_MODERATED_PROP_NAMES = Arrays.asList( + WorkflowModelModeratedInvitation.wfVarInviteeUserName, + WorkflowModelModeratedInvitation.wfVarInviteeRole, + WorkflowModelModeratedInvitation.wfVarResourceName, + WorkflowModelModeratedInvitation.bpmGroupAssignee, + WorkflowModelModeratedInvitation.wfVarResourceType, + WorkflowModelModeratedInvitation.wfVarTemplateAssetsUrl, + WorkflowModelModeratedInvitation.wfVarWorkspaceUrl); /** @@ -170,8 +173,9 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli private Repository repositoryHelper; private ServiceRegistry serviceRegistry; private MessageService messageService; - private InviteNominatedSender inviteNominatedSender; + private InviteNominatedSender inviteNominatedSender; private InviteModeratedSender inviteModeratedSender; + private ClientAppConfig clientAppConfig; // maximum number of tries to generate a invitee user name which // does not already belong to an existing person @@ -194,6 +198,11 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli private String moderatedInvitationWorkflowId = WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; + public void setClientAppConfig(ClientAppConfig clientAppConfig) + { + this.clientAppConfig = clientAppConfig; + } + /** * Set the policy component * @@ -253,7 +262,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli PropertyCheck.mandatory(this, "PolicyComponent", policyComponent); PropertyCheck.mandatory(this, "templateService", templateService); - this.inviteNominatedSender = new InviteNominatedSender(serviceRegistry, repositoryHelper, messageService); + this.inviteNominatedSender = new InviteNominatedSender(serviceRegistry, repositoryHelper, messageService); this.inviteModeratedSender = new InviteModeratedSender(serviceRegistry, repositoryHelper, messageService); // @@ -995,7 +1004,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli query.setTaskName(WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK); // query for invite workflow tasks - List results = new ArrayList(); + List results = new ArrayList(); if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) { query.setTaskName(WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK); @@ -1983,10 +1992,10 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli String emailSubjectKey, Map executionVariables) { sendInviteEmail(inviteNominatedSender, SEND_INVITE_NOMINATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables); - } - - private void sendInviteEmail(InviteSender inviteSender, List invitePropNames, String inviteId, String emailTemplateXpath, String emailSubjectKey, Map executionVariables) - { + } + + private void sendInviteEmail(InviteSender inviteSender, List invitePropNames, String inviteId, String emailTemplateXpath, String emailSubjectKey, Map executionVariables) + { if (isSendEmails()) { Map properties = makePropertiesFromContextVariables(executionVariables, invitePropNames); @@ -1997,23 +2006,23 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli properties.put(InviteNominatedSender.WF_INSTANCE_ID, inviteId); inviteSender.sendMail(emailTemplateXpath, emailSubjectKey, properties); - } - } - - - @Override - public void sendModeratedInvitation(String inviteId, String emailTemplateXpath, String emailSubjectKey, Map executionVariables) - { - sendInviteEmail(inviteModeratedSender, SEND_INVITE_MODERATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables); - - } - - private String getPackageRef(Map executionVariables) - { - String packageName = WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService).replace(":", "_"); - ScriptNode packageNode = (ScriptNode) executionVariables.get(packageName); - String packageRef = packageNode.getNodeRef().toString(); - return packageRef; + } + } + + + @Override + public void sendModeratedInvitation(String inviteId, String emailTemplateXpath, String emailSubjectKey, Map executionVariables) + { + sendInviteEmail(inviteModeratedSender, SEND_INVITE_MODERATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables); + + } + + private String getPackageRef(Map executionVariables) + { + String packageName = WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService).replace(":", "_"); + ScriptNode packageNode = (ScriptNode) executionVariables.get(packageName); + String packageRef = packageNode.getNodeRef().toString(); + return packageRef; } @Override @@ -2042,4 +2051,71 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli { return CollectionUtils.filterKeys((Map) executionVariables, CollectionUtils.containsFilter(propertyNames)); } + + /** + * Start the invitation process for a ModeratedInvitation + * + * @param inviteeComments why does the invitee want access to the resource ? + * @param inviteeUserName who is to be invited + * @param resourceType Invitation .ResourceType what resource type ? + * @param resourceName which resource + * @param inviteeRole which role ? + * @param clientName which client + */ + public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, + Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String clientName, String workspacePath) + { + if (resourceType == Invitation.ResourceType.WEB_SITE) + { + return startModeratedInvite(inviteeComments, inviteeUserName, resourceType, resourceName, inviteeRole, clientName, workspacePath); + } + throw new InvitationException("unknown resource type"); + } + + /** + * Moderated invitation implementation for given client + * + * @return the new moderated invitation + */ + private ModeratedInvitation startModeratedInvite(String inviteeComments, String inviteeUserName, + Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String clientName, String workspacePath) + { + SiteInfo siteInfo = siteService.getSite(resourceName); + + if (siteService.isMember(resourceName, inviteeUserName)) + { + if (logger.isDebugEnabled()) + logger.debug("Failed - invitee user is already a member of the site."); + + Object objs[] = { inviteeUserName, "", resourceName }; + throw new InvitationExceptionUserError("invitation.invite.already_member", objs); + } + + String roleGroup = siteService.getSiteRoleGroup(resourceName, SiteModel.SITE_MANAGER); + + // get the workflow description + String workflowDescription = generateWorkflowDescription(siteInfo, "invitation.moderated.workflow.description"); + + Map workflowProps = new HashMap(16); + workflowProps.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, workflowDescription); + 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()); + + workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_CLIENT_NAME, clientName); + if(clientName != null && clientAppConfig.getClient(clientName) != null) { + ClientAppConfig.ClientApp client = clientAppConfig.getClient(clientName); + workflowProps.put(WorkflowModelModeratedInvitation.WF_TEMPLATE_ASSETS_URL, client.getTemplateAssetsUrl()); + String workspaceUrl = workspacePath != null ? workspacePath : client.getProperty("workspaceUrl"); + workflowProps.put(WorkflowModelModeratedInvitation.WF_WORKSPACE_URL, workspaceUrl); + } + + // get the moderated workflow + + WorkflowDefinition wfDefinition = getWorkflowDefinition(InvitationWorkflowType.MODERATED); + return (ModeratedInvitation) startWorkflow(wfDefinition, workflowProps); + } } diff --git a/repository/src/main/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java b/repository/src/main/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java index c7e9f27cef..22820764fb 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.invitation; import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS; @@ -31,6 +31,7 @@ import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_P import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_MODIFIED_AT; import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME; import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE; +import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_CLIENT_NAME; import java.io.Serializable; import java.util.Date; @@ -77,6 +78,7 @@ import org.alfresco.service.namespace.QName; parentProps.put(RESOURCE_TYPE_KEY,(String)props.get(WF_PROP_RESOURCE_TYPE)); parentProps.put(CREATED_AT,(Date)props.get(ContentModel.PROP_CREATED)); parentProps.put(MODIFIED_AT,(Date)props.get(WF_PROP_MODIFIED_AT)); + parentProps.put(CLIENT_NAME,(Date)props.get(WF_PROP_CLIENT_NAME)); return parentProps; } diff --git a/repository/src/main/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java b/repository/src/main/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java index 0e63cd06b6..b04bcdd5a8 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.invitation; import org.alfresco.service.namespace.NamespaceService; @@ -66,6 +66,11 @@ public interface WorkflowModelModeratedInvitation public static final QName WF_PROP_REVIEWER= QName.createQName(NAMESPACE_URI, "reviewer"); public static final QName WF_PROP_MODIFIED_AT= QName.createQName(NAMESPACE_URI, "modifiedAt"); + public static final QName WF_PROP_CLIENT_NAME= QName.createQName(NAMESPACE_URI, "clientName"); + public static final QName WF_WORKSPACE_URL = QName.createQName(NAMESPACE_URI, "workspaceUrl"); + public static final QName WF_SHARED_LINK_BASE_URL = QName.createQName(NAMESPACE_URI, "sharedLinkBaseUrl"); + public static final QName WF_TEMPLATE_ASSETS_URL = QName.createQName(NAMESPACE_URI, "templateAssetsUrl"); + // workflow execution context variable names public static final String wfVarInviteeUserName = "imwf_inviteeUserName"; public static final String wfVarInviteeRole = "imwf_inviteeRole"; @@ -73,6 +78,10 @@ public interface WorkflowModelModeratedInvitation public static final String wfVarResourceName = "imwf_resourceName"; public static final String wfVarResourceType = "imwf_resourceType"; public static final String wfVarReviewer = "imwf_reviewer"; - public static final String wfVarReviewComments = "imwf_reviewComments"; + public static final String wfVarReviewComments = "imwf_reviewComments"; public static final String bpmGroupAssignee = "bpm_groupAssignee"; + + public static final String wfVarClientName = "imwf_clientName"; + public static final String wfVarWorkspaceUrl = "imwf_workspaceUrl"; + public static final String wfVarTemplateAssetsUrl = "imwf_templateAssetsUrl"; } diff --git a/repository/src/main/java/org/alfresco/repo/invitation/activiti/SendModeratedInviteDelegate.java b/repository/src/main/java/org/alfresco/repo/invitation/activiti/SendModeratedInviteDelegate.java index 6cc9511a80..0eb78612be 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/activiti/SendModeratedInviteDelegate.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/activiti/SendModeratedInviteDelegate.java @@ -23,38 +23,65 @@ * along with Alfresco. If not, see . * #L% */ -package org.alfresco.repo.invitation.activiti; - -import java.util.Map; - -import org.activiti.engine.delegate.DelegateExecution; -import org.alfresco.repo.workflow.activiti.ActivitiConstants; - -/** - * Activiti delegate that is executed when a invitation request has been sent. - * - * @author Constantin Popa - */ -public class SendModeratedInviteDelegate extends AbstractInvitationDelegate +package org.alfresco.repo.invitation.activiti; + +import java.util.Map; + +import org.activiti.engine.delegate.DelegateExecution; +import org.alfresco.repo.client.config.ClientAppConfig; +import org.alfresco.repo.invitation.WorkflowModelModeratedInvitation; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; +import org.alfresco.util.EmailHelper; + +/** + * Activiti delegate that is executed when a invitation request has been sent. + * + * @author Constantin Popa + */ +public class SendModeratedInviteDelegate extends AbstractInvitationDelegate { private String emailTemplatePath; - public static final String ENTERPRISE_EMAIL_TEMPLATE_PATH = "app:company_home/app:dictionary/app:email_templates/cm:invite/cm:invite-email-moderated.html.ftl"; - - public static final String EMAIL_SUBJECT_KEY = - "invitation.moderated.email.subject"; - - + private ClientAppConfig clientAppConfig; + private EmailHelper emailHelper; + public static final String ENTERPRISE_EMAIL_TEMPLATE_PATH = "app:company_home/app:dictionary/app:email_templates/cm:invite/cm:invite-email-moderated.html.ftl"; + + public static final String EMAIL_SUBJECT_KEY = "invitation.moderated.email.subject"; + private static final String EMAIL_TEMPLATE_REF ="alfresco/templates/workspace/invite-email-moderated.html.ftl"; + + public void setEmailTemplatePath(String emailTemplatePath) { this.emailTemplatePath = emailTemplatePath; } - @Override - public void execute(DelegateExecution execution) throws Exception - { - String invitationId = ActivitiConstants.ENGINE_ID + "$" + execution.getProcessInstanceId(); - Map variables = execution.getVariables(); - invitationService.sendModeratedInvitation(invitationId, emailTemplatePath, EMAIL_SUBJECT_KEY, variables); - } -} + public void setClientAppConfig(ClientAppConfig clientAppConfig) + { + this.clientAppConfig = clientAppConfig; + } + + public void setEmailHelper(EmailHelper emailHelper) + { + this.emailHelper = emailHelper; + } + + @Override + public void execute(DelegateExecution execution) throws Exception + { + String invitationId = ActivitiConstants.ENGINE_ID + "$" + execution.getProcessInstanceId(); + Map variables = execution.getVariables(); + String clientName = (String) variables.get(WorkflowModelModeratedInvitation.wfVarClientName); + + ClientAppConfig.ClientApp clientApp = clientAppConfig.getClient(clientName); + if(clientApp != null) + { + final String path = clientApp.getProperty("inviteModeratedTemplatePath"); + final String templatePath = emailHelper.getEmailTemplate(clientApp.getName(), path, EMAIL_TEMPLATE_REF); + invitationService.sendModeratedInvitation(invitationId, templatePath, EMAIL_SUBJECT_KEY, variables); + } + else + { + invitationService.sendModeratedInvitation(invitationId, emailTemplatePath, EMAIL_SUBJECT_KEY, variables); + } + } +} diff --git a/repository/src/main/java/org/alfresco/repo/invitation/site/InviteModeratedSender.java b/repository/src/main/java/org/alfresco/repo/invitation/site/InviteModeratedSender.java index 6a1f20cbe2..3e29916bd4 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/site/InviteModeratedSender.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/site/InviteModeratedSender.java @@ -23,9 +23,9 @@ * along with Alfresco. If not, see . * #L% */ - -package org.alfresco.repo.invitation.site; - + +package org.alfresco.repo.invitation.site; + import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.bpmGroupAssignee; import java.io.Serializable; @@ -47,28 +47,30 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.cmr.security.PersonService.PersonInfo; import org.alfresco.util.ModelUtil; +import org.alfresco.util.UrlUtil; import org.apache.commons.lang3.StringUtils; - -/** - * This class is responsible for sending email notifications to site managers informing about users requesting access. - * - * @author Constantin Popa - */ -public class InviteModeratedSender extends InviteSender -{ + +/** + * This class is responsible for sending email notifications to site managers informing about users requesting access. + * + * @author Constantin Popa + */ +public class InviteModeratedSender extends InviteSender +{ private static final String DATA_DICTIONARY_XPATH_PREFIX = "app:"; public static final String WF_PACKAGE = "wf_package"; - public static final String SHARE_PENDING_INVITES_LINK = "{0}/page/site/{1}/pending-invites"; - + public static final String SHARE_PENDING_INVITES_LINK = "{0}/page/site/{1}/pending-invites"; + public static final String WORKSPACE_PENDING_INVITES_LINK = "{0}/#/{1}/members/libraries"; + private static final List INVITE_MODERATED_EXPECTED_PROPERTIES = Arrays.asList( WorkflowModelModeratedInvitation.wfVarInviteeUserName, WorkflowModelModeratedInvitation.wfVarInviteeRole, WorkflowModelModeratedInvitation.wfVarResourceName, WorkflowModelModeratedInvitation.bpmGroupAssignee, - WorkflowModelModeratedInvitation.wfVarResourceType); - - + WorkflowModelModeratedInvitation.wfVarResourceType); + + public InviteModeratedSender(ServiceRegistry services, Repository repository, MessageService messageService) { super(services, repository, messageService); @@ -107,6 +109,8 @@ public class InviteModeratedSender extends InviteSender model.put("inviteeName", StringUtils.join(new String[] { inviteePerson.getFirstName(), inviteePerson.getLastName() }, " ")); model.put("siteName", getSiteName(properties)); model.put("sharePendingInvitesLink", StringUtils.stripStart(getPendingInvitesLink(properties), "/")); + model.put("workspacePendingInvitesLink", StringUtils.stripStart(getWorkSpaceInvitesLink(properties), "/")); + model.put("template_assets_url", getTemplateAssetsLink(properties)); return model; } @@ -116,6 +120,24 @@ public class InviteModeratedSender extends InviteSender properties.get(WorkflowModelModeratedInvitation.wfVarResourceName)); } + protected String getWorkSpaceInvitesLink(Map properties) + { + String path = properties.get(WorkflowModelModeratedInvitation.wfVarWorkspaceUrl); + boolean hasValidBaseUrl = path != null && !StringUtils.isAllBlank(path) && path.length() > 1; + String workspaceUrl = sysAdminParams.getAlfrescoProtocol() + "://" + sysAdminParams.getAlfrescoHost() + ":" + sysAdminParams.getAlfrescoPort() + + ( hasValidBaseUrl ? "/" + path.trim() : ""); + + return MessageFormat.format(WORKSPACE_PENDING_INVITES_LINK, workspaceUrl, properties.get(WorkflowModelModeratedInvitation.wfVarResourceName)); + } + + protected String getTemplateAssetsLink(Map properties) + { + if (properties.get(WorkflowModelModeratedInvitation.wfVarTemplateAssetsUrl) != null) { + return UrlUtil.replaceAlfrescoUrlPlaceholder(properties.get(WorkflowModelModeratedInvitation.wfVarTemplateAssetsUrl), this.sysAdminParams); + } + return UrlUtil.getAlfrescoUrl(this.sysAdminParams); + } + @Override public List getRequiredProperties() { @@ -126,5 +148,5 @@ public class InviteModeratedSender extends InviteSender protected String getWorkflowPropForSiteName() { return WorkflowModelModeratedInvitation.wfVarResourceName; - } -} + } +} diff --git a/repository/src/main/java/org/alfresco/repo/invitation/site/InviteSender.java b/repository/src/main/java/org/alfresco/repo/invitation/site/InviteSender.java index 1caa5193a7..7d82fab60a 100644 --- a/repository/src/main/java/org/alfresco/repo/invitation/site/InviteSender.java +++ b/repository/src/main/java/org/alfresco/repo/invitation/site/InviteSender.java @@ -1,53 +1,54 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.invitation.site; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; - -import java.io.Serializable; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.repo.i18n.MessageService; -import org.alfresco.repo.model.Repository; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.admin.RepoAdminService; -import org.alfresco.service.cmr.invitation.InvitationException; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -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.alfresco.service.namespace.NamespaceService; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.admin.SysAdminParams; +import org.alfresco.repo.i18n.MessageService; +import org.alfresco.repo.model.Repository; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.admin.RepoAdminService; +import org.alfresco.service.cmr.invitation.InvitationException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +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.alfresco.service.namespace.NamespaceService; /** * Notifies the necessary user(s) of a pending site membership invitation/request. @@ -66,6 +67,7 @@ public abstract class InviteSender protected final FileFolderService fileFolderService; protected final RepoAdminService repoAdminService; protected final NamespaceService namespaceService; + protected final SysAdminParams sysAdminParams; public InviteSender(ServiceRegistry services, Repository repository, MessageService messageService) { @@ -79,6 +81,7 @@ public abstract class InviteSender this.namespaceService = services.getNamespaceService(); this.repository = repository; this.messageService = messageService; + this.sysAdminParams = services.getSysAdminParams(); } /** @@ -88,10 +91,10 @@ public abstract class InviteSender * @param emailSubjectKey the subject of the email * @param properties A Map containing the properties needed to send the email. */ - public abstract void sendMail(String emailTemplateXpath, String emailSubjectKey, Map properties); - - protected abstract Map buildMailTextModel(Map properties); - + public abstract void sendMail(String emailTemplateXpath, String emailSubjectKey, Map properties); + + protected abstract Map buildMailTextModel(Map properties); + protected abstract List getRequiredProperties(); /** @@ -141,8 +144,8 @@ public abstract class InviteSender siteName = siteTitle; } return siteName; - } - - protected abstract String getWorkflowPropForSiteName(); + } + + protected abstract String getWorkflowPropForSiteName(); } diff --git a/repository/src/main/java/org/alfresco/service/cmr/invitation/InvitationService.java b/repository/src/main/java/org/alfresco/service/cmr/invitation/InvitationService.java index 29947ef1f5..6865d469e7 100644 --- a/repository/src/main/java/org/alfresco/service/cmr/invitation/InvitationService.java +++ b/repository/src/main/java/org/alfresco/service/cmr/invitation/InvitationService.java @@ -1,33 +1,33 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.service.cmr.invitation; import java.util.List; import java.util.Map; - + import org.alfresco.service.Auditable; import org.alfresco.service.NotAuditable; @@ -138,6 +138,19 @@ public interface InvitationService @Auditable(parameters = { "inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole" }) public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole); + /** + * Start the invitation process for a ModeratedInvitation + * + * @param inviteeUserName who is to be invited + * @param Invitation.ResourceType resourceType what resource type ? + * @param resourceName which resource + * @param inviteeRole which role ? + * @param clientName which client + * @param workspacePath path of the digital workspace + */ + @Auditable(parameters = { "inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole", "clientName", "workspacePath" }) + public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String clientName, String workspacePath); + /** * Update the invitee comments for an existing moderated invitation * @@ -324,17 +337,17 @@ public interface InvitationService * @return true if emails are sent on invite. */ @NotAuditable - boolean isSendEmails(); - - /** - * - * Sends the site join request notification email using the given template, subject localization key, and variables. - * - * @param invitationId - * @param emailTemplateXpath - * @param emailSubjectKey - * @param variables - */ - @Auditable(parameters = { "inviteId" }) + boolean isSendEmails(); + + /** + * + * Sends the site join request notification email using the given template, subject localization key, and variables. + * + * @param invitationId + * @param emailTemplateXpath + * @param emailSubjectKey + * @param variables + */ + @Auditable(parameters = { "inviteId" }) public void sendModeratedInvitation(String invitationId, String emailTemplateXpath, String emailSubjectKey, Map variables); } diff --git a/repository/src/main/java/org/alfresco/util/UrlUtil.java b/repository/src/main/java/org/alfresco/util/UrlUtil.java index 59c9ff0237..f040c31858 100644 --- a/repository/src/main/java/org/alfresco/util/UrlUtil.java +++ b/repository/src/main/java/org/alfresco/util/UrlUtil.java @@ -39,7 +39,8 @@ public class UrlUtil { // ${shareUrl} placeholder public static final Pattern PATTERN = Pattern.compile("\\$\\{shareUrl\\}"); - + // ${alfrescoUrl} placeholder + public static final Pattern REPO_PATTERN = Pattern.compile("\\$\\{alfrescoUrl\\}"); /** * Builds up the Url to Alfresco based on the settings in the * {@link SysAdminParams}. @@ -113,6 +114,15 @@ public class UrlUtil return value; } + public static String replaceAlfrescoUrlPlaceholder(String value, SysAdminParams sysAdminParams) + { + if (value != null) + { + return REPO_PATTERN.matcher(value).replaceAll(getAlfrescoUrl(sysAdminParams)); + } + return value; + } + protected static String buildUrl(String protocol, String host, int port, String context) { StringBuilder url = new StringBuilder(); diff --git a/repository/src/main/resources/alfresco/invitation-service-context.xml b/repository/src/main/resources/alfresco/invitation-service-context.xml index 5609f946b7..3f889afe67 100644 --- a/repository/src/main/resources/alfresco/invitation-service-context.xml +++ b/repository/src/main/resources/alfresco/invitation-service-context.xml @@ -119,5 +119,7 @@ + + diff --git a/repository/src/main/resources/alfresco/messages/templates-messages.properties b/repository/src/main/resources/alfresco/messages/templates-messages.properties index 3c569ce147..5df386bbad 100644 --- a/repository/src/main/resources/alfresco/messages/templates-messages.properties +++ b/repository/src/main/resources/alfresco/messages/templates-messages.properties @@ -97,3 +97,7 @@ templates.generic-email.ftl.salutation=Hi {0}, templates.generic-email.ftl.copy_right=All Rights Reserved. templates.generic-email.ftl.contact_us=Contact Us +#workspace invite-email-moderated.ftl +templates.workspace.invite-email-moderated.html.call-to-action=Join Request +templates.workspace.invite-email-moderated.html.body=has requested to join +templates.workspace.invite-email-moderated.html.action=Review request \ No newline at end of file diff --git a/repository/src/main/resources/alfresco/templates/workspace/invite-email-moderated.html.ftl b/repository/src/main/resources/alfresco/templates/workspace/invite-email-moderated.html.ftl new file mode 100644 index 0000000000..78fcc45c85 --- /dev/null +++ b/repository/src/main/resources/alfresco/templates/workspace/invite-email-moderated.html.ftl @@ -0,0 +1,121 @@ + + + + + + + +
+
+ + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + +
+ Alfresco +
+ + + + + + +
+

+ Join Request +

+
+
+ + + + + + +
+

+ ${inviteeName} +

+ +

+ ${message("templates.workspace.invite-email-moderated.html.body")} +

+ +

+ ${siteName} +

+ +

+ + + + + + +
+ + ${message("templates.workspace.invite-email-moderated.html.action")} + +
+

+
+
+

+ © 2020 Alfresco Software, Inc. All rights reserved. +

+
+
+
+
+
+ + \ No newline at end of file diff --git a/repository/src/main/resources/alfresco/workflow/invitation-moderated-workflow-model.xml b/repository/src/main/resources/alfresco/workflow/invitation-moderated-workflow-model.xml index 3635efffa9..587340ffa8 100644 --- a/repository/src/main/resources/alfresco/workflow/invitation-moderated-workflow-model.xml +++ b/repository/src/main/resources/alfresco/workflow/invitation-moderated-workflow-model.xml @@ -82,6 +82,9 @@ d:date + + d:text +