KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > controller > Registration


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 /**
66  * Registration.java
67  *
68  * Copyright 2000, 2001 Jcorporate Ltd.
69  */

70 package com.jcorporate.expresso.services.controller;
71
72 import com.jcorporate.expresso.core.controller.ControllerException;
73 import com.jcorporate.expresso.core.controller.ControllerRequest;
74 import com.jcorporate.expresso.core.controller.ControllerResponse;
75 import com.jcorporate.expresso.core.controller.ServletControllerRequest;
76 import com.jcorporate.expresso.core.db.DBException;
77 import com.jcorporate.expresso.core.dbobj.DBObject;
78 import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
79 import com.jcorporate.expresso.core.misc.ConfigManager;
80 import com.jcorporate.expresso.core.misc.StringUtil;
81 import com.jcorporate.expresso.core.security.DelayThread;
82 import com.jcorporate.expresso.core.security.User;
83 import com.jcorporate.expresso.services.dbobj.RegistrationDomain;
84 import com.jcorporate.expresso.services.dbobj.RegistrationObjectMap;
85 import com.jcorporate.expresso.services.validation.AuthValidationException;
86 import com.jcorporate.expresso.services.validation.ValidationEntry;
87 import org.apache.log4j.Logger;
88
89 import javax.servlet.http.HttpServletRequest JavaDoc;
90 import java.text.NumberFormat JavaDoc;
91 import java.util.ArrayList JavaDoc;
92 import java.util.Iterator JavaDoc;
93
94 /**
95  * <p>Registration Controller. Provides services for self-registering people... ie
96  * sign-up pages on websites. This is the abstract class from which all Registration class
97  * should extend from. This class contains most of the non prompt/process methods</p>
98  * <p/>
99  * Depends on:<br />
100  * <ul>
101  * <li>Login Controller</li>
102  * <li>Email Validator</li>
103  * <li>Registration Validator</li>
104  * </ul>
105  */

