[ACS-777] Email notification for digital workspace

This commit is contained in:
dhrn
2020-11-03 15:03:43 +05:30
parent 8bf87153bf
commit 2933d45eff
17 changed files with 778 additions and 393 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -45,15 +45,25 @@ public interface SiteMembershipRequests
/** /**
* Create a site membership request for the user 'inviteeId' * 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 * @param siteInvite the site invite
* @return SiteMembershipRequest * @return SiteMembershipRequest
*/ */
SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite); 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 * 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 * @param siteInvite the site invite
* @return the updated siteMembershipRequest * @return the updated siteMembershipRequest
*/ */
@@ -62,7 +72,7 @@ public interface SiteMembershipRequests
/** /**
* Cancel site membership request for invitee and site. * 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 * @param siteId the site id
*/ */
void cancelSiteMembershipRequest(String inviteeId, String siteId); 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. * 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 * @param siteId the site id
* @return the site membership request * @return the site membership request
*/ */
@@ -79,7 +89,7 @@ public interface SiteMembershipRequests
/** /**
* Get a paged list of site membership requests for inviteeId. * 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 * @param paging paging information
* @return a paged list of site membership requests * @return a paged list of site membership requests
*/ */

View File

@@ -158,9 +158,9 @@ public class SiteMembershipRequestsImpl implements SiteMembershipRequests
} }
private SiteMembershipRequest inviteToModeratedSite(final String message, final String inviteeId, final String siteId, 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(); SiteMembershipRequest ret = new SiteMembershipRequest();
ret.setId(siteId); ret.setId(siteId);
@@ -270,7 +270,74 @@ public class SiteMembershipRequestsImpl implements SiteMembershipRequests
if(siteVisibility.equals(SiteVisibility.MODERATED)) 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)) else if(siteVisibility.equals(SiteVisibility.PUBLIC))
{ {

View File

@@ -1,28 +1,28 @@
/* /*
* #%L * #%L
* Alfresco Remote API * Alfresco Remote API
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.rest.api.people; package org.alfresco.rest.api.people;
import java.util.ArrayList; import java.util.ArrayList;
@@ -73,7 +73,14 @@ RelationshipResourceAction.Create<SiteMembershipRequest>, RelationshipResourceAc
List<SiteMembershipRequest> result = new ArrayList<SiteMembershipRequest>(invites.size()); List<SiteMembershipRequest> result = new ArrayList<SiteMembershipRequest>(invites.size());
for(SiteMembershipRequest invite : invites) 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); result.add(siteInvite);
} }
return result; return result;

View File

@@ -1,28 +1,28 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation; package org.alfresco.repo.invitation;
import java.io.Serializable; 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 ROLE_KEY = "role";
public static final String CREATED_AT = "createdAt"; public static final String CREATED_AT = "createdAt";
public static final String MODIFIED_AT = "modifiedAt"; public static final String MODIFIED_AT = "modifiedAt";
public static final String CLIENT_NAME = "clientName";
/** /**
* Unique reference for this invitation * Unique reference for this invitation
@@ -72,6 +73,8 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
private final Date modifiedAt; private final Date modifiedAt;
private final Date clientName;
public InvitationImpl(Map<String, Serializable> props) public InvitationImpl(Map<String, Serializable> props)
{ {
this.inviteId = (String)props.get(ID_KEY); 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.resourceType = type==null ? ResourceType.WEB_SITE : ResourceType.valueOf(type);
this.createdAt = (Date)props.get(CREATED_AT); this.createdAt = (Date)props.get(CREATED_AT);
this.modifiedAt = (Date)props.get(MODIFIED_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; return inviteeUserName;
} }
public Date getClientName()
{
return clientName;
}
public abstract InvitationType getInvitationType(); public abstract InvitationType getInvitationType();
} }

View File

@@ -1,119 +1,120 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation; package org.alfresco.repo.invitation;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarAcceptUrl; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarAcceptUrl;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteTicket; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteTicket;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeGenPassword; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeGenPassword;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeUserName; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeUserName;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviterUserName; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviterUserName;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRejectUrl; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRejectUrl;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRole; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRole;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter; import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.admin.SysAdminParams; import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.i18n.MessageService; import org.alfresco.repo.client.config.ClientAppConfig;
import org.alfresco.repo.invitation.activiti.SendNominatedInviteDelegate; import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.invitation.site.InviteModeratedSender; import org.alfresco.repo.invitation.activiti.SendNominatedInviteDelegate;
import org.alfresco.repo.invitation.site.InviteNominatedSender; import org.alfresco.repo.invitation.site.InviteModeratedSender;
import org.alfresco.repo.invitation.site.InviteSender; import org.alfresco.repo.invitation.site.InviteNominatedSender;
import org.alfresco.repo.jscript.ScriptNode; import org.alfresco.repo.invitation.site.InviteSender;
import org.alfresco.repo.model.Repository; import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.model.Repository;
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy; import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.PasswordGenerator; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.authentication.UserNameGenerator; import org.alfresco.repo.security.authentication.PasswordGenerator;
import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.security.authentication.UserNameGenerator;
import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.repo.site.SiteModel;
import org.alfresco.repo.workflow.CancelWorkflowActionExecuter; import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.repo.workflow.CancelWorkflowActionExecuter;
import org.alfresco.repo.workflow.activiti.ActivitiConstants; import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.ServiceRegistry; import org.alfresco.repo.workflow.activiti.ActivitiConstants;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.invitation.Invitation.ResourceType; import org.alfresco.service.cmr.invitation.Invitation;
import org.alfresco.service.cmr.invitation.InvitationException; import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; import org.alfresco.service.cmr.invitation.InvitationException;
import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden;
import org.alfresco.service.cmr.invitation.InvitationExceptionUserError; import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound;
import org.alfresco.service.cmr.invitation.InvitationSearchCriteria; import org.alfresco.service.cmr.invitation.InvitationExceptionUserError;
import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; import org.alfresco.service.cmr.invitation.InvitationSearchCriteria;
import org.alfresco.service.cmr.invitation.InvitationService; import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType;
import org.alfresco.service.cmr.invitation.ModeratedInvitation; import org.alfresco.service.cmr.invitation.InvitationService;
import org.alfresco.service.cmr.invitation.NominatedInvitation; import org.alfresco.service.cmr.invitation.ModeratedInvitation;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.invitation.NominatedInvitation;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.workflow.WorkflowAdminService; import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowAdminService;
import org.alfresco.service.cmr.workflow.WorkflowException; import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowPath; import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowTask; import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery; import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.GUID; import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.GUID;
import org.alfresco.util.UrlUtil; import org.alfresco.util.PropertyCheck;
import org.alfresco.util.collections.CollectionUtils; import org.alfresco.util.UrlUtil;
import org.alfresco.util.collections.Function; import org.alfresco.util.collections.CollectionUtils;
import org.apache.commons.logging.Log; import org.alfresco.util.collections.Function;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log;
import org.springframework.extensions.surf.util.I18NUtil; import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* Implementation of invitation service. * Implementation of invitation service.
@@ -138,14 +139,16 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
wfVarServerPath,// wfVarServerPath,//
wfVarAcceptUrl,// wfVarAcceptUrl,//
wfVarRejectUrl, wfVarRejectUrl,
InviteNominatedSender.WF_INSTANCE_ID); InviteNominatedSender.WF_INSTANCE_ID);
private static final List<String> SEND_INVITE_MODERATED_PROP_NAMES = Arrays.asList( private static final List<String> SEND_INVITE_MODERATED_PROP_NAMES = Arrays.asList(
WorkflowModelModeratedInvitation.wfVarInviteeUserName, WorkflowModelModeratedInvitation.wfVarInviteeUserName,
WorkflowModelModeratedInvitation.wfVarInviteeRole, WorkflowModelModeratedInvitation.wfVarInviteeRole,
WorkflowModelModeratedInvitation.wfVarResourceName, WorkflowModelModeratedInvitation.wfVarResourceName,
WorkflowModelModeratedInvitation.bpmGroupAssignee, WorkflowModelModeratedInvitation.bpmGroupAssignee,
WorkflowModelModeratedInvitation.wfVarResourceType); WorkflowModelModeratedInvitation.wfVarResourceType,
WorkflowModelModeratedInvitation.wfVarTemplateAssetsUrl,
WorkflowModelModeratedInvitation.wfVarWorkspaceUrl);
/** /**
@@ -170,8 +173,9 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
private Repository repositoryHelper; private Repository repositoryHelper;
private ServiceRegistry serviceRegistry; private ServiceRegistry serviceRegistry;
private MessageService messageService; private MessageService messageService;
private InviteNominatedSender inviteNominatedSender; private InviteNominatedSender inviteNominatedSender;
private InviteModeratedSender inviteModeratedSender; private InviteModeratedSender inviteModeratedSender;
private ClientAppConfig clientAppConfig;
// maximum number of tries to generate a invitee user name which // maximum number of tries to generate a invitee user name which
// does not already belong to an existing person // does not already belong to an existing person
@@ -194,6 +198,11 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
private String moderatedInvitationWorkflowId = private String moderatedInvitationWorkflowId =
WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI;
public void setClientAppConfig(ClientAppConfig clientAppConfig)
{
this.clientAppConfig = clientAppConfig;
}
/** /**
* Set the policy component * Set the policy component
* *
@@ -253,7 +262,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
PropertyCheck.mandatory(this, "PolicyComponent", policyComponent); PropertyCheck.mandatory(this, "PolicyComponent", policyComponent);
PropertyCheck.mandatory(this, "templateService", templateService); 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); 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.setTaskName(WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK);
// query for invite workflow tasks // query for invite workflow tasks
List<WorkflowTask> results = new ArrayList<WorkflowTask>(); List<WorkflowTask> results = new ArrayList<WorkflowTask>();
if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID))
{ {
query.setTaskName(WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK); query.setTaskName(WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK);
@@ -1983,10 +1992,10 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
String emailSubjectKey, Map<String, Object> executionVariables) String emailSubjectKey, Map<String, Object> executionVariables)
{ {
sendInviteEmail(inviteNominatedSender, SEND_INVITE_NOMINATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables); sendInviteEmail(inviteNominatedSender, SEND_INVITE_NOMINATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables);
} }
private void sendInviteEmail(InviteSender inviteSender, List<String> invitePropNames, String inviteId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> executionVariables) private void sendInviteEmail(InviteSender inviteSender, List<String> invitePropNames, String inviteId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> executionVariables)
{ {
if (isSendEmails()) if (isSendEmails())
{ {
Map<String, String> properties = makePropertiesFromContextVariables(executionVariables, invitePropNames); Map<String, String> properties = makePropertiesFromContextVariables(executionVariables, invitePropNames);
@@ -1997,23 +2006,23 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
properties.put(InviteNominatedSender.WF_INSTANCE_ID, inviteId); properties.put(InviteNominatedSender.WF_INSTANCE_ID, inviteId);
inviteSender.sendMail(emailTemplateXpath, emailSubjectKey, properties); inviteSender.sendMail(emailTemplateXpath, emailSubjectKey, properties);
} }
} }
@Override @Override
public void sendModeratedInvitation(String inviteId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> executionVariables) public void sendModeratedInvitation(String inviteId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> executionVariables)
{ {
sendInviteEmail(inviteModeratedSender, SEND_INVITE_MODERATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables); sendInviteEmail(inviteModeratedSender, SEND_INVITE_MODERATED_PROP_NAMES, inviteId, emailTemplateXpath, emailSubjectKey, executionVariables);
} }
private String getPackageRef(Map<String, Object> executionVariables) private String getPackageRef(Map<String, Object> executionVariables)
{ {
String packageName = WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService).replace(":", "_"); String packageName = WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService).replace(":", "_");
ScriptNode packageNode = (ScriptNode) executionVariables.get(packageName); ScriptNode packageNode = (ScriptNode) executionVariables.get(packageName);
String packageRef = packageNode.getNodeRef().toString(); String packageRef = packageNode.getNodeRef().toString();
return packageRef; return packageRef;
} }
@Override @Override
@@ -2042,4 +2051,71 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
{ {
return CollectionUtils.filterKeys((Map<String, String>) executionVariables, CollectionUtils.containsFilter(propertyNames)); return CollectionUtils.filterKeys((Map<String, String>) 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<QName, Serializable> workflowProps = new HashMap<QName, Serializable>(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);
}
} }

View File

@@ -1,28 +1,28 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation; package org.alfresco.repo.invitation;
import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS; 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_MODIFIED_AT;
import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME; 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_RESOURCE_TYPE;
import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_CLIENT_NAME;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; 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(RESOURCE_TYPE_KEY,(String)props.get(WF_PROP_RESOURCE_TYPE));
parentProps.put(CREATED_AT,(Date)props.get(ContentModel.PROP_CREATED)); parentProps.put(CREATED_AT,(Date)props.get(ContentModel.PROP_CREATED));
parentProps.put(MODIFIED_AT,(Date)props.get(WF_PROP_MODIFIED_AT)); parentProps.put(MODIFIED_AT,(Date)props.get(WF_PROP_MODIFIED_AT));
parentProps.put(CLIENT_NAME,(Date)props.get(WF_PROP_CLIENT_NAME));
return parentProps; return parentProps;
} }

View File

@@ -1,28 +1,28 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation; package org.alfresco.repo.invitation;
import org.alfresco.service.namespace.NamespaceService; 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_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_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 // workflow execution context variable names
public static final String wfVarInviteeUserName = "imwf_inviteeUserName"; public static final String wfVarInviteeUserName = "imwf_inviteeUserName";
public static final String wfVarInviteeRole = "imwf_inviteeRole"; 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 wfVarResourceName = "imwf_resourceName";
public static final String wfVarResourceType = "imwf_resourceType"; public static final String wfVarResourceType = "imwf_resourceType";
public static final String wfVarReviewer = "imwf_reviewer"; 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 bpmGroupAssignee = "bpm_groupAssignee";
public static final String wfVarClientName = "imwf_clientName";
public static final String wfVarWorkspaceUrl = "imwf_workspaceUrl";
public static final String wfVarTemplateAssetsUrl = "imwf_templateAssetsUrl";
} }

View File

@@ -23,38 +23,65 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation.activiti; package org.alfresco.repo.invitation.activiti;
import java.util.Map; import java.util.Map;
import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.DelegateExecution;
import org.alfresco.repo.workflow.activiti.ActivitiConstants; import org.alfresco.repo.client.config.ClientAppConfig;
import org.alfresco.repo.invitation.WorkflowModelModeratedInvitation;
/** import org.alfresco.repo.workflow.activiti.ActivitiConstants;
* Activiti delegate that is executed when a invitation request has been sent. import org.alfresco.util.EmailHelper;
*
* @author Constantin Popa /**
*/ * Activiti delegate that is executed when a invitation request has been sent.
public class SendModeratedInviteDelegate extends AbstractInvitationDelegate *
* @author Constantin Popa
*/
public class SendModeratedInviteDelegate extends AbstractInvitationDelegate
{ {
private String emailTemplatePath; 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"; private ClientAppConfig clientAppConfig;
private EmailHelper emailHelper;
public static final String EMAIL_SUBJECT_KEY = public static final String ENTERPRISE_EMAIL_TEMPLATE_PATH = "app:company_home/app:dictionary/app:email_templates/cm:invite/cm:invite-email-moderated.html.ftl";
"invitation.moderated.email.subject";
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) public void setEmailTemplatePath(String emailTemplatePath)
{ {
this.emailTemplatePath = emailTemplatePath; this.emailTemplatePath = emailTemplatePath;
} }
@Override public void setClientAppConfig(ClientAppConfig clientAppConfig)
public void execute(DelegateExecution execution) throws Exception {
{ this.clientAppConfig = clientAppConfig;
String invitationId = ActivitiConstants.ENGINE_ID + "$" + execution.getProcessInstanceId(); }
Map<String, Object> variables = execution.getVariables();
invitationService.sendModeratedInvitation(invitationId, emailTemplatePath, EMAIL_SUBJECT_KEY, variables); public void setEmailHelper(EmailHelper emailHelper)
} {
} this.emailHelper = emailHelper;
}
@Override
public void execute(DelegateExecution execution) throws Exception
{
String invitationId = ActivitiConstants.ENGINE_ID + "$" + execution.getProcessInstanceId();
Map<String, Object> 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);
}
}
}

