/**
* Koya is an alfresco module that provides a corporate orientated dataroom.
*
* Copyright (C) Itl Developpement 2014
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see `<http://www.gnu.org/licenses/>`.
*/
package fr.itldev.koya.webscript.invitation;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.invitation.WorkflowModelNominatedInvitation;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.activities.ActivityService;
import org.alfresco.service.cmr.invitation.InvitationService;
import org.alfresco.service.cmr.invitation.NominatedInvitation;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.namespace.QName;
import org.apache.log4j.Logger;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import fr.itldev.koya.action.notification.AfterValidateInvitePostActivityActionExecuter;
import fr.itldev.koya.alfservice.UserService;
import fr.itldev.koya.exception.KoyaServiceException;
import fr.itldev.koya.model.exceptions.KoyaErrorCodes;
import fr.itldev.koya.model.impl.User;
import fr.itldev.koya.webscript.KoyaWebscript;
/**
* Validate User invitation.
*
*
*/
public class ValidateInvitation extends AbstractWebScript {
private Logger logger = Logger.getLogger(this.getClass());
private UserService userService;
private InvitationService invitationService;
private WorkflowService workflowService;
protected ActivityService activityService;
protected ActionService actionService;
protected SiteService siteService;
// <editor-fold defaultstate="collapsed" desc="Getters/Setters">
public void setUserService(UserService userService) {
this.userService = userService;
}
public void setInvitationService(InvitationService invitationService) {
this.invitationService = invitationService;
}
public void setWorkflowService(WorkflowService workflowService) {
this.workflowService = workflowService;
}
public void setActivityService(ActivityService activityService) {
this.activityService = activityService;
}
public void setActionService(ActionService actionService) {
this.actionService = actionService;
}
public void setSiteService(SiteService siteService) {
this.siteService = siteService;
}
// </editor-fold>
@Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
Map<String, Object> jsonPostMap = KoyaWebscript.getJsonMap(req);
final String invitationId = (String) jsonPostMap.get("inviteId");
final String inviteTicket = (String) jsonPostMap.get("inviteTicket");
final String newPassword = (String) jsonPostMap.get("password");
final Boolean userEnabled = Boolean.valueOf((String) jsonPostMap.get("userEnabled"));
final User userInvited = new User();
userInvited.setName((String) jsonPostMap.get("lastName"));
userInvited.setFirstName((String) jsonPostMap.get("firstName"));
userInvited.setCivilTitle((String) jsonPostMap.get("civilTitle"));
try {
final NominatedInvitation invitation;
try {
invitation = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<NominatedInvitation>() {
@Override
public NominatedInvitation doWork() throws Exception {
try {
return (NominatedInvitation) invitationService.getInvitation(invitationId);
} catch (Exception ex) {
logger.error("Error getting invitation from invitationId : " + ex.toString());
throw ex;
}
}
});
} catch (RuntimeException rex) {
throw new KoyaServiceException(KoyaErrorCodes.INVALID_INVITATION_ID);
}
WorkflowTask startTask;
try {
startTask = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<WorkflowTask>() {
@Override
public WorkflowTask doWork() throws Exception {
try {
return workflowService.getStartTask(invitationId);
} catch (Exception ex) {
logger.error("Error getting WorkflowTask from invitationId : " + ex.toString());
throw ex;
}
}
});
} catch (RuntimeException rex) {
throw new KoyaServiceException(KoyaErrorCodes.INVALID_INVITATION_ID);
}
/**
* Test invitation validity code inspired by InvitationServiceImpl
*/
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(startTask.getPath().getId());
if (tasks.size() != 1) {
logger.warn("invitation validation error : " + tasks.size() + " tasks found for (id=" + invitationId
+ ";ticket=" + inviteTicket);
throw new KoyaServiceException(KoyaErrorCodes.INVITATION_ALREADY_COMPLETED);
}
WorkflowTask task = tasks.get(0);
if (!taskTypeMatches(task, WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING,
WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING)) {
logger.warn("invitation validation error : taskType=" + task.getDefinition().getMetadata().getName()
+ " for (id=" + invitationId + ";ticket=" + inviteTicket);
throw new KoyaServiceException(KoyaErrorCodes.INVITATION_ALREADY_COMPLETED);
}
/**
* Test invite ticket validity
*/
if (!invitation.getTicket().equals(inviteTicket)) {
throw new KoyaServiceException(KoyaErrorCodes.INVALID_INVITATION_TICKET);
}
userInvited.setUserName(invitation.getInviteeUserName());
userInvited.setEmail(invitation.getInviteeEmail());
// First accept invitation
Exception eInvite = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Exception>() {
@Override
public Exception doWork() throws Exception {
try {
invitationService.accept(invitationId, inviteTicket);
} catch (Exception ex) {
return ex;
}
return null;
}
}, invitation.getInviteeUserName());
if (eInvite != null) {
throw new KoyaServiceException(KoyaErrorCodes.INVITATION_PROCESS_ACCEPT_ERROR, eInvite);
}
if(!userEnabled){
// then modify user properties and password
Exception eModify = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Exception>() {
@Override
public Exception doWork() throws Exception {
try {
//Validate user information only if passwords are setted
//if not session validation is initiated by logged and already enabled user
userService.modifyUser(userInvited);
} catch (Exception ex) {
return ex;
}
return null;
}
}, invitation.getInviteeUserName());
if (eModify != null) {
eModify.printStackTrace();
throw new KoyaServiceException(KoyaErrorCodes.INVITATION_PROCESS_USER_MODIFICATION_ERROR, eModify);
}
AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Exception>() {
@Override
public Exception doWork() throws Exception {
try {
userService.adminForceChangePassword(invitation.getInviteeUserName(), newPassword);
} catch (Exception ex) {
return ex;
}
return null;
}
});
}
/**
* Post an activity for dossiers shared to this user in the company context
*
* executed asynchronously
*/
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>() {
@Override
public Void doWork() throws Exception {
Action doPostActivity = actionService
.createAction(AfterValidateInvitePostActivityActionExecuter.NAME, null);
actionService.executeAction(doPostActivity,
siteService.getSite(invitation.getResourceName()).getNodeRef(), false, true);
return null;
}
}, invitation.getInviteeUserName());
/**
*
* TODO Enable notification by default when user validates
* invitation
*
*
*/
logger.info("[Invite Validation] : {'user':'" + userInvited.getEmail() + "','company':'"+invitation.getResourceName()+"'}");
} catch (KoyaServiceException ex) {
throw new WebScriptException("KoyaError : " + ex.getErrorCode().toString());
}
res.setContentType("application/json;charset=UTF-8");
// TODO return validation status
res.getWriter().write(KoyaWebscript.getObjectAsJson(userInvited));
}
private boolean taskTypeMatches(WorkflowTask task, QName... types) {
QName taskDefName = task.getDefinition().getMetadata().getName();
return Arrays.asList(types).contains(taskDefName);
}
}