001: /*
002: * Enhydra Java Application Server
003: * The Initial Developer of the Original Code is Lutris Technologies Inc.
004: * Portions created by Lutris are Copyright (C) 1997-2000 Lutris Technologies
005: * Inc.
006: * All Rights Reserved.
007: *
008: * The contents of this file are subject to the Enhydra Public License Version
009: * 1.0 (the "License"); you may not use this file except in compliance with the
010: * License. You may obtain a copy of the License at
011: * http://www.enhydra.org/software/license/epl.html
012: *
013: * Software distributed under the License is distributed on an "AS IS" basis,
014: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
015: * License for the specific language governing rights and limitations under the
016: * License.
017: *
018: *
019: */
020:
021: package golfShop.business.user;
022:
023: import java.io.*;
024: import java.net.*;
025: import java.security.*;
026: import java.util.*;
027: import com.lutris.appserver.server.user.*;
028: import com.lutris.appserver.server.session.*;
029: import com.lutris.util.*;
030: import golfShop.data.user.UserDOImpl;
031:
032: import golfShop.business.item.ItemQuery;
033: import golfShop.business.cart.CartImpl;
034: import golfShop.spec.user.*;
035: import golfShop.spec.LoginException;
036:
037: /**
038: * The User Manager Business Object. This object handles requests
039: * for user specific data and login verification.
040: *
041: * @author Shawn McMurdo
042: * @version $Revision: 1.1 $
043: */
044: public class GolfShopUserManagerImpl implements GolfShopUserManager {
045: /**
046: * Username and password verification was successful.
047: */
048: public final int AUTH_OK = 0;
049:
050: /**
051: * Username and password verification failed because of
052: * authentication failure.
053: * AUTH_FAILED is thrown by a login request if the username
054: * does not exist in the User database, the password was
055: * incorrect, or an otherwise unknown error occured during the login
056: * request. The reason for the third case is that it is not wise from a
057: * security standpoint to give unknown users potentially valuable
058: * information about possible errors occuring in the login facility.
059: */
060: public final int AUTH_FAILED = 1;
061:
062: /**
063: * UNKNOWN_ERROR is indicated by methods other than the user login method
064: * to report that an unknown error has prevented a request from
065: * being processed. The UserManager.login() method reports
066: * AUTH_FAILED for unknown errors for security reasons.
067: */
068: public final int UNKNOWN_ERROR = 2;
069:
070: /**
071: * IO_ERROR is thrown by methods of the UserManager if a
072: * communication failure prevented access to required information
073: * from the User database or elsewhere.
074: */
075: public final int IO_ERROR = 3;
076:
077: /**
078: * PERMISSION_DENIED indicates that a UserManager method has
079: * failed because the requesting user has insufficient privilege
080: * to perform the requested operation.
081: */
082: public final int PERMISSION_DENIED = 4;
083:
084: /**
085: * MULTIPLE_LOGIN indicates that a user has attempted to login
086: * more than the maximum number of allowable sessions.
087: */
088: public final int MULTIPLE_LOGIN = 5;
089:
090: /**
091: * ACCOUNT_DISABLED indicates that the account for the
092: * requested user has been disabled by the administrator.
093: */
094: public final int ACCOUNT_DISABLED = 6;
095:
096: /**
097: * PASSWORD_TYPO indicates that the two copies of the new
098: * password were not identical, implying that a user may have
099: * accidentally typed a new password incorrectly.
100: */
101: public final int PASSWORD_TYPO = 7;
102:
103: /**
104: * PASSWORD_WEAK indicates that the UserManager refused
105: * to accept a user's password change request because the new password
106: * does not comply with policy relating to password strength. For
107: * example, the password may not have been long enough or contained
108: * enough nonalphabetic characters.
109: */
110: public final int PASSWORD_WEAK = 8;
111:
112: /**
113: * UNKNOWN_HOST indicates that a login attempt failed because the IP
114: * address of the requester's host was not furnished with the login
115: * request.
116: */
117: public final int UNKNOWN_HOST = 9;
118:
119: /**
120: * USERNAME_ALREADY_EXISTS indicates that a new account could not be
121: * created because an account with that same username already exists.
122: */
123: public final int USERNAME_ALREADY_EXISTS = 10;
124:
125: /**
126: * The GolfShop application instance that this manager is
127: * a part of.
128: */
129:
130: /**
131: * Process an authentication request. Verify
132: * that the user's account and password are valid.
133: *
134: * @param username The username for the account.
135: * @param password The password entered by the user.
136: *
137: * @returns An int representing success (AUTH_OK), or a failure
138: * reason (AUTH_FAILED, AUTH_IO_ERROR).
139: */
140: public int authenticate(String username, String password) {
141: // Get user from database.
142: UserDO theUser = UserDOImpl.lookupUser(username);
143: if (theUser == null) {
144: // No such user.
145: return AUTH_FAILED;
146: }
147: // Check password.
148: return theUser.authenticate(password);
149: }
150:
151: /**
152: * Process a login request issued by a user. Verify
153: * that the user's account and password are valid.
154: * A username may be logged in multiple times. If the login is
155: * sucessfull, the session object's user pointer is set to the
156: * user data object represeting the logged in username.
157: *
158: * @param username The user identification entered by the user.
159: * @param password The password entered by the user.
160: * @param session The session object for the broweser attempting the
161: * login.
162: * @exception LoginException Thrown if authentication fails.
163: */
164: public void login(String username, String password, Session session)
165: throws LoginException, SessionException {
166: Session standardSession = (Session) session;
167: SessionManager standardSessionManager = (SessionManager) session
168: .getSessionManager();
169: SessionData sd = standardSession.getSessionData();
170: // Verify the login.
171: // Get user from database.
172: UserDO theUser = UserDOImpl.lookupUser(username);
173: if (theUser == null)
174: // No such user.
175: refuse(AUTH_FAILED);
176: // Check password.
177: if (theUser.authenticate(password) != AUTH_OK)
178: refuse(AUTH_FAILED);
179:
180: /*
181: * Even if the user is already logged in, allow the login.
182: * If they are already logged in, they have already connected to
183: * the Lutris Business Server, and so they already have a session
184: * cookie and an assocated session object exists in the session
185: * manager.
186: * Either way, give them a new (empty) cart.
187: *
188: * This is an important policy decision. We could re-use the
189: * existing session key, so the two users share one cart. Or we
190: * could have the new login to terminate the old session by
191: * elimintating the previous session key. Or we could deny the
192: * new login. It depends on how you want your application to behave.
193: */
194: if (standardSession.getUser() != null) {
195: standardSession.clearUser();
196: try {
197: sd.remove("cart"); // Throw away old cart.
198: } catch (KeywordValueException e) {
199: throw new FatalExceptionError(e);
200: }
201: }
202:
203: /*
204: * Save the user in the session. This signifies that the
205: * session is valid, and the user is logged in. When the user fisrt
206: * connects to this application, she will be given a new session,
207: * but the user is not logged in so the user pointer is null.
208: * That is, new sessions have an internal user pointer. It is
209: * initally null. Until we set it, the user for a given session
210: * is not considered logged in.
211: */
212: standardSession.setUser((UserDOImpl) theUser);
213:
214: /*
215: * Save the cart in the session data so it is available for each
216: * request they make.
217: */
218: try {
219: sd.set("cart", new CartImpl(ItemQuery.global));
220: } catch (KeywordValueException e) {
221: throw new LoginException(UNKNOWN_ERROR);
222: }
223: }
224:
225: /**
226: *
227: * @param session The session to log out.
228: */
229: public void logout(Session session) throws SessionException {
230: if (session != null) {
231: /*DTDT 260604*/
232: try {
233: SessionData sessionData = session.getSessionData();
234: String[] sessinDataKeys = sessionData.leafKeys();
235: for (int i = 0; i < sessinDataKeys.length; i++) {
236: sessionData.remove(sessinDataKeys[i]);
237: }
238: } catch (Exception e) {
239: throw new SessionException(e.getMessage());
240: }
241:
242: //session.getSessionManager().deleteSession(session.getSessionKey());
243: }
244: }
245:
246: /**
247: * Internal convenience method to throw a login refusal error.
248: *
249: * @param why The error code indicating why the request failed.
250: */
251: private static final void refuse(int why) throws LoginException {
252: throw new LoginException(why);
253: }
254:
255: /**
256: * This function creates a new account, then calls login() above to
257: * create the session etc...
258: *
259: * @param username The user identification entered by the user.
260: * @param password The password entered by the user.
261: * @returns A cookie representing the user's new session.
262: * @exception LoginException Thrown if authentication fails.
263: */
264: public void createAccount(String username, String password,
265: String address1, String address2, String city,
266: String state, String zip, String creditCard, String email,
267: Session session) throws LoginException, SessionException {
268:
269: // Verify the username is available.
270: // Get user from database.
271: UserDO theUser = UserDOImpl.lookupUser(username);
272: if (theUser != null) {
273: // That user name is already taken.
274: refuse(USERNAME_ALREADY_EXISTS);
275: }
276: // Create the new user account/data-object.
277: UserDO newUser = UserDOImpl
278: .createUser(username, password, address1, address2,
279: city, state, zip, creditCard, email);
280: if (newUser == null)
281: refuse(UNKNOWN_ERROR);
282: // Now that the account exists, log in like normal.
283: login(username, password, session);
284: }
285:
286: /*
287: * This is just defined so that we meet the UserManager interface
288: * specs. In a larger application this would be usefull, but in this
289: * demo it is not used.
290: */
291: public User getUser(String username) {
292: return (User) UserDOImpl.lookupUser(username);
293: }
294: }
|