106
107 public abstract class Registration
108         extends com.jcorporate.expresso.core.controller.DBController {
109
110     private static Logger log = Logger.getLogger(Registration.class.getName());
111
112     public Registration() {
113         super();
114         this.setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
115     }
116
117
118     /**
119      * Given the request object, get the logged in user associated
120      * with this request.
121      *
122      * @param request The ControllerRequest object associated with this request
123      * @return A built User object for this session.
124      */

125     protected User getRegUser(ControllerRequest request)
126             throws ControllerException {
127
128         String JavaDoc loginName = request.getUser();
129
130         if (loginName.equals("")) {
131             throw new ControllerException("You are not logged-in");
132         }
133
134         User user = null;
135
136         try {
137             user = new User();
138             user.setDataContext(request.getDataContext());
139             user.setLoginName(loginName);
140
141             if (!user.find()) {
142                 throw new ControllerException("Account \"" + loginName +
143                         "\" not found");
144             }
145
146             if (user.getAccountStatus().equals("D")) {
147                 throw new ControllerException("Account \"" + loginName +
148                         "\" has been disabled");
149             } else if (user.getAccountStatus().equals("I")) {
150                 throw new ControllerException("Account \"" + loginName +
151                         "\" has not been activated yet");
152             }
153         } catch (DBException dbe) {
154             throw new ControllerException("Database access error for login \"" +
155                     loginName + "\"", dbe);
156         }
157
158         return user;
159     }
160
161
162     /**
163      * Check a specific UID to see if their registration is complete.
164      * If it is, update the user record to reflect this
165      *
166      * @param request The ControllerRequest object
167      * @param uid The UID
168      * @return true if our records show that the user's registration is complete
169      */

170     protected boolean checkRegComplete(ControllerRequest request, int uid)
171             throws DBException, ControllerException {
172         User myUser = new User();
173         myUser.setDataContext(request.getDataContext());
174         myUser.setUid(uid);
175         myUser.retrieve();
176
177         int regDomId = 1;
178         RegistrationDomain dom = new RegistrationDomain();
179         dom.setDataContext(request.getDataContext());
180         dom.setField("Name", myUser.getRegistrationDomain());
181
182         if (dom.find()) {
183             regDomId = dom.getFieldInt("RegDomId");
184         }
185
186         RegistrationObjectMap rm = new RegistrationObjectMap();
187         rm.setDataContext(request.getDataContext());
188         rm.setField("RegDomId", regDomId);
189
190         boolean regComplete = true;
191         RegistrationObjectMap oneMap = null;
192
193         for (Iterator JavaDoc i = rm.searchAndRetrieveList().iterator(); i.hasNext();) {
194             oneMap = (RegistrationObjectMap) i.next();
195
196             int min = oneMap.getFieldInt("RecMin");
197             SecuredDBObject oneObj = loadDBObject(request,
198                     oneMap.getField("RegObj"));
199             oneObj.setField(oneMap.getField("UidField"), uid);
200
201             if (oneObj.count() < min) {
202                 regComplete = false;
203                 break;
204             }
205         }
206
207         myUser.setRegComplete(regComplete);
208         myUser.update();
209
210         return regComplete;
211     }
212
213     /**
214      * Function called to suspend thread execution for x many seconds before
215      * offering a retry to login. Helps to slow down brute force attacks.
216      * [a 40,000 word dictionary attack prolonged by 3 seconds a piece
217      * adds potentially 33 hours to the attack time. Yes this can be partially bypassed
218      * through simultaneous requests, but it still adds significant reponse time]
219      */

220     protected void delayLogin() {
221         DelayThread.delay();
222     }
223
224
225     /**
226      * Format a value for display in the HTML being returned to the client
227      *
228      * @param fieldType The type of the field to format
229      * @param fieldValue The value of the field
230      * @return String The formatted field
231      * @throws ControllerException If the field format information could not be
232      * determined
233      */

234     protected String JavaDoc displayValue(String JavaDoc fieldType, String JavaDoc fieldValue)
235             throws ControllerException {
236         try {
237             if (fieldType.equalsIgnoreCase("money")) {
238                 if (!fieldValue.equals("")) {
239                     return NumberFormat.getCurrencyInstance().format(new Double JavaDoc(fieldValue).doubleValue());
240                 }
241             } else {
242                 return fieldValue;
243             }
244         } catch (NumberFormatException JavaDoc ne) {
245             throw new ControllerException("Number for field not in a " +
246                     "valid numeric format:" +
247                     fieldValue, ne);
248         }
249
250         return null;
251     } /* displayValue(String, String) */
252
253
254     /**
255      * Returns the db listed based upon the dbobj parameter.
256      *
257      * @param request The ControllerRequest object
258      * @return the data context name that we're supposed to register with
259      */

260     public String JavaDoc getDB(ControllerRequest request)
261             throws ControllerException {
262         String JavaDoc dbobj = StringUtil.notNull(request.getParameter("dbobj"));
263
264         if (dbobj.equals("")) {
265             throw new ControllerException("dbobj parameter was not specified");
266         }
267
268         return dbobj;
269     }
270
271     /**
272      * ?????
273      *
274      * @param fieldName ????
275      * @return currently null
276      */

277     protected String JavaDoc getDefaultValue(String JavaDoc fieldName) {
278         return null;
279     }
280
281
282     /**
283      * Based upon the user and the ControllerRequest, return the registration
284      * domain belonging to this session
285      *
286      * @param request The ControllerRequest of this request.
287      * @param user the user associated with this session.
288      * @return a built registration domain object
289      */

290     protected RegistrationDomain getRegDomain(ControllerRequest request,
291                                               User user)
292             throws ControllerException {
293         RegistrationDomain rd = null;
294
295         try {
296             String JavaDoc domain = user.getRegistrationDomain();
297             rd = new RegistrationDomain();
298             rd.setDataContext(request.getDataContext());
299             rd.setField("Name", domain);
300
301             if (!rd.find()) {
302                 throw new ControllerException("Domain " + domain +
303                         " not created yet");
304             }
305         } catch (DBException dbe) {
306             throw new ControllerException("Database error", dbe);
307         }
308
309         return rd;
310     }
311
312
313     /**
314      * Instantiated a dbobject based upon the request and dbobject requested.
315      *
316      * @param request the ControllerRequest Object
317      * @param dbobj The name of the dbobject to instantiate
318      * @return a fully instantiated SecuredDbObject
319      */

320     protected SecuredDBObject loadDBObject(ControllerRequest request,
321                                            String JavaDoc dbobj)
322             throws ControllerException {
323         SecuredDBObject db = null;
324
325         try {
326             db = (SecuredDBObject) Class.forName(dbobj).newInstance();
327             db.setRequestingUid(SecuredDBObject.SYSTEM_ACCOUNT);
328             db.setDataContext(request.getDataContext());
329             db.setLocale(request.getLocale());
330         } catch (Exception JavaDoc e) {
331             throw new ControllerException("Instantiate failed for database object " + dbobj, e);
332         }
333
334         return db;
335     }
336
337
338     /**
339      * Return the name of the next record required for a complete
340      * registration, or null of no more are required.
341      *
342      * @param request the ControllerRequest Object
343      * @return java.lang.String that is the name of the next dbobject required
344      * to be filled out for registration
345      */

346     public String JavaDoc nextToAdd(ControllerRequest request)
347             throws ControllerException {
348         if (log.isDebugEnabled()) {
349             log.debug("Checking if user '" + request.getUser() +
350                     "' is fully registered, db '" + request.getDataContext() +
351                     "'");
352         }
353         try {
354             User user = new User();
355             user.setDataContext(request.getDataContext());
356             user.setUid(request.getUid());
357             user.retrieve();
358             if (log.isDebugEnabled()) {
359                 log.debug("Checking registration for used id '" + user.getUid() +
360                         "'");
361             }
362
363             RegistrationDomain rd = new RegistrationDomain();
364             rd.setDataContext(request.getDataContext());
365             rd.setField("Name", user.getRegistrationDomain());
366
367             if (!rd.find()) {
368                 throw new ControllerException("Domain " +
369                         user.getRegistrationDomain() +
370                         " not created yet");
371             }
372
373             RegistrationObjectMap rom = new RegistrationObjectMap();
374             rom.setDataContext(request.getDataContext());
375             rom.setField("RegDomId", rd.getField("RegDomId"));
376
377             RegistrationObjectMap oneRom = null;
378
379             for (Iterator JavaDoc e = rom.searchAndRetrieveList("RegOrder").iterator();
380                  e.hasNext();) {
381                 oneRom = (RegistrationObjectMap) e.next();
382
383
384                 DBObject db = isRegistrationObjectNeeded(request, user, oneRom);
385
386                 if (db != null) {
387                     return db.getClass().getName();
388                 }
389             }
390         } catch (DBException de) {
391             throw new ControllerException(de);
392         }
393
394         return null;
395     }
396
397
398     /**
399      * Loads the dbobject and returns it if it is required.
400      *
401      * @param request The framework's controller Request object
402      * @param user The instantiated user for the registration.
403      * @param rom The RegistrationObjectMap to count.
404      * @return boolean if the record count is less than the minimum needed.
405      */

406     protected DBObject isRegistrationObjectNeeded(ControllerRequest request,
407                                                   User user,
408                                                   RegistrationObjectMap rom)
409             throws DBException {
410
411         int min;
412         int records = 0;
413
414         DBObject returnObject = null;
415         rom.setDataContext(request.getDataContext());
416         min = rom.getFieldInt("RecMin");
417
418
419         if (log.isDebugEnabled()) {
420             log.debug("Need at least " + min + " records for '" +
421                     rom.getField("RegObj") + "'");
422         }
423
424         try {
425             returnObject = (DBObject) Class.forName(rom.getField("RegObj")).newInstance();
426         } catch (Exception JavaDoc ex) {
427             log.error("isRegistrationObjectNeeded() Dynanamic load failed.", ex);
428             throw new DBException("Dynamic load failed for " +
429                     rom.getField("RegObj"),
430                     ex);
431         }
432
433         returnObject.setDataContext(request.getDataContext());
434
435         if (user != null) {
436             String JavaDoc fieldName = rom.getField("UidField");
437             returnObject.setField(fieldName, user.getUid());
438             if (log.isDebugEnabled()) {
439                 log.debug("Looking for '" + returnObject.getClass().getName() +
440                         "' record with " + fieldName + " = " +
441                         user.getUid() + " in db " + request.getDataContext());
442             }
443
444             records = returnObject.count();
445             if (log.isDebugEnabled()) {
446                 log.debug("Found " + records);
447             }
448         }
449
450         if (records < min) {
451             if (log.isDebugEnabled()) {
452                 log.debug("There were '" + records + "' records, but " +
453                         min + " are required for '" +
454                         returnObject.getClass().getName() + "'");
455             }
456
457             return returnObject;
458
459         } else {
460             if (log.isDebugEnabled()) {
461                 log.debug("There were '" + records + "' records for " +
462                         returnObject.getClass().getName() +
463                         ", so we don't need any more.");
464             }
465
466             return null;
467         }
468     }
469
470
471     /**
472      * Returns the required registration dbobjects... ie, what's the minimum
473      * to do?
474      *
475      * @param request The System ControllerRequest
476      * @param rd The currently set up RegistrationDomain for this user
477      * @param user (optional) if null means that the user is new and all normally
478      * required dbobjects will be returned.
479      * @return a DBObject array of required dbobjects to be filled out
480      * @throws DBException if there's an error mapping the registration domains
481      * and building the DBObjects.
482      */

483     protected DBObject[] getRequiredDBObjects(ControllerRequest request,
484                                               RegistrationDomain rd,
485                                               User user)
486             throws DBException {
487
488         ArrayList JavaDoc dbobjects = new ArrayList JavaDoc();
489
490         if (log.isDebugEnabled()) {
491             log.debug("Getting the registration objects that user '" + request.getUser() +
492                     "' needs, db='" + request.getDataContext() +
493                     "'");
494         }
495
496 //
497
// User user = new User();
498
// user.setDBName(request.getDBName());
499
// user.setUid(request.getParameter("uid"));
500
// user.retrieve();
501
// if (log.isDebugEnabled()) {
502
// log.debug("Checking registration for used id '" + user.getUid() +
503
// "'");
504
// }
505

506 // RegistrationDomain rd = new RegistrationDomain();
507
// rd.setDBName(request.getDBName());
508
// rd.setField("Name", user.getRegistrationDomain());
509

510         if (!rd.find()) {
511             throw new DBException("Domain " +
512                     user.getRegistrationDomain() +
513                     " not created yet");
514         }
515
516         RegistrationObjectMap rom = new RegistrationObjectMap(SecuredDBObject.SYSTEM_ACCOUNT);
517         rom.setDataContext(request.getDataContext());
518         rom.setField("RegDomId", rd.getField("RegDomId"));
519
520         RegistrationObjectMap oneRom = null;
521
522         for (Iterator JavaDoc e = rom.searchAndRetrieveList("RegOrder").iterator();
523              e.hasNext();) {
524             oneRom = (RegistrationObjectMap) e.next();
525
526
527             DBObject db = isRegistrationObjectNeeded(request, user, oneRom);
528
529             if (db != null) {
530                 if (user != null) {
531                     db.setField(oneRom.getField("UidField"), user.getUid());
532                 }
533                 dbobjects.add(db);
534
535             }
536         }
537
538         return (DBObject[]) dbobjects.toArray(new DBObject[dbobjects.size()]);
539     }
540
541
542     /**
543      * Given the ControllerRequest get what the login controller is. If the request
544      * doesn't have the loginController parameter, then it uses the default Expresso
545      * login controller instead.
546      *
547      * @param request The ControllerRequest that may or may not have the loginController
548      * parameter.
549      * @return The classname of the login controller to use.
550      */

551     protected String JavaDoc getLoginController(ControllerRequest request) {
552         final String JavaDoc defaultController = com.jcorporate.expresso.services.controller
553
                .LoginController.class.getName();
554         boolean defaultValue = false;
555         String JavaDoc controller = request.getParameter("login");
556         if (controller == null) {
557             defaultValue = true;
558             try {
559                 controller = this.getSchemaInstance()
560                         .getLoginController().getClass().getName();
561             } catch (ControllerException ex) {
562                 controller = defaultController;
563             }
564         }
565
566         //
567
//Check if the requested login controller is actually instantiatable.
568
//
569
if (!defaultValue) {
570             try {
571                 ConfigManager.getControllerFactory()
572                         .getController(controller);
573             } catch (Exception JavaDoc e) {
574                 log.error("Unable to instantiate login controller: "
575                         + controller +
576                         " . Using default login controller instead", e);
577
578                 controller = defaultController;
579             }
580         }
581
582         return controller;
583     }
584
585     /**
586      * Creates the validation entry for validating email.
587      *
588      * @param request The ControllerRequest object
589      * @param response The ControllerResponse object
590      * @param user the user that is registering
591      * @param rd The registration domain that the user is signing up for
592      * @param loginControllerName the name of the login controller used
593      * @throws DBException upon data access error
594      * @throws ControllerException for other errors
595      */

596     protected void setupEmailValidation(ControllerRequest request,
597                                         ControllerResponse response, User user,
598                                         RegistrationDomain rd,
599                                         String JavaDoc loginControllerName)
600             throws DBException, ControllerException {
601
602         String JavaDoc emailAuthCode = user.getEmailAuthCode();
603         String JavaDoc loginName = user.getLoginName();
604         user.setEmailValCode(emailAuthCode);
605         user.update();
606
607         HttpServletRequest JavaDoc hreq = (HttpServletRequest JavaDoc) ((ServletControllerRequest) request).getServletRequest();
608
609         try {
610
611             ValidationEntry ve = new ValidationEntry(request.getDataContext());
612             ve.expiresAfter(72, 0, 0); //Expires after 72 hours
613
ve.setValidationHandler(com.jcorporate.expresso.services.validation.LoginEmailValidator.class.getName());
614             ve.setTitle("Registration Email Validation");
615             ve.setDesc("user=" + loginName + ", db=" + request.getDataContext());
616             ve.setServer(hreq.getServerName());
617             ve.setPort(Integer.toString(hreq.getServerPort()));
618             ve.setContextPath(hreq.getContextPath());
619             ve.addParam("db", request.getDataContext());
620             ve.addParam("UserName", loginName);
621             ve.addParam("RegistrationController", this.getClass().getName());
622             ve.addParam("LoginController", loginControllerName);
623             ve.submit();
624         } catch (AuthValidationException avex) {
625             delayLogin();
626             throw new ControllerException("Validation framework exception",
627                     avex);
628         }
629     }
630
631
632 }
Popular Tags