Merge pull request #120 from Alfresco/dev-dhrn-ACS-777

[ACS-777] Email notification for digital workspace
This commit is contained in:
Eugenio Romano
2020-11-16 09:24:26 +00:00
committed by GitHub
24 changed files with 959 additions and 426 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -45,15 +45,24 @@ 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
* @return SiteMembershipRequest
*/
SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite, final String client);
/** /**
* 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 +71,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 +79,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 +88,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)
{ {
ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole); ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole, clientName);
SiteMembershipRequest ret = new SiteMembershipRequest(); SiteMembershipRequest ret = new SiteMembershipRequest();
ret.setId(siteId); ret.setId(siteId);
@@ -270,7 +270,76 @@ 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);
}
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)
{
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);
} }
else if(siteVisibility.equals(SiteVisibility.PUBLIC)) else if(siteVisibility.equals(SiteVisibility.PUBLIC))
{ {

View File

@@ -53,6 +53,7 @@ public class SiteMembershipRequest implements Comparable<SiteMembershipRequest>
private Date modifiedAt; private Date modifiedAt;
private String title; // for sorting only private String title; // for sorting only
private Person person; private Person person;
private String client;
public static Pair<String, String> splitId(String id) public static Pair<String, String> splitId(String id)
{ {
@@ -137,11 +138,21 @@ public class SiteMembershipRequest implements Comparable<SiteMembershipRequest>
this.person = person; this.person = person;
} }
public String getClient()
{
return client;
}
public void setClient(String client)
{
this.client = client;
}
@Override @Override
public String toString() public String toString()
{ {
return "SiteMembershipRequest [id=" + id + ", message=" + message + ", createdAt=" + createdAt return "SiteMembershipRequest [id=" + id + ", message=" + message + ", createdAt=" + createdAt
+ ", modifiedAt=" + modifiedAt + "]"; + ", modifiedAt=" + modifiedAt + ", client=" + client + "]";
} }
@Override @Override

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;
if(invite.getClient() != null)
{
siteInvite = siteMembershipRequests.createSiteMembershipRequest(personId, invite, invite.getClient());
} 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 String 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 = (String)props.get(CLIENT_NAME);
} }
/** /**
@@ -122,6 +126,11 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
{ {
return inviteeUserName; return inviteeUserName;
} }
public String 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
* *
@@ -252,8 +261,9 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
PropertyCheck.mandatory(this, "PasswordGenerator", passwordGenerator); PropertyCheck.mandatory(this, "PasswordGenerator", passwordGenerator);
PropertyCheck.mandatory(this, "PolicyComponent", policyComponent); PropertyCheck.mandatory(this, "PolicyComponent", policyComponent);
PropertyCheck.mandatory(this, "templateService", templateService); PropertyCheck.mandatory(this, "templateService", templateService);
PropertyCheck.mandatory(this, "clientAppConfig", clientAppConfig);
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 +1005,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 +1993,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 +2007,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 +2052,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)
{
if (resourceType == Invitation.ResourceType.WEB_SITE)
{
return startModeratedInvite(inviteeComments, inviteeUserName, resourceType, resourceName, inviteeRole, clientName);
}
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)
{
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());
workflowProps.put(WorkflowModelModeratedInvitation.WF_WORKSPACE_URL, client.getProperty("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;
@@ -76,7 +77,8 @@ import org.alfresco.service.namespace.QName;
parentProps.put(RESOURCE_NAME_KEY,(String)props.get(WF_PROP_RESOURCE_NAME)); parentProps.put(RESOURCE_NAME_KEY,(String)props.get(WF_PROP_RESOURCE_NAME));
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, (String)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);
if(clientName != null && clientAppConfig.getClient(clientName) != null)
{
ClientAppConfig.ClientApp clientApp = clientAppConfig.getClient(clientName);
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,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.service.cmr.invitation; package org.alfresco.service.cmr.invitation;
import java.util.Date; import java.util.Date;
@@ -97,4 +97,10 @@ public interface Invitation
Date getCreatedAt(); Date getCreatedAt();
Date getModifiedAt(); Date getModifiedAt();
/**
* Which client to be sent
* @return the clientName
*/
String getClientName();
} }

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,18 @@ 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
*/
@Auditable(parameters = { "inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole", "clientName" })
public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String clientName);
/** /**
* Update the invitee comments for an existing moderated invitation * Update the invitee comments for an existing moderated invitation
* *
@@ -324,17 +336,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

@@ -47,7 +47,6 @@
<import resource="classpath:alfresco/notification-services-context.xml"/> <import resource="classpath:alfresco/notification-services-context.xml"/>
<import resource="classpath:alfresco/activities/activities-feed-context.xml" /> <import resource="classpath:alfresco/activities/activities-feed-context.xml" />
<import resource="classpath:alfresco/tagging-services-context.xml"/> <import resource="classpath:alfresco/tagging-services-context.xml"/>
<import resource="classpath:alfresco/invitation-service-context.xml"/>
<import resource="classpath:alfresco/webdav-context.xml"/> <import resource="classpath:alfresco/webdav-context.xml"/>
<import resource="classpath*:alfresco/patch/*-context.xml" /> <import resource="classpath*:alfresco/patch/*-context.xml" />
<import resource="classpath*:alfresco/dbscripts/*-context.xml" /> <import resource="classpath*:alfresco/dbscripts/*-context.xml" />

View File

@@ -44,4 +44,5 @@
<import resource="classpath*:alfresco/deprecated-model-bootstrap-context.xml" /> <import resource="classpath*:alfresco/deprecated-model-bootstrap-context.xml" />
<import resource="classpath*:alfresco/events-context.xml" /> <import resource="classpath*:alfresco/events-context.xml" />
<import resource="classpath*:alfresco/messaging-context.xml" /> <import resource="classpath*:alfresco/messaging-context.xml" />
<import resource="classpath:alfresco/invitation-service-context.xml"/>
</beans> </beans>

View File

@@ -17,4 +17,9 @@ repo.client-app.share.requestResetPasswordTemplatePath=
# reset password UI page url # reset password UI page url
repo.client-app.share.resetPasswordPageUrl=${shareUrl}/page/reset-password repo.client-app.share.resetPasswordPageUrl=${shareUrl}/page/reset-password
# reset password confirmation email template path # reset password confirmation email template path
repo.client-app.share.confirmResetPasswordTemplatePath= repo.client-app.share.confirmResetPasswordTemplatePath=
### Digital workspace template configurations
repo.client-app.workspace.inviteModeratedTemplatePath=
repo.client-app.workspace.workspaceUrl=workspace
repo.client-app.workspace.templateAssetsUrl=${alfrescoUrl}/images

View File

@@ -33,6 +33,7 @@
<property name="serviceRegistry" ref="ServiceRegistry"/> <property name="serviceRegistry" ref="ServiceRegistry"/>
<property name="repositoryHelper" ref="repositoryHelper"/> <property name="repositoryHelper" ref="repositoryHelper"/>
<property name="messageService" ref="messageService"/> <property name="messageService" ref="messageService"/>
<property name="clientAppConfig" ref="clientAppConfig"/>
</bean> </bean>
<!-- Site service security bean --> <!-- Site service security bean -->
@@ -119,5 +120,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,143 @@
<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 0 0 0">
<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: 60px;" width="100%">
<tbody>
<tr>
<td style="padding-bottom:40px;padding-left:40px;">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td height="30" width="30">
<img src="${template_assets_url}/logo/workspace.png" alt="Alfresco" width="35" height="35" style="border:none;">
</td>
<td align="" valign="center" bgcolor="#FFFFFF">
<span bgcolor="#FFFFFF" style="font-size: 16px;letter-spacing: 0;color: #212328;opacity: 1;padding: 10px;" align="left">
Digital Workspace
</span>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
<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 style="padding-right:40px;padding-bottom:40px;padding-left:40px">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<p style="letter-spacing: 0; color: #707070;font-size: 28px; margin: 0">
Join Request
</p>
</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: 0; color: #707070; display: block; font-weight: bold; font-size: 20px; margin: 0;">
${inviteeName}
</p>
<p style="letter-spacing: 0;color: #707070;margin: 0;font-size: 20px">
${message("templates.workspace.invite-email-moderated.html.body")}
</p>
<p style="letter-spacing: 0;color: #707070;display: block;font-weight: bold;font-size: 20px;margin: 0;">
${siteName}
</p>
<p style="letter-spacing: 0; color: #707070; display: block; margin: 40px 0">
<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: 18px; font-family:Helvetica,Arial,Verdana,sans-serif;font-weight:400;padding: 15px 35px;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>

View File

@@ -65,6 +65,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.test.annotation.Commit; import org.springframework.test.annotation.Commit;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
@@ -202,9 +204,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* end of setup now for some real tests * end of setup now for some real tests
*/ */
/** @Test
*
*/
public void testConfiguration() public void testConfiguration()
{ {
assertNotNull("Invitation service is null", invitationService); assertNotNull("Invitation service is null", invitationService);
@@ -216,6 +216,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* *
* @throws Exception * @throws Exception
*/ */
@Test
public void testInternalUserNotDeletedAfterInviteCancelled() throws Exception public void testInternalUserNotDeletedAfterInviteCancelled() throws Exception
{ {
// Disable our existing User // Disable our existing User
@@ -257,6 +258,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* *
* @throws Exception * @throws Exception
*/ */
@Test
public void testExternalUserDeletedAfterInviteCancelled() throws Exception public void testExternalUserDeletedAfterInviteCancelled() throws Exception
{ {
String inviteeFirstName = PERSON_FIRSTNAME; String inviteeFirstName = PERSON_FIRSTNAME;
@@ -290,6 +292,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* *
* @throws Exception * @throws Exception
*/ */
@Test
public void testNominatedInvitationNewUser() throws Exception public void testNominatedInvitationNewUser() throws Exception
{ {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
@@ -467,6 +470,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* *
* @throws Exception * @throws Exception
*/ */
@Test
public void testNominatedInvitationNewUserReject() throws Exception public void testNominatedInvitationNewUserReject() throws Exception
{ {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
@@ -543,6 +547,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* *
* @throws Exception * @throws Exception
*/ */
@Test
public void testNominatedInvitationNewUserSameEmails() throws Exception public void testNominatedInvitationNewUserSameEmails() throws Exception
{ {
String inviteeAFirstName = "John"; String inviteeAFirstName = "John";
@@ -624,6 +629,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
siteService.removeMembership(resourceName, inviteeBUserName); siteService.removeMembership(resourceName, inviteeBUserName);
} }
@Test
public void testMNT11775() throws Exception public void testMNT11775() throws Exception
{ {
String inviteeUserName = USER_TWO; String inviteeUserName = USER_TWO;
@@ -693,6 +699,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* *
* @throws Exception * @throws Exception
*/ */
@Test
public void test_MNT15614() throws Exception public void test_MNT15614() throws Exception
{ {
String[] siteNames = {"it", "site", "GROUP"}; String[] siteNames = {"it", "site", "GROUP"};
@@ -726,6 +733,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* Test nominated user - new user with whitespace in name. Related to * Test nominated user - new user with whitespace in name. Related to
* ETHREEOH-3030. * ETHREEOH-3030.
*/ */
@Test
public void testNominatedInvitationNewUserWhitespace() throws Exception public void testNominatedInvitationNewUserWhitespace() throws Exception
{ {
String inviteeFirstName = PERSON_FIRSTNAME_SPACES; String inviteeFirstName = PERSON_FIRSTNAME_SPACES;
@@ -919,6 +927,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
siteService.removeMembership(resourceName, inviteeUserName); siteService.removeMembership(resourceName, inviteeUserName);
} }
@Test
public void testNominatedInvitationExistingUser() throws Exception public void testNominatedInvitationExistingUser() throws Exception
{ {
this.invitationServiceImpl.setNominatedInvitationWorkflowId( this.invitationServiceImpl.setNominatedInvitationWorkflowId(
@@ -931,6 +940,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
* moderated invitation Reject the invitation Create a moderated invitation * moderated invitation Reject the invitation Create a moderated invitation
* Approve the invitation * Approve the invitation
*/ */
@Test
public void testModeratedInvitation() public void testModeratedInvitation()
{ {
String inviteeUserName = USER_TWO; String inviteeUserName = USER_TWO;
@@ -1018,9 +1028,90 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
} }
/**
* Create a moderated invitation for workspace client Get it Search for it Cancel it
*/
@Test
public void testWorkspaceModeratedInvitation()
{
String inviteeUserName = USER_TWO;
Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE;
String resourceName = SITE_SHORT_NAME_INVITE;
String inviteeRole = SiteModel.SITE_COLLABORATOR;
String comments = "please sir, let me in!";
this.authenticationComponent.setCurrentUser(USER_TWO);
ModeratedInvitation invitation = invitationService.inviteModerated(comments, inviteeUserName, resourceType,
resourceName, inviteeRole, "workspace");
assertNotNull("moderated invitation is null", invitation);
String inviteId = invitation.getInviteId();
assertEquals("user name wrong", inviteeUserName, invitation.getInviteeUserName());
assertEquals("role name wrong", inviteeRole, invitation.getRoleName());
assertEquals("comments", comments, invitation.getInviteeComments());
assertEquals("resource type name wrong", resourceType, invitation.getResourceType());
assertEquals("resource name wrong", resourceName, invitation.getResourceName());
assertEquals("client name wrong", "workspace", invitation.getClientName());
/**
* Now we have an invitation get it and check the details have been
* returned correctly.
*/
ModeratedInvitation mi2 = (ModeratedInvitation) invitationService.getInvitation(inviteId);
assertEquals("invite id", inviteId, mi2.getInviteId());
assertEquals("user name wrong", inviteeUserName, mi2.getInviteeUserName());
assertEquals("role name wrong", inviteeRole, mi2.getRoleName());
assertEquals("comments", comments, mi2.getInviteeComments());
assertEquals("resource type name wrong", resourceType, mi2.getResourceType());
assertEquals("resource name wrong", resourceName, mi2.getResourceName());
/**
* Search for the new invitation
*/
List<Invitation> invitations = invitationService.listPendingInvitationsForResource(resourceType, resourceName);
assertTrue("invitations is empty", !invitations.isEmpty());
ModeratedInvitation firstInvite = (ModeratedInvitation) invitations.get(0);
assertEquals("invite id wrong", inviteId, firstInvite.getInviteId());
/**
* Cancel the invitation
*/
ModeratedInvitation canceledInvitation = (ModeratedInvitation) invitationService.cancel(inviteId);
assertEquals("invite id wrong", inviteId, canceledInvitation.getInviteId());
assertEquals("comments wrong", comments, canceledInvitation.getInviteeComments());
/**
* Should now be no invitation
*/
List<Invitation> inv2 = invitationService.listPendingInvitationsForResource(resourceType, resourceName);
assertTrue("After cancel invitations is not empty", inv2.isEmpty());
/**
* New invitation
*/
this.authenticationComponent.setCurrentUser(USER_TWO);
ModeratedInvitation invite3 = invitationService.inviteModerated(comments, inviteeUserName, resourceType,
resourceName, inviteeRole);
assertEquals("client name wrong", null, invite3.getClientName());
String thirdInvite = invite3.getInviteId();
this.authenticationComponent.setCurrentUser(USER_MANAGER);
invitationService.approve(thirdInvite, "Welcome in");
/**
* Now verify access control list
*/
String roleName = siteService.getMembersRole(resourceName, inviteeUserName);
assertEquals("role name wrong", inviteeRole, roleName);
siteService.removeMembership(resourceName, inviteeUserName);
}
/** /**
* Test the approval of a moderated invitation * Test the approval of a moderated invitation
*/ */
@Test
public void testModeratedApprove() public void testModeratedApprove()
{ {
String inviteeUserName = USER_TWO; String inviteeUserName = USER_TWO;
@@ -1090,6 +1181,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
/** /**
* Tests of Moderated Reject * Tests of Moderated Reject
*/ */
@Test
public void testModeratedReject() public void testModeratedReject()
{ {
String inviteeUserName = USER_TWO; String inviteeUserName = USER_TWO;
@@ -1148,6 +1240,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
/** /**
* Test search invitation * Test search invitation
*/ */
@Test
public void testSearchInvitation() public void testSearchInvitation()
{ {
/** /**
@@ -1240,6 +1333,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
/** /**
* test that the search limiter works * test that the search limiter works
*/ */
@Test
public void testSearchInvitationWithLimit() throws Exception public void testSearchInvitationWithLimit() throws Exception
{ {
Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE;
@@ -1282,6 +1376,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
/** /**
* MNT-17341 : External users with Manager role cannot invite other external users to the site because site invitation accept fails * MNT-17341 : External users with Manager role cannot invite other external users to the site because site invitation accept fails
*/ */
@Test
public void testExternalUserManagerInvitingAnotherExternalUser() throws Exception{ public void testExternalUserManagerInvitingAnotherExternalUser() throws Exception{
String inviteeFirstName = PERSON_FIRSTNAME; String inviteeFirstName = PERSON_FIRSTNAME;
String inviteeLastName = PERSON_LASTNAME; String inviteeLastName = PERSON_LASTNAME;
@@ -1334,6 +1429,8 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
} }
@Ignore
@Test
@Commit @Commit
public void disabled_test100Invites() throws Exception public void disabled_test100Invites() throws Exception
{ {
@@ -1367,6 +1464,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri
assertEquals(invite.getInviteId(), results.get(0).getInviteId()); assertEquals(invite.getInviteId(), results.get(0).getInviteId());
} }
@Test
public void testGetInvitation() public void testGetInvitation()
{ {
try try

View File

@@ -44,6 +44,8 @@ import junit.framework.TestCase;
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.SysAdminParamsImpl;
import org.alfresco.repo.i18n.MessageService; import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.invitation.WorkflowModelModeratedInvitation; import org.alfresco.repo.invitation.WorkflowModelModeratedInvitation;
import org.alfresco.repo.invitation.activiti.SendModeratedInviteDelegate; import org.alfresco.repo.invitation.activiti.SendModeratedInviteDelegate;
@@ -175,6 +177,7 @@ public class InviteModeratedSenderTest extends TestCase
SearchService mockSearchService = mockSearchService(); SearchService mockSearchService = mockSearchService();
SiteService mockSiteService = mockSiteService(); SiteService mockSiteService = mockSiteService();
FileFolderService mockFileFolderService = mockFileFolderService(); FileFolderService mockFileFolderService = mockFileFolderService();
SysAdminParams sysAdminParams = new SysAdminParamsImpl();
ServiceRegistry services = mock(ServiceRegistry.class); ServiceRegistry services = mock(ServiceRegistry.class);
when(services.getActionService()).thenReturn(mockActionService); when(services.getActionService()).thenReturn(mockActionService);
@@ -183,6 +186,7 @@ public class InviteModeratedSenderTest extends TestCase
when(services.getSearchService()).thenReturn(mockSearchService); when(services.getSearchService()).thenReturn(mockSearchService);
when(services.getSiteService()).thenReturn(mockSiteService); when(services.getSiteService()).thenReturn(mockSiteService);
when(services.getFileFolderService()).thenReturn(mockFileFolderService); when(services.getFileFolderService()).thenReturn(mockFileFolderService);
when(services.getSysAdminParams()).thenReturn(sysAdminParams);
return services; return services;
} }