View File

@@ -23,9 +23,9 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation.site; package org.alfresco.repo.invitation.site;
import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.bpmGroupAssignee; import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.bpmGroupAssignee;
import java.io.Serializable; 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.repository.TemplateService;
import org.alfresco.service.cmr.security.PersonService.PersonInfo; import org.alfresco.service.cmr.security.PersonService.PersonInfo;
import org.alfresco.util.ModelUtil; import org.alfresco.util.ModelUtil;
import org.alfresco.util.UrlUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
/** /**
* This class is responsible for sending email notifications to site managers informing about users requesting access. * This class is responsible for sending email notifications to site managers informing about users requesting access.
* *
* @author Constantin Popa * @author Constantin Popa
*/ */
public class InviteModeratedSender extends InviteSender public class InviteModeratedSender extends InviteSender
{ {
private static final String DATA_DICTIONARY_XPATH_PREFIX = "app:"; private static final String DATA_DICTIONARY_XPATH_PREFIX = "app:";
public static final String WF_PACKAGE = "wf_package"; 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<String> INVITE_MODERATED_EXPECTED_PROPERTIES = Arrays.asList( private static final List<String> INVITE_MODERATED_EXPECTED_PROPERTIES = Arrays.asList(
WorkflowModelModeratedInvitation.wfVarInviteeUserName, WorkflowModelModeratedInvitation.wfVarInviteeUserName,
WorkflowModelModeratedInvitation.wfVarInviteeRole, WorkflowModelModeratedInvitation.wfVarInviteeRole,
WorkflowModelModeratedInvitation.wfVarResourceName, WorkflowModelModeratedInvitation.wfVarResourceName,
WorkflowModelModeratedInvitation.bpmGroupAssignee, WorkflowModelModeratedInvitation.bpmGroupAssignee,
WorkflowModelModeratedInvitation.wfVarResourceType); WorkflowModelModeratedInvitation.wfVarResourceType);
public InviteModeratedSender(ServiceRegistry services, Repository repository, MessageService messageService) public InviteModeratedSender(ServiceRegistry services, Repository repository, MessageService messageService)
{ {
super(services, repository, 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("inviteeName", StringUtils.join(new String[] { inviteePerson.getFirstName(), inviteePerson.getLastName() }, " "));
model.put("siteName", getSiteName(properties)); model.put("siteName", getSiteName(properties));
model.put("sharePendingInvitesLink", StringUtils.stripStart(getPendingInvitesLink(properties), "/")); model.put("sharePendingInvitesLink", StringUtils.stripStart(getPendingInvitesLink(properties), "/"));
model.put("workspacePendingInvitesLink", StringUtils.stripStart(getWorkSpaceInvitesLink(properties), "/"));
model.put("template_assets_url", getTemplateAssetsLink(properties));
return model; return model;
} }
@@ -116,6 +120,24 @@ public class InviteModeratedSender extends InviteSender
properties.get(WorkflowModelModeratedInvitation.wfVarResourceName)); properties.get(WorkflowModelModeratedInvitation.wfVarResourceName));
} }
protected String getWorkSpaceInvitesLink(Map<String, String> 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<String, String> properties)
{
if (properties.get(WorkflowModelModeratedInvitation.wfVarTemplateAssetsUrl) != null) {
return UrlUtil.replaceAlfrescoUrlPlaceholder(properties.get(WorkflowModelModeratedInvitation.wfVarTemplateAssetsUrl), this.sysAdminParams);
}
return UrlUtil.getAlfrescoUrl(this.sysAdminParams);
}
@Override @Override
public List<String> getRequiredProperties() public List<String> getRequiredProperties()
{ {
@@ -126,5 +148,5 @@ public class InviteModeratedSender extends InviteSender
protected String getWorkflowPropForSiteName() protected String getWorkflowPropForSiteName()
{ {
return WorkflowModelModeratedInvitation.wfVarResourceName; return WorkflowModelModeratedInvitation.wfVarResourceName;
} }
} }

