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