001/* 002 * (C) Copyright 2011 Nuxeo SAS (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.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 * Contributors: 014 * Nuxeo - initial API and implementation 015 */ 016 017package org.nuxeo.ecm.user.registration; 018 019import java.io.Serializable; 020import java.io.StringWriter; 021import java.util.HashMap; 022import java.util.Map; 023 024import javax.mail.MessagingException; 025import javax.naming.NamingException; 026 027import org.apache.commons.lang.StringUtils; 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.common.utils.IdUtils; 031import org.nuxeo.ecm.core.api.CoreSession; 032import org.nuxeo.ecm.core.api.DocumentModel; 033import org.nuxeo.ecm.core.api.NuxeoException; 034import org.nuxeo.ecm.core.api.PropertyException; 035import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 036import org.nuxeo.ecm.core.api.security.ACE; 037import org.nuxeo.ecm.core.api.security.ACL; 038import org.nuxeo.ecm.core.api.security.ACP; 039import org.nuxeo.ecm.core.api.security.SecurityConstants; 040import org.nuxeo.ecm.core.api.security.impl.ACLImpl; 041import org.nuxeo.ecm.core.api.security.impl.ACPImpl; 042import org.nuxeo.ecm.platform.rendering.api.RenderingException; 043import org.nuxeo.ecm.platform.usermanager.NuxeoPrincipalImpl; 044import org.nuxeo.ecm.platform.usermanager.UserManager; 045import org.nuxeo.ecm.user.invite.RegistrationRules; 046import org.nuxeo.ecm.user.invite.UserInvitationComponent; 047import org.nuxeo.ecm.user.invite.UserRegistrationConfiguration; 048import org.nuxeo.ecm.user.invite.UserRegistrationException; 049import org.nuxeo.ecm.user.invite.UserRegistrationInfo; 050import org.nuxeo.runtime.api.Framework; 051 052public class UserRegistrationComponent extends UserInvitationComponent implements UserRegistrationService { 053 054 protected static Log log = LogFactory.getLog(UserRegistrationService.class); 055 056 private static final String REGISTRATION_SUBMITTED_EVENT = "registrationSubmitted"; 057 058 private static final String REGISTRATION_ACCEPTED_EVENT = "registrationAccepted"; 059 060 private static final String REGISTRATION_REJECTED_EVENT = "registrationRejected"; 061 062 private static final String REGISTRATION_VALIDATED_EVENT = "registrationValidated"; 063 064 protected class RegistrationCreator extends UnrestrictedSessionRunner { 065 066 protected UserRegistrationInfo userInfo; 067 068 protected DocumentRegistrationInfo docInfo; 069 070 protected Map<String, Serializable> additionnalInfo; 071 072 protected String registrationUuid; 073 074 protected String principalName; 075 076 protected ValidationMethod validationMethod; 077 078 protected UserRegistrationConfiguration configuration; 079 080 public String getRegistrationUuid() { 081 return registrationUuid; 082 } 083 084 public RegistrationCreator(String configurationName, UserRegistrationInfo userInfo, 085 DocumentRegistrationInfo docInfo, Map<String, Serializable> additionnalInfo, 086 ValidationMethod validationMethod, String principalName) { 087 super(getTargetRepositoryName()); 088 this.userInfo = userInfo; 089 this.additionnalInfo = additionnalInfo; 090 this.validationMethod = validationMethod; 091 this.docInfo = docInfo; 092 this.configuration = getConfiguration(configurationName); 093 this.principalName = principalName; 094 } 095 096 @Override 097 public void run() { 098 099 //Check if login is defined - if not define it with email 100 userInfo.setLogin(userInfo.getLogin() == null ? userInfo.getEmail() : userInfo.getLogin()); 101 102 String title = "registration request for " + userInfo.getLogin() + " (" + userInfo.getEmail() + " " 103 + userInfo.getCompany() + ") "; 104 String name = IdUtils.generateId(title + "-" + System.currentTimeMillis(), "-", true, 24); 105 106 String targetPath = getOrCreateRootDocument(session, configuration.getName()).getPathAsString(); 107 108 DocumentModel doc = session.createDocumentModel(configuration.getRequestDocType()); 109 doc.setPathInfo(targetPath, name); 110 doc.setPropertyValue("dc:title", title); 111 112 // store userinfo 113 doc.setPropertyValue(configuration.getUserInfoUsernameField(), userInfo.getLogin()); 114 doc.setPropertyValue(configuration.getUserInfoFirstnameField(), userInfo.getFirstName()); 115 doc.setPropertyValue(configuration.getUserInfoLastnameField(), userInfo.getLastName()); 116 doc.setPropertyValue(configuration.getUserInfoEmailField(), userInfo.getEmail()); 117 doc.setPropertyValue(configuration.getUserInfoCompanyField(), userInfo.getCompany()); 118 doc.setPropertyValue(configuration.getUserInfoGroupsField(), (Serializable) userInfo.getGroups()); 119 120 // validation method 121 doc.setPropertyValue("registration:validationMethod", validationMethod.toString()); 122 123 // Document info 124 doc.setPropertyValue(DocumentRegistrationInfo.DOCUMENT_ID_FIELD, docInfo.getDocumentId()); 125 doc.setPropertyValue(DocumentRegistrationInfo.DOCUMENT_RIGHT_FIELD, docInfo.getPermission()); 126 doc.setPropertyValue(DocumentRegistrationInfo.DOCUMENT_TITLE_FIELD, docInfo.getDocumentTitle()); 127 doc.setPropertyValue(DocumentRegistrationInfo.DOCUMENT_BEGIN_FIELD, docInfo.getBegin()); 128 doc.setPropertyValue(DocumentRegistrationInfo.DOCUMENT_END_FIELD, docInfo.getEnd()); 129 130 // additionnal infos 131 for (String key : additionnalInfo.keySet()) { 132 try { 133 doc.setPropertyValue(key, additionnalInfo.get(key)); 134 } catch (PropertyException e) { 135 // skip silently 136 } 137 } 138 139 doc = session.createDocument(doc); 140 141 // Set the ACP for the UserRegistration object 142 ACP acp = new ACPImpl(); 143 ACE denyEverything = new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, false); 144 ACE allowEverything = new ACE(principalName, SecurityConstants.EVERYTHING, true); 145 ACL acl = new ACLImpl(); 146 acl.setACEs(new ACE[] { allowEverything, denyEverything }); 147 acp.addACL(acl); 148 doc.setACP(acp, true); 149 150 registrationUuid = doc.getId(); 151 152 sendEvent(session, doc, getNameEventRegistrationSubmitted()); 153 154 session.save(); 155 } 156 157 } 158 159 public String submitRegistrationRequest(UserRegistrationInfo userInfo, Map<String, Serializable> additionnalInfo, 160 ValidationMethod validationMethod, boolean autoAccept, String principalName) { 161 return submitRegistrationRequest(CONFIGURATION_NAME, userInfo, new DocumentRegistrationInfo(), additionnalInfo, 162 validationMethod, autoAccept, principalName); 163 } 164 165 @Override 166 public String submitRegistrationRequest(String configurationName, UserRegistrationInfo userInfo, 167 DocumentRegistrationInfo docInfo, Map<String, Serializable> additionnalInfo, 168 ValidationMethod validationMethod, boolean autoAccept, String principalName) throws 169 UserRegistrationException { 170 RegistrationCreator creator = new RegistrationCreator(configurationName, userInfo, docInfo, additionnalInfo, 171 validationMethod, principalName); 172 creator.runUnrestricted(); 173 String registrationUuid = creator.getRegistrationUuid(); 174 175 boolean userAlreadyExists = null != Framework.getLocalService(UserManager.class).getPrincipal( 176 userInfo.getLogin()); 177 // Directly accept registration if the configuration allow it and the 178 // user already exists 179 RegistrationRules registrationRules = getRegistrationRules(configurationName); 180 boolean byPassAdminValidation = autoAccept; 181 byPassAdminValidation |= userAlreadyExists && registrationRules.allowDirectValidationForExistingUser(); 182 byPassAdminValidation |= registrationRules.allowDirectValidationForExistingUser() 183 && registrationRules.allowDirectValidationForNonExistingUser(); 184 if (byPassAdminValidation) { 185 // Build validationBaseUrl with nuxeo.url property as request is 186 // not accessible. 187 if (!additionnalInfo.containsKey("enterPasswordUrl")) { 188 String baseUrl = Framework.getProperty(NUXEO_URL_KEY); 189 190 baseUrl = StringUtils.isBlank(baseUrl) ? "/" : baseUrl; 191 if (!baseUrl.endsWith("/")) { 192 baseUrl += "/"; 193 } 194 String enterPasswordUrl = getConfiguration(configurationName).getEnterPasswordUrl(); 195 if (enterPasswordUrl.startsWith("/")) { 196 enterPasswordUrl = enterPasswordUrl.substring(1); 197 } 198 additionnalInfo.put("enterPasswordUrl", baseUrl.concat(enterPasswordUrl)); 199 } 200 acceptRegistrationRequest(registrationUuid, additionnalInfo); 201 } 202 return registrationUuid; 203 } 204 205 public Map<String, Serializable> validateRegistrationAndSendEmail(String requestId, 206 Map<String, Serializable> additionnalInfo) throws UserRegistrationException { 207 208 Map<String, Serializable> registrationInfo = validateRegistration(requestId, additionnalInfo); 209 210 Map<String, Serializable> input = new HashMap<String, Serializable>(); 211 input.putAll(registrationInfo); 212 input.put("info", (Serializable) additionnalInfo); 213 StringWriter writer = new StringWriter(); 214 215 UserRegistrationConfiguration configuration = getConfiguration((DocumentModel) registrationInfo.get(REGISTRATION_DATA_DOC)); 216 try { 217 rh.getRenderingEngine().render(configuration.getSuccessEmailTemplate(), input, writer); 218 } catch (RenderingException e) { 219 throw new NuxeoException("Error during rendering email", e); 220 } 221 222 String emailAdress = ((NuxeoPrincipalImpl) registrationInfo.get("registeredUser")).getEmail(); 223 String body = writer.getBuffer().toString(); 224 String title = configuration.getValidationEmailTitle(); 225 if (!Framework.isTestModeSet()) { 226 try { 227 generateMail(emailAdress, null, title, body); 228 } catch (NamingException | MessagingException e) { 229 throw new NuxeoException("Error while sending mail", e); 230 } 231 } else { 232 testRendering = body; 233 } 234 235 return registrationInfo; 236 } 237 238 @Override 239 public void addRightsOnDoc(CoreSession session, DocumentModel registrationDoc) { 240 UserRegistrationConfiguration configuration = getConfiguration(registrationDoc); 241 DocumentModel document = ((DefaultRegistrationUserFactory) getRegistrationUserFactory(configuration)).doAddDocumentPermission( 242 session, registrationDoc, configuration); 243 if (document != null) { 244 ((RegistrationUserFactory) getRegistrationUserFactory(configuration)).doPostAddDocumentPermission(session, 245 registrationDoc, document); 246 } 247 } 248 249 @Override 250 public String getNameEventRegistrationSubmitted() { 251 return REGISTRATION_SUBMITTED_EVENT; 252 } 253 254 @Override 255 public String getNameEventRegistrationAccepted() { 256 return REGISTRATION_ACCEPTED_EVENT; 257 } 258 259 @Override 260 public String getNameEventRegistrationRejected() { 261 return REGISTRATION_REJECTED_EVENT; 262 } 263 264 @Override 265 public String getNameEventRegistrationValidated() { 266 return REGISTRATION_VALIDATED_EVENT; 267 } 268}