View File

@@ -1,53 +1,54 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.invitation.site; package org.alfresco.repo.invitation.site;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName;
import java.io.Serializable; import java.io.Serializable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.repo.i18n.MessageService; import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.model.Repository; import org.alfresco.repo.i18n.MessageService;
import org.alfresco.service.ServiceRegistry; import org.alfresco.repo.model.Repository;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.invitation.InvitationException; import org.alfresco.service.cmr.admin.RepoAdminService;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.invitation.InvitationException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.namespace.NamespaceService; 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. * 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 FileFolderService fileFolderService;
protected final RepoAdminService repoAdminService; protected final RepoAdminService repoAdminService;
protected final NamespaceService namespaceService; protected final NamespaceService namespaceService;
protected final SysAdminParams sysAdminParams;
public InviteSender(ServiceRegistry services, Repository repository, MessageService messageService) public InviteSender(ServiceRegistry services, Repository repository, MessageService messageService)
{ {
@@ -79,6 +81,7 @@ public abstract class InviteSender
this.namespaceService = services.getNamespaceService(); this.namespaceService = services.getNamespaceService();
this.repository = repository; this.repository = repository;
this.messageService = messageService; this.messageService = messageService;
this.sysAdminParams = services.getSysAdminParams();
} }
/** /**
@@ -88,10 +91,10 @@ public abstract class InviteSender
* @param emailSubjectKey the subject of the email * @param emailSubjectKey the subject of the email
* @param properties A Map containing the properties needed to send the email. * @param properties A Map containing the properties needed to send the email.
*/ */
public abstract void sendMail(String emailTemplateXpath, String emailSubjectKey, Map<String, String> properties); public abstract void sendMail(String emailTemplateXpath, String emailSubjectKey, Map<String, String> properties);
protected abstract Map<String, Serializable> buildMailTextModel(Map<String, String> properties); protected abstract Map<String, Serializable> buildMailTextModel(Map<String, String> properties);
protected abstract List<String> getRequiredProperties(); protected abstract List<String> getRequiredProperties();
/** /**
@@ -141,8 +144,8 @@ public abstract class InviteSender
siteName = siteTitle; siteName = siteTitle;
} }
return siteName; return siteName;
} }
protected abstract String getWorkflowPropForSiteName(); protected abstract String getWorkflowPropForSiteName();
} }

View File

@@ -1,33 +1,33 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2016 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.service.cmr.invitation; package org.alfresco.service.cmr.invitation;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.service.Auditable; import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable; import org.alfresco.service.NotAuditable;
@@ -138,6 +138,19 @@ public interface InvitationService
@Auditable(parameters = { "inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole" }) @Auditable(parameters = { "inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole" })
public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String 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 * Update the invitee comments for an existing moderated invitation
* *
@@ -324,17 +337,17 @@ public interface InvitationService
* @return true if emails are sent on invite. * @return true if emails are sent on invite.
*/ */
@NotAuditable @NotAuditable
boolean isSendEmails(); boolean isSendEmails();
/** /**
* *
* Sends the site join request notification email using the given template, subject localization key, and variables. * Sends the site join request notification email using the given template, subject localization key, and variables.
* *
* @param invitationId * @param invitationId
* @param emailTemplateXpath * @param emailTemplateXpath
* @param emailSubjectKey * @param emailSubjectKey
* @param variables * @param variables
*/ */
@Auditable(parameters = { "inviteId" }) @Auditable(parameters = { "inviteId" })
public void sendModeratedInvitation(String invitationId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> variables); public void sendModeratedInvitation(String invitationId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> variables);
} }

