001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *  Vladimir Pasquier <vpasquier@nuxeo.com>
016 */
017package org.nuxeo.shibboleth.invitation;
018
019import java.io.Serializable;
020import java.util.HashMap;
021import java.util.Map;
022
023import javax.ws.rs.FormParam;
024import javax.ws.rs.GET;
025import javax.ws.rs.POST;
026import javax.ws.rs.Path;
027import javax.ws.rs.PathParam;
028import javax.ws.rs.Produces;
029
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper;
033import org.nuxeo.ecm.user.invite.AlreadyProcessedRegistrationException;
034import org.nuxeo.ecm.user.invite.DefaultInvitationUserFactory;
035import org.nuxeo.ecm.user.invite.UserInvitationService;
036import org.nuxeo.ecm.user.invite.UserRegistrationException;
037import org.nuxeo.ecm.user.registration.UserRegistrationService;
038import org.nuxeo.ecm.webengine.forms.FormData;
039import org.nuxeo.ecm.webengine.model.Template;
040import org.nuxeo.ecm.webengine.model.WebObject;
041import org.nuxeo.ecm.webengine.model.impl.ModuleRoot;
042import org.nuxeo.runtime.api.Framework;
043
044@Path("/shibboInvite")
045@WebObject(type = "shibboInvite")
046@Produces("text/html;charset=UTF-8")
047public class ShibboInviteObject extends ModuleRoot {
048    private static final Log log = LogFactory.getLog(ShibboInviteObject.class);
049
050    @POST
051    @Path("validate")
052    public Object validateTrialForm(@FormParam("isShibbo") boolean isShibbo) {
053        UserInvitationService usr = fetchService();
054
055        FormData formData = getContext().getForm();
056        String requestId = formData.getString("RequestId");
057        String password = formData.getString("Password");
058        String passwordConfirmation = formData.getString("PasswordConfirmation");
059
060        // Check if the requestId is an existing one
061        try {
062            usr.checkRequestId(requestId);
063        } catch (AlreadyProcessedRegistrationException ape) {
064            return getView("ValidationErrorTemplate").arg("exceptionMsg",
065                    ctx.getMessage("label.error.requestAlreadyProcessed"));
066        } catch (UserRegistrationException ue) {
067            return getView("ValidationErrorTemplate").arg("exceptionMsg",
068                    ctx.getMessage("label.error.requestNotExisting", requestId));
069        }
070
071        if (!isShibbo) {
072            // Check if both entered passwords are correct
073            if (password == null || "".equals(password.trim())) {
074                return redisplayFormWithErrorMessage("EnterPassword",
075                        ctx.getMessage("label.registerForm.validation.password"), formData);
076
077            }
078            if (passwordConfirmation == null || "".equals(passwordConfirmation.trim()) && !isShibbo) {
079                return redisplayFormWithErrorMessage("EnterPassword",
080                        ctx.getMessage("label.registerForm.validation.passwordconfirmation"), formData);
081            }
082            password = password.trim();
083            passwordConfirmation = passwordConfirmation.trim();
084            if (!password.equals(passwordConfirmation) && !isShibbo) {
085                return redisplayFormWithErrorMessage("EnterPassword",
086                        ctx.getMessage("label.registerForm.validation.passwordvalidation"), formData);
087            }
088        }
089        Map<String, Serializable> registrationData;
090        try {
091            Map<String, Serializable> additionalInfo = buildAdditionalInfos();
092            // Add the entered password to the document model
093            additionalInfo.put(DefaultInvitationUserFactory.PASSWORD_KEY, password);
094            // Validate the creation of the user
095            registrationData = usr.validateRegistration(requestId, additionalInfo);
096        } catch (AlreadyProcessedRegistrationException ape) {
097            log.info("Try to validate an already processed registration");
098            return getView("ValidationErrorTemplate").arg("exceptionMsg",
099                    ctx.getMessage("label.error.requestAlreadyProcessed"));
100        } catch (UserRegistrationException ue) {
101            log.warn("Unable to validate registration request", ue);
102            return getView("ValidationErrorTemplate").arg("exceptionMsg",
103                    ctx.getMessage("label.errror.requestNotAccepted"));
104        }
105        // User redirected to the logout page after validating the password
106        String webappName = VirtualHostHelper.getWebAppName(getContext().getRequest());
107        String redirectUrl = "/" + webappName + "/logout";
108        if (isShibbo) {
109            return getView("UserCreated").arg("data", registrationData)
110                                         .arg("redirectUrl", "/nuxeo/site/shibboleth?requestedUrl=")
111                                         .arg("isShibbo", isShibbo);
112        }
113        return getView("UserCreated").arg("redirectUrl", redirectUrl)
114                                     .arg("data", registrationData)
115                                     .arg("isShibbo", isShibbo);
116    }
117
118    protected UserInvitationService fetchService() {
119        return Framework.getLocalService(UserRegistrationService.class);
120    }
121
122    @GET
123    @Path("enterpassword/{configurationName}/{requestId}")
124    public Object validatePasswordForm(@PathParam("requestId") String requestId,
125            @PathParam("configurationName") String configurationName) {
126
127        UserInvitationService usr = fetchService();
128        try {
129            usr.checkRequestId(requestId);
130        } catch (AlreadyProcessedRegistrationException ape) {
131            return getView("ValidationErrorTemplate").arg("exceptionMsg",
132                    ctx.getMessage("label.error.requestAlreadyProcessed"));
133        } catch (UserRegistrationException ue) {
134            return getView("ValidationErrorTemplate").arg("exceptionMsg",
135                    ctx.getMessage("label.error.requestNotExisting", requestId));
136        }
137
138        Map<String, String> data = new HashMap<String, String>();
139        data.put("RequestId", requestId);
140        data.put("ConfigurationName", configurationName);
141        String webappName = VirtualHostHelper.getWebAppName(getContext().getRequest());
142        String validationRelUrl = usr.getConfiguration(configurationName).getValidationRelUrl();
143        String valUrl = "/" + webappName + "/" + validationRelUrl;
144        data.put("ValidationUrl", valUrl);
145        return getView("EnterPassword").arg("data", data);
146    }
147
148    protected Map<String, Serializable> buildAdditionalInfos() {
149        return new HashMap<>();
150    }
151
152    protected Template redisplayFormWithMessage(String messageType, String formName, String message, FormData data) {
153        Map<String, String> savedData = new HashMap<String, String>();
154        for (String key : data.getKeys()) {
155            savedData.put(key, data.getString(key));
156        }
157        return getView(formName).arg("data", savedData).arg(messageType, message);
158    }
159
160    protected Template redisplayFormWithInfoMessage(String formName, String message, FormData data) {
161        return redisplayFormWithMessage("info", formName, message, data);
162    }
163
164    protected Template redisplayFormWithErrorMessage(String formName, String message, FormData data) {
165        return redisplayFormWithMessage("err", formName, message, data);
166    }
167
168}