File Source: Register.java
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
19 package org.apache.roller.weblogger.ui.struts2.core;
20
21 import java.util.Locale;
22 import java.util.TimeZone;
23 import java.util.UUID;
24 import javax.servlet.http.HttpServletRequest;
25 import org.apache.commons.lang.CharSetUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.roller.weblogger.WebloggerException;
30 import org.apache.roller.weblogger.business.WebloggerFactory;
31 import org.apache.roller.weblogger.business.UserManager;
32 import org.apache.roller.weblogger.config.WebloggerConfig;
33 import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
34 import org.apache.roller.weblogger.pojos.User;
35 import org.apache.roller.weblogger.ui.core.security.CustomUserRegistry;
36 import org.apache.roller.weblogger.ui.struts2.util.UIAction;
37 import org.apache.roller.weblogger.util.MailUtil;
38 import org.apache.struts2.interceptor.ServletRequestAware;
39 import org.apache.struts2.interceptor.validation.SkipValidation;
40
41
42 /**
43 * Actions for registering a new user.
44 */
45 public class Register extends UIAction implements ServletRequestAware {
46
/*
P/P * Method: org.apache.roller.weblogger.ui.struts2.core.Register__static_init
*
* Postconditions:
* DEFAULT_ALLOWED_CHARS == &"A-Za-z0-9"
* init'ed(log)
*/
47 private static Log log = LogFactory.getLog(Register.class);
48
49 public static String DEFAULT_ALLOWED_CHARS = "A-Za-z0-9";
50
51 // this is a no-no, we should not need this
52 private HttpServletRequest servletRequest = null;
53
54 private boolean fromSS0 = false;
55 private String activationStatus = null;
56
57 private String activationCode = null;
58 private ProfileBean bean = new ProfileBean();
59
60
/*
P/P * Method: void org.apache.roller.weblogger.ui.struts2.core.Register()
*
* Postconditions:
* this.activationCode == null
* this.activationStatus == null
* this.servletRequest == null
* this.bean.emailAddress == null
* this.bean.fullName == null
* this.bean.id == null
* this.bean.locale == null
* this.bean.password == null
* this.bean.passwordConfirm == null
* this.bean.passwordText == null
* ...
*/
61 public Register() {
62 this.pageTitle = "newUser.addNewUser";
63 }
64
65
66 // override default security, we do not require an authenticated user
67 public boolean isUserRequired() {
/*
P/P * Method: bool isUserRequired()
*
* Postconditions:
* return_value == 0
*/
68 return false;
69 }
70
71 // override default security, we do not require an action weblog
72 public boolean isWeblogRequired() {
/*
P/P * Method: bool isWeblogRequired()
*
* Postconditions:
* return_value == 0
*/
73 return false;
74 }
75
76
77 @SkipValidation
78 public String execute() {
79
/*
P/P * Method: String execute()
*
* Preconditions:
* (soft) log != null
* (soft) this.bean != null
*
* Presumptions:
* java.util.Locale:getDefault(...)@85 != null
* java.util.TimeZone:getDefault(...)@86 != null
*
* Postconditions:
* java.util.Locale:toString(...)._tainted == 0
* return_value in Addr_Set{&"input",&"disabled"}
* possibly_updated(this.bean.emailAddress)
* possibly_updated(this.bean.fullName)
* possibly_updated(this.bean.id)
* possibly_updated(this.bean.locale)
* possibly_updated(this.bean.password)
* possibly_updated(this.bean.screenName)
* possibly_updated(this.bean.timeZone)
* possibly_updated(this.bean.userName)
* ...
*
* Test Vectors:
* org.apache.roller.weblogger.config.WebloggerConfig:getBooleanProperty(...)@91: {0}, {1}
* org.apache.roller.weblogger.config.WebloggerRuntimeConfig:getBooleanProperty(...)@80: {1}, {0}
* org.apache.roller.weblogger.ui.core.security.CustomUserRegistry:getUserDetailsFromAuthentication(...)@93: Addr_Set{null}, Inverse{null}
*/
80 if(!WebloggerRuntimeConfig.getBooleanProperty("users.registration.enabled")) {
81 return "disabled";
82 }
83
84 // set some defaults
85 getBean().setLocale(Locale.getDefault().toString());
86 getBean().setTimeZone(TimeZone.getDefault().getID());
87
88 try {
89 // Let's see if there's any user-authentication available from Acegi
90 // and retrieve custom user data to pre-populate form.
91 boolean usingSSO = WebloggerConfig.getBooleanProperty("users.sso.enabled");
92 if(usingSSO) {
93 User fromSSO = CustomUserRegistry.getUserDetailsFromAuthentication();
94 if(fromSSO != null) {
95 getBean().copyFrom(fromSSO);
96 setFromSS0(true);
97 }
98 }
99
100 } catch (Exception ex) {
101 log.error("Error reading SSO user data", ex);
102 addError("error.editing.user", ex.toString());
103 }
104
105 return INPUT;
106 }
107
108
109 public String save() {
110
/*
P/P * Method: String save()
*
* Preconditions:
* (soft) init'ed(DEFAULT_ALLOWED_CHARS)
* (soft) log != null
* (soft) init'ed(this.bean.passwordConfirm)
* (soft) this.bean.passwordText != null
* (soft) init'ed(this.bean.userName)
* (soft) this.bean != null
* (soft) init'ed(this.bean.emailAddress)
* (soft) init'ed(this.bean.fullName)
* (soft) init'ed(this.bean.locale)
* (soft) init'ed(this.bean.screenName)
* ...
*
* Presumptions:
* init'ed(java.lang.Boolean.FALSE)
* init'ed(java.lang.Boolean.TRUE)
* java.util.UUID:randomUUID(...)@142 != null
* java.util.UUID:randomUUID(...)@150 != null
* javax.servlet.http.HttpServletRequest:getSession(...)@184 != null
* ...
*
* Postconditions:
* return_value in Addr_Set{&"success",&"input",&"disabled"}
* this.activationStatus == One-of{old this.activationStatus, &"pending"}
* init'ed(this.bean.passwordConfirm)
* this.bean.passwordText != null
* init'ed(this.bean.userName)
* possibly_updated(this.fromSS0)
*
* Test Vectors:
* org.apache.commons.lang.StringUtils:isEmpty(...)@129: {1}, {0}
* org.apache.roller.weblogger.business.UserManager:getUserByActivationCode(...)@144: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.config.WebloggerRuntimeConfig:getBooleanProperty(...)@111: {1}, {0}
* org.apache.roller.weblogger.config.WebloggerRuntimeConfig:getBooleanProperty(...)@135: {0}, {1}
* org.apache.roller.weblogger.pojos.User:getActivationCode(...)@170: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.ui.struts2.core.Register:hasActionErrors(...)@117: {1}, {0}
*/
111 if(!WebloggerRuntimeConfig.getBooleanProperty("users.registration.enabled")) {
112 return "disabled";
113 }
114
115 myValidate();
116
117 if (!hasActionErrors()) try {
118
119 UserManager mgr = WebloggerFactory.getWeblogger().getUserManager();
120
121 // copy form data into new user pojo
122 User ud = new User();
123 getBean().copyTo(ud); // doesn't copy password
124 ud.setUserName(getBean().getUserName());
125 ud.setDateCreated(new java.util.Date());
126 ud.setEnabled(Boolean.TRUE);
127
128 // If user set both password and passwordConfirm then reset password
129 if (!StringUtils.isEmpty(getBean().getPasswordText()) &&
130 !StringUtils.isEmpty(getBean().getPasswordConfirm())) {
131 ud.resetPassword(getBean().getPasswordText());
132 }
133
134 // are we using email activation?
135 boolean activationEnabled = WebloggerRuntimeConfig.getBooleanProperty(
136 "user.account.activation.enabled");
137 if (activationEnabled) {
138 // User account will be enabled after the activation process
139 ud.setEnabled(Boolean.FALSE);
140
141 // Create & save the activation data
142 String activationCode = UUID.randomUUID().toString();
143
144 if (mgr.getUserByActivationCode(activationCode) != null) {
145 // In the *extremely* unlikely event that we generate an
146 // activation code that is already use, we'll retry 3 times.
147 int numOfRetries = 3;
+ 148 if (numOfRetries < 1) numOfRetries = 1;
149 for (int i = 0; i < numOfRetries; i++) {
150 activationCode = UUID.randomUUID().toString();
151 if (mgr.getUserByActivationCode(activationCode) == null) {
152 break;
153 } else {
154 activationCode = null;
155 }
156 }
157 // In more unlikely event that three retries isn't enough
+ 158 if (activationCode == null){
159 throw new WebloggerException("error.add.user.activationCodeInUse");
160 }
161 }
162 ud.setActivationCode(activationCode);
163 }
164
165 // save new user
166 mgr.addUser(ud);
167 WebloggerFactory.getWeblogger().flush();
168
169 // now send activation email if necessary
170 if (activationEnabled && ud.getActivationCode() != null) {
171 try {
172 // send activation mail to the user
173 MailUtil.sendUserActivationEmail(ud);
174 } catch (WebloggerException ex) {
175 log.error("Error sending activation email to - "+ud.getEmailAddress(), ex);
176 }
177
178 setActivationStatus("pending");
179 }
180
181 // Invalidate session, otherwise new user who was originally
182 // authenticated via LDAP/SSO will remain logged in with
183 // a but without a valid Roller role.
184 getServletRequest().getSession().invalidate();
185
186 // set a special page title
187 setPageTitle("welcome.title");
188
189 return SUCCESS;
190
191 } catch (WebloggerException ex) {
192 log.error("Error adding new user", ex);
193 // TODO: i18n
194 addError("Error adding new user");
195 }
196
197 return INPUT;
198 }
199
200
201 @SkipValidation
202 public String activate() {
203
204 try {
/*
P/P * Method: String activate()
*
* Preconditions:
* (soft) log != null
* (soft) init'ed(this.activationCode)
*
* Presumptions:
* init'ed(java.lang.Boolean.TRUE)
* org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@205 != null
* org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@205 != null
* org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@217 != null
*
* Postconditions:
* return_value == &"success"
* this.activationStatus == One-of{old this.activationStatus, &"active", &"error"}
*
* Test Vectors:
* this.activationCode: Inverse{null}, Addr_Set{null}
* org.apache.roller.weblogger.business.UserManager:getUserByActivationCode(...)@210: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.ui.struts2.core.Register:hasActionErrors(...)@231: {0}, {1}
*/
205 UserManager mgr = WebloggerFactory.getWeblogger().getUserManager();
206
207 if (getActivationCode() == null) {
208 addError("error.activate.user.missingActivationCode");
209 } else {
210 User user = mgr.getUserByActivationCode(getActivationCode());
211
212 if (user != null) {
213 // enable user account
214 user.setEnabled(Boolean.TRUE);
215 user.setActivationCode(null);
216 mgr.saveUser(user);
217 WebloggerFactory.getWeblogger().flush();
218
219 setActivationStatus("active");
220
221 } else {
222 addError("error.activate.user.invalidActivationCode");
223 }
224 }
225
226 } catch (WebloggerException e) {
227 addError(e.getMessage());
228 log.error("ERROR in activateUser", e);
229 }
230
231 if (hasActionErrors()) {
232 setActivationStatus("error");
233 }
234
235 // set a special page title
236 setPageTitle("welcome.title");
237
238 return SUCCESS;
239 }
240
241
242 public void myValidate() {
243
244 // if usingSSO, we don't want to error on empty password/username from HTML form.
/*
P/P * Method: void myValidate()
*
* Preconditions:
* this.bean != null
* (soft) init'ed(DEFAULT_ALLOWED_CHARS)
* (soft) log != null
* (soft) init'ed(this.bean.passwordConfirm)
* (soft) this.bean.passwordText != null
* (soft) init'ed(this.bean.userName)
*
* Presumptions:
* org.apache.commons.lang.CharSetUtils:keep(...)@268 != null
* org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@280 != null
* org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@280 != null
* org.apache.roller.weblogger.config.WebloggerConfig:getProperty(...)@251 != null
* org.apache.roller.weblogger.pojos.User:getPassword(...)@253 != null
*
* Postconditions:
* init'ed(this.bean.passwordConfirm)
* this.bean.passwordText != null
* init'ed(this.bean.userName)
* init'ed(this.fromSS0)
*
* Test Vectors:
* java.lang.String:equals(...)@269: {1}, {0}
* java.lang.String:equals(...)@274: {1}, {0}
* java.lang.String:length(...)@263: {1..232-1}, {0}
* org.apache.commons.lang.StringUtils:isEmpty(...)@279: {1}, {0}
* org.apache.roller.weblogger.business.UserManager:getUserByUserName(...)@281: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.config.WebloggerConfig:getBooleanProperty(...)@246: {0}, {1}
* org.apache.roller.weblogger.config.WebloggerConfig:getBooleanProperty(...)@248: {0}, {1}
* org.apache.roller.weblogger.config.WebloggerConfig:getProperty(...)@262: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.ui.core.security.CustomUserRegistry:getUserDetailsFromAuthentication(...)@249: Addr_Set{null}, Inverse{null}
*/
245 setFromSS0(false);
246 boolean usingSSO = WebloggerConfig.getBooleanProperty("users.sso.enabled");
247 if(usingSSO) {
248 boolean storePassword = WebloggerConfig.getBooleanProperty("users.sso.passwords.saveInRollerDb");
249 User fromSSO = CustomUserRegistry.getUserDetailsFromAuthentication();
250 if(fromSSO != null) {
251 String password = WebloggerConfig.getProperty("users.sso.passwords.defaultValue", "<unknown>");
252 if(storePassword) {
253 password = fromSSO.getPassword();
254 }
255 getBean().setPasswordText(password);
256 getBean().setPasswordConfirm(password);
257 getBean().setUserName(fromSSO.getUserName());
258 setFromSS0(true);
259 }
260 }
261
262 String allowed = WebloggerConfig.getProperty("username.allowedChars");
263 if(allowed == null || allowed.trim().length() == 0) {
264 allowed = DEFAULT_ALLOWED_CHARS;
265 }
266
267 // check that username only contains safe characters
268 String safe = CharSetUtils.keep(getBean().getUserName(), allowed);
269 if (!safe.equals(getBean().getUserName()) ) {
270 addError("error.add.user.badUserName");
271 }
272
273 // check that passwords match
274 if(!getBean().getPasswordText().equals(getBean().getPasswordConfirm())) {
275 addError("Register.error.passowordMismatch");
276 }
277
278 // check that username is not taken
279 if(!StringUtils.isEmpty(getBean().getUserName())) try {
280 UserManager mgr = WebloggerFactory.getWeblogger().getUserManager();
281 if(mgr.getUserByUserName(getBean().getUserName(), null) != null) {
282 addError("error.add.user.userNameInUse");
283 // reset user name
284 getBean().setUserName(null);
285 }
286 } catch (WebloggerException ex) {
287 log.error("error checking for user", ex);
288 // TODO: i18n
289 addError("unexpected error");
290 }
291 }
292
293
294 public HttpServletRequest getServletRequest() {
/*
P/P * Method: HttpServletRequest getServletRequest()
*
* Preconditions:
* init'ed(this.servletRequest)
*
* Postconditions:
* return_value == this.servletRequest
* init'ed(return_value)
*/
295 return servletRequest;
296 }
297
298 public void setServletRequest(HttpServletRequest servletRequest) {
/*
P/P * Method: void setServletRequest(HttpServletRequest)
*
* Postconditions:
* this.servletRequest == servletRequest
* init'ed(this.servletRequest)
*/
299 this.servletRequest = servletRequest;
300 }
301
302 public ProfileBean getBean() {
/*
P/P * Method: ProfileBean getBean()
*
* Preconditions:
* init'ed(this.bean)
*
* Postconditions:
* return_value == this.bean
* init'ed(return_value)
*/
303 return bean;
304 }
305
306 public void setBean(ProfileBean bean) {
/*
P/P * Method: void setBean(ProfileBean)
*
* Postconditions:
* this.bean == bean
* init'ed(this.bean)
*/
307 this.bean = bean;
308 }
309
310 public boolean isFromSS0() {
/*
P/P * Method: bool isFromSS0()
*
* Preconditions:
* init'ed(this.fromSS0)
*
* Postconditions:
* return_value == this.fromSS0
* init'ed(return_value)
*/
311 return fromSS0;
312 }
313
314 public void setFromSS0(boolean fromSS0) {
/*
P/P * Method: void setFromSS0(bool)
*
* Postconditions:
* this.fromSS0 == fromSS0
* init'ed(this.fromSS0)
*/
315 this.fromSS0 = fromSS0;
316 }
317
318 public String getActivationStatus() {
/*
P/P * Method: String getActivationStatus()
*
* Preconditions:
* init'ed(this.activationStatus)
*
* Postconditions:
* return_value == this.activationStatus
* init'ed(return_value)
*/
319 return activationStatus;
320 }
321
322 public void setActivationStatus(String activationStatus) {
/*
P/P * Method: void setActivationStatus(String)
*
* Postconditions:
* this.activationStatus == activationStatus
* init'ed(this.activationStatus)
*/
323 this.activationStatus = activationStatus;
324 }
325
326 public String getActivationCode() {
/*
P/P * Method: String getActivationCode()
*
* Preconditions:
* init'ed(this.activationCode)
*
* Postconditions:
* return_value == this.activationCode
* init'ed(return_value)
*/
327 return activationCode;
328 }
329
330 public void setActivationCode(String activationCode) {
/*
P/P * Method: void setActivationCode(String)
*
* Postconditions:
* this.activationCode == activationCode
* init'ed(this.activationCode)
*/
331 this.activationCode = activationCode;
332 }
333
334 }
SofCheck Inspector Build Version : 2.18479
| Register.java |
2009-Jan-02 14:25:20 |
| Register.class |
2009-Sep-04 03:12:45 |