View File

@@ -39,7 +39,8 @@ public class UrlUtil
{ {
// ${shareUrl} placeholder // ${shareUrl} placeholder
public static final Pattern PATTERN = Pattern.compile("\\$\\{shareUrl\\}"); 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 * Builds up the Url to Alfresco based on the settings in the
* {@link SysAdminParams}. * {@link SysAdminParams}.
@@ -113,6 +114,15 @@ public class UrlUtil
return value; 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) protected static String buildUrl(String protocol, String host, int port, String context)
{ {
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();

View File

@@ -119,5 +119,7 @@
<property name="emailTemplatePath"> <property name="emailTemplatePath">
<util:constant static-field="org.alfresco.repo.invitation.activiti.SendModeratedInviteDelegate.ENTERPRISE_EMAIL_TEMPLATE_PATH"/> <util:constant static-field="org.alfresco.repo.invitation.activiti.SendModeratedInviteDelegate.ENTERPRISE_EMAIL_TEMPLATE_PATH"/>
</property> </property>
<property name="clientAppConfig" ref="clientAppConfig"/>
<property name="emailHelper" ref="emailHelper"/>
</bean> </bean>
</beans> </beans>

View File

@@ -97,3 +97,7 @@ templates.generic-email.ftl.salutation=Hi {0},
templates.generic-email.ftl.copy_right=All Rights Reserved. templates.generic-email.ftl.copy_right=All Rights Reserved.
templates.generic-email.ftl.contact_us=Contact Us 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

View File

@@ -0,0 +1,121 @@
<html>
<head>
<style type="text/css">
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
width: 100% ! important;
height: 100% !important;
color: #727174;
font-weight: 400;
font-size: 18px;
margin: 0;
}
</style>
</head>
<body>
<div bgcolor="transparent">
<center>
<table align="center" bgcolor="transparent" border="0" cellpadding="0" cellspacing="0" height="100%"
width="100%">
<tbody>
<tr>
<td align="center" valign="top" style="padding-bottom:60px">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="padding: 25px;">
<tbody>
<tr>
<td align="center" valign="top">
<table align="center" bgcolor="#FFFFFF" border="0" cellpadding="0"
cellspacing="0"
style="background-color:#ffffff;max-width: 600px;max-height: 600px;"
width="100%">
<tbody>
<tr>
<td align="" valign="top" bgcolor="#FFFFFF"
style="padding: 40px;">
<img style="border:none; display:block; border-collapse:collapse; outline:none; text-decoration:none;"
src="${template_assets_url}/logo/workspace.png" border="0"
alt="Alfresco" width="180" height="36">
</td>
</tr>
<tr>
<td style="padding-right:40px;padding-bottom:30px;padding-left:40px">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<h3 style="letter-spacing: 0; color: #707070;font-size: 20px; margin: 0">
Join Request
</h3>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td style="padding-right:40px;padding-bottom:10px;padding-left:40px">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<p style="letter-spacing: 0px; color: #707070; display: block; font-weight: bold; font-size: 1.17em; margin: 0; ">
${inviteeName}
</p>
<p style="letter-spacing: 0px; color: #707070;">
${message("templates.workspace.invite-email-moderated.html.body")}
</p>
<p style="letter-spacing: 0px; color: #707070; display: block; font-weight: bold; font-size: 1.17em; ">
${siteName}
</p>
<p style="letter-spacing: 0px; color: #707070; display: block;">
<table bgcolor="#FFFFFF" border="0"
cellpadding="0" cellspacing="0"
style="background: #2A7DE1 0 0 no-repeat padding-box;border-radius: 5px;color: #FFFFFF;">
<tbody>
<tr>
<td>
<a href="${workspacePendingInvitesLink}"
style="color:#ffffff;display:inline-block;border-radius: 5px;font-size:16px;font-family:Helvetica,Arial,Verdana,sans-serif;font-weight:400;padding: 10px;text-decoration:none;"
target="_blank"
data-saferedirecturl="${workspacePendingInvitesLink}">
${message("templates.workspace.invite-email-moderated.html.action")}
</a>
</td>
</tr>
</tbody>
</table>
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-top:2px solid #efeeea;color:#6a655f;font-family:Helvetica,Arial,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:24px;padding-top:40px;padding-bottom:40px;text-align:center">
<p style="color:#6a655f;font-family:Helvetica,Arial,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:24px;padding:0 20px;margin:0;text-align:center">
© 2020 Alfresco Software, Inc. All rights reserved.
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</center>
</div>
</body>
</html>

View File

@@ -82,6 +82,9 @@
<property name="imwf:modifiedAt"> <property name="imwf:modifiedAt">
<type>d:date</type> <type>d:date</type>
</property> </property>
<property name="imwf:clientName">
<type>d:text</type>
</property>
</properties> </properties>
</aspect> </aspect>
</aspects> </aspects>