/projects/roller-5.0.1/weblogger-web/src/main/java/org/apache/roller/weblogger/ui/struts2/core/Register.java
Java | 426 lines | 255 code | 79 blank | 92 comment | 57 complexity | efbd2f3c662317a4ffa41a79f35036a0 MD5 | raw file
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. The ASF licenses this file to You
4 * under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. For additional information regarding
15 * copyright in this work, please see the NOTICE file in the top level
16 * directory of this distribution.
17 */
18
19package org.apache.roller.weblogger.ui.struts2.core;
20
21import java.util.TimeZone;
22import java.util.UUID;
23import javax.servlet.http.HttpServletRequest;
24import org.apache.commons.lang.CharSetUtils;
25import org.apache.commons.lang.StringUtils;
26import org.apache.commons.logging.Log;
27import org.apache.commons.logging.LogFactory;
28import org.apache.roller.weblogger.WebloggerException;
29import org.apache.roller.weblogger.business.WebloggerFactory;
30import org.apache.roller.weblogger.business.UserManager;
31import org.apache.roller.weblogger.config.WebloggerConfig;
32import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
33import org.apache.roller.weblogger.pojos.User;
34import org.apache.roller.weblogger.pojos.UserAttribute;
35import org.apache.roller.weblogger.ui.core.security.CustomUserRegistry;
36import org.apache.roller.weblogger.ui.struts2.util.UIAction;
37import org.apache.roller.weblogger.util.MailUtil;
38import org.apache.struts2.interceptor.ServletRequestAware;
39import org.apache.struts2.interceptor.validation.SkipValidation;
40//import org.springframework.security.userdetails.openid.OpenIDUserAttribute;
41
42
43
44/**
45 * Actions for registering a new user.
46 */
47public class Register extends UIAction implements ServletRequestAware {
48
49 private static Log log = LogFactory.getLog(Register.class);
50
51 public static String DEFAULT_ALLOWED_CHARS = "A-Za-z0-9";
52
53 // this is a no-no, we should not need this
54 private HttpServletRequest servletRequest = null;
55
56 private boolean fromSS0 = false;
57 private String activationStatus = null;
58
59 private String activationCode = null;
60 private ProfileBean bean = new ProfileBean();
61
62
63 public Register() {
64 this.pageTitle = "newUser.addNewUser";
65 }
66
67
68 // override default security, we do not require an authenticated user
69 public boolean isUserRequired() {
70 return false;
71 }
72
73 // override default security, we do not require an action weblog
74 public boolean isWeblogRequired() {
75 return false;
76 }
77
78 public String getOpenIdConfiguration() {
79 return WebloggerConfig.getProperty("authentication.openid");
80 }
81
82 @SkipValidation
83 public String execute() {
84
85 // if registation is disabled, then don't allow registration
86 try {
87 if (!WebloggerRuntimeConfig.getBooleanProperty("users.registration.enabled")
88 // unless there are 0 users (need to allow creation of first user)
89 && WebloggerFactory.getWeblogger().getUserManager().getUserCount() != 0) {
90 return "disabled";
91 }
92 } catch (Exception e) {
93 log.error("Error checking user count", e);
94 return "disabled";
95 }
96
97 // For new user default to locale set in browser
98 bean.setLocale(getServletRequest().getLocale().toString());
99
100 // For new user default to timezone of server
101 bean.setTimeZone(TimeZone.getDefault().getID());
102
103 /* TODO: when Spring Security 2.1 is release comment out this stuff,
104 * which pre-populates the user bean with info from OpenID provider.
105 *
106 Collection attrsCollect = (Collection)WebloggerFactory.getWeblogger()
107 .getUserManager().userAttributes.get(UserAttribute.Attributes.openidUrl.toString());
108
109 if (attrsCollect != null) {
110 ArrayList attrs = new ArrayList(attrsCollect);
111 for (Iterator it = attrs.iterator(); it.hasNext();) {
112 OpenIDUserAttribute attr = (OpenIDUserAttribute) it.next();
113 if (attr.getName().equals(OpenIDUserAttribute.Attributes.country.toString())) {
114 getBean().setLocale(UIUtils.getLocale(attr.getValue()));
115 }
116 if (attr.getName().equals(OpenIDUserAttribute.Attributes.email.toString())) {
117 getBean().setEmailAddress(attr.getValue());
118 }
119 if (attr.getName().equals(OpenIDUserAttribute.Attributes.fullname.toString())) {
120 getBean().setFullName(attr.getValue());
121 }
122 if (attr.getName().equals(OpenIDUserAttribute.Attributes.nickname.toString())) {
123 getBean().setUserName(attr.getValue());
124 }
125 if (attr.getName().equals(OpenIDUserAttribute.Attributes.timezone.toString())) {
126 getBean().setTimeZone(UIUtils.getTimeZone(attr.getValue()));
127 }
128 if (attr.getName().equals(OpenIDUserAttribute.Attributes.openidname.toString())) {
129 getBean().setOpenidUrl(attr.getValue());
130 }
131
132 }
133 }*/
134
135 try {
136
137 boolean usingSSO = WebloggerConfig.getBooleanProperty("users.sso.enabled");
138 if (usingSSO) {
139 // See if user is already logged in via Acegi
140 User fromSSO = CustomUserRegistry.getUserDetailsFromAuthentication(getServletRequest());
141 if (fromSSO != null) {
142 // Copy user details from Acegi, including LDAP attributes
143 getBean().copyFrom(fromSSO);
144 setFromSso(true);
145 }
146 // See if user is already logged in via CMA
147 else if (getServletRequest().getUserPrincipal() != null) {
148 // Only detail we get is username, sadly no LDAP attributes
149 getBean().setUserName(getServletRequest().getUserPrincipal().getName());
150 getBean().setScreenName(getServletRequest().getUserPrincipal().getName());
151 setFromSso(true);
152 }
153 }
154
155 } catch (Exception ex) {
156 log.error("Error reading SSO user data", ex);
157 addError("error.editing.user", ex.toString());
158 }
159
160 return INPUT;
161 }
162
163
164 public String save() {
165
166 // if registation is disabled, then don't allow registration
167 try {
168 if (!WebloggerRuntimeConfig.getBooleanProperty("users.registration.enabled")
169 // unless there are 0 users (need to allow creation of first user)
170 && WebloggerFactory.getWeblogger().getUserManager().getUserCount() != 0) {
171 return "disabled";
172 }
173 } catch (Exception e) {
174 log.error("Error checking user count", e);
175 return "disabled";
176 }
177
178 myValidate();
179
180 if (!hasActionErrors()) try {
181
182 UserManager mgr = WebloggerFactory.getWeblogger().getUserManager();
183
184 // copy form data into new user pojo
185 User ud = new User();
186 getBean().copyTo(ud); // doesn't copy password
187 ud.setUserName(getBean().getUserName());
188 ud.setDateCreated(new java.util.Date());
189 ud.setEnabled(Boolean.TRUE);
190
191 // If user set both password and passwordConfirm then reset password
192 if (!StringUtils.isEmpty(getBean().getPasswordText()) &&
193 !StringUtils.isEmpty(getBean().getPasswordConfirm())) {
194 ud.resetPassword(getBean().getPasswordText());
195 }
196
197 // are we using email activation?
198 boolean activationEnabled = WebloggerRuntimeConfig.getBooleanProperty(
199 "user.account.activation.enabled");
200 if (activationEnabled) {
201 // User account will be enabled after the activation process
202 ud.setEnabled(Boolean.FALSE);
203
204 // Create & save the activation data
205 String activationCode = UUID.randomUUID().toString();
206
207 if (mgr.getUserByActivationCode(activationCode) != null) {
208 // In the *extremely* unlikely event that we generate an
209 // activation code that is already use, we'll retry 3 times.
210 int numOfRetries = 3;
211 if (numOfRetries < 1) numOfRetries = 1;
212 for (int i = 0; i < numOfRetries; i++) {
213 activationCode = UUID.randomUUID().toString();
214 if (mgr.getUserByActivationCode(activationCode) == null) {
215 break;
216 } else {
217 activationCode = null;
218 }
219 }
220 // In more unlikely event that three retries isn't enough
221 if (activationCode == null){
222 throw new WebloggerException("error.add.user.activationCodeInUse");
223 }
224 }
225 ud.setActivationCode(activationCode);
226 }
227
228 // save new user
229 mgr.addUser(ud);
230
231 String openidurl = getBean().getOpenIdUrl();
232 if (openidurl != null) {
233 if (openidurl.endsWith("/")) {
234 openidurl = openidurl.substring(0, openidurl.length() - 1);
235 }
236 mgr.setUserAttribute(
237 ud.getUserName(), UserAttribute.Attributes.OPENID_URL.toString(),
238 openidurl);
239 }
240
241 WebloggerFactory.getWeblogger().flush();
242
243 // now send activation email if necessary
244 if (activationEnabled && ud.getActivationCode() != null) {
245 try {
246 // send activation mail to the user
247 MailUtil.sendUserActivationEmail(ud);
248 } catch (WebloggerException ex) {
249 log.error("Error sending activation email to - "+ud.getEmailAddress(), ex);
250 }
251
252 setActivationStatus("pending");
253 }
254
255 // Invalidate session, otherwise new user who was originally
256 // authenticated via LDAP/SSO will remain logged in with
257 // a but without a valid Roller role.
258 getServletRequest().getSession().invalidate();
259
260 // set a special page title
261 setPageTitle("welcome.title");
262
263 return SUCCESS;
264
265 } catch (WebloggerException ex) {
266 log.error("Error adding new user", ex);
267 // TODO: i18n
268 addError("Error adding new user");
269 }
270
271 return INPUT;
272 }
273
274
275 @SkipValidation
276 public String activate() {
277
278 try {
279 UserManager mgr = WebloggerFactory.getWeblogger().getUserManager();
280
281 if (getActivationCode() == null) {
282 addError("error.activate.user.missingActivationCode");
283 } else {
284 User user = mgr.getUserByActivationCode(getActivationCode());
285
286 if (user != null) {
287 // enable user account
288 user.setEnabled(Boolean.TRUE);
289 user.setActivationCode(null);
290 mgr.saveUser(user);
291 WebloggerFactory.getWeblogger().flush();
292
293 setActivationStatus("active");
294
295 } else {
296 addError("error.activate.user.invalidActivationCode");
297 }
298 }
299
300 } catch (WebloggerException e) {
301 addError(e.getMessage());
302 log.error("ERROR in activateUser", e);
303 }
304
305 if (hasActionErrors()) {
306 setActivationStatus("error");
307 }
308
309 // set a special page title
310 setPageTitle("welcome.title");
311
312 return SUCCESS;
313 }
314
315
316 public void myValidate() {
317
318 // if usingSSO, we don't want to error on empty password/username from HTML form.
319 setFromSso(false);
320 boolean usingSSO = WebloggerConfig.getBooleanProperty("users.sso.enabled");
321 if (usingSSO) {
322 boolean storePassword = WebloggerConfig.getBooleanProperty("users.sso.passwords.saveInRollerDb");
323 String password = WebloggerConfig.getProperty("users.sso.passwords.defaultValue", "<unknown>");
324
325 // Preserve username and password, Acegi case
326 User fromSSO = CustomUserRegistry.getUserDetailsFromAuthentication(getServletRequest());
327 if (fromSSO != null) {
328 if (storePassword) {
329 password = fromSSO.getPassword();
330 }
331 getBean().setPasswordText(password);
332 getBean().setPasswordConfirm(password);
333 getBean().setUserName(fromSSO.getUserName());
334 setFromSso(true);
335 }
336
337 // Preserve username and password, CMA case
338 else if (getServletRequest().getUserPrincipal() != null) {
339 getBean().setUserName(getServletRequest().getUserPrincipal().getName());
340 getBean().setPasswordText(password);
341 getBean().setPasswordConfirm(password);
342 setFromSso(true);
343 }
344 }
345
346 String allowed = WebloggerConfig.getProperty("username.allowedChars");
347 if (allowed == null || allowed.trim().length() == 0) {
348 allowed = DEFAULT_ALLOWED_CHARS;
349 }
350
351 // check that username only contains safe characters
352 String safe = CharSetUtils.keep(getBean().getUserName(), allowed);
353 if (!safe.equals(getBean().getUserName()) ) {
354 addError("error.add.user.badUserName");
355 }
356
357 // check password, it is required if OpenID and SSO are disabled
358 if (getOpenIdConfiguration().equals("disabled") && !getFromSso()) {
359 if (StringUtils.isEmpty(getBean().getPasswordText())) {
360 addError("error.add.user.passwordEmpty");
361 return;
362 }
363 }
364
365 // check that passwords match
366 if (!getBean().getPasswordText().equals(getBean().getPasswordConfirm())) {
367 addError("Register.error.passowordMismatch");
368 }
369
370 // check that username is not taken
371 if (!StringUtils.isEmpty(getBean().getUserName())) try {
372 UserManager mgr = WebloggerFactory.getWeblogger().getUserManager();
373 if (mgr.getUserByUserName(getBean().getUserName(), null) != null) {
374 addError("error.add.user.userNameInUse");
375 // reset user name
376 getBean().setUserName(null);
377 }
378 } catch (WebloggerException ex) {
379 log.error("error checking for user", ex);
380 // TODO: i18n
381 addError("unexpected error");
382 }
383 }
384
385
386 public HttpServletRequest getServletRequest() {
387 return servletRequest;
388 }
389
390 public void setServletRequest(HttpServletRequest servletRequest) {
391 this.servletRequest = servletRequest;
392 }
393
394 public ProfileBean getBean() {
395 return bean;
396 }
397
398 public void setBean(ProfileBean bean) {
399 this.bean = bean;
400 }
401
402 public boolean getFromSso() {
403 return fromSS0;
404 }
405
406 public void setFromSso(boolean fromSS0) {
407 this.fromSS0 = fromSS0;
408 }
409
410 public String getActivationStatus() {
411 return activationStatus;
412 }
413
414 public void setActivationStatus(String activationStatus) {
415 this.activationStatus = activationStatus;
416 }
417
418 public String getActivationCode() {
419 return activationCode;
420 }
421
422 public void setActivationCode(String activationCode) {
423 this.activationCode = activationCode;
424 }
425
426}