1 package org.apache.turbine.services.security.db;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.ArrayList;
58 import java.util.Iterator;
59 import java.util.List;
60 import org.apache.torque.om.BaseObject;
61 import org.apache.torque.util.Criteria;
62 import org.apache.turbine.om.security.User;
63 import org.apache.turbine.om.security.peer.TurbineUserPeer;
64 import org.apache.turbine.services.security.TurbineSecurity;
65 import org.apache.turbine.services.security.UserManager;
66 import org.apache.turbine.util.security.DataBackendException;
67 import org.apache.turbine.util.security.EntityExistsException;
68 import org.apache.turbine.util.security.PasswordMismatchException;
69 import org.apache.turbine.util.security.UnknownEntityException;
70
71 /***
72 * An UserManager performs {@link org.apache.turbine.om.security.User} objects
73 * related tasks on behalf of the
74 * {@link org.apache.turbine.services.security.BaseSecurityService}.
75 *
76 * This implementation uses a relational database for storing user data. It
77 * expects that the User interface implementation will be castable to
78 * {@link org.apache.turbine.om.BaseObject}.
79 *
80 * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
81 * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
82 * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
83 * @author <a href="mailto:cberry@gluecode.com">Craig D. Berry</a>
84 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
85 * @version $Id: DBUserManager.java,v 1.3 2002/07/11 07:34:31 mpoeschl Exp $
86 */
87 public class DBUserManager implements UserManager
88 {
89 /***
90 * Check whether a specified user's account exists.
91 *
92 * The login name is used for looking up the account.
93 *
94 * @param user The user to be checked.
95 * @return true if the specified account exists
96 * @throws DataBackendException if there was an error accessing
97 * the data backend.
98 */
99 public boolean accountExists( User user )
100 throws DataBackendException
101 {
102 return accountExists(user.getUserName());
103 }
104
105 /***
106 * Check whether a specified user's account exists.
107 *
108 * The login name is used for looking up the account.
109 *
110 * @param usename The name of the user to be checked.
111 * @return true if the specified account exists
112 * @throws DataBackendException if there was an error accessing
113 * the data backend.
114 */
115 public boolean accountExists( String username )
116 throws DataBackendException
117 {
118 Criteria criteria = new Criteria();
119 criteria.add(TurbineUserPeer.USERNAME, username);
120 List users;
121 try
122 {
123 users = TurbineUserPeer.doSelect(criteria);
124 }
125 catch(Exception e)
126 {
127 throw new DataBackendException(
128 "Failed to check account's presence", e);
129 }
130 if ( users.size() > 1 )
131 {
132 throw new DataBackendException(
133 "Multiple Users with same username '" + username + "'");
134 }
135 return(users.size() == 1);
136 }
137
138 /***
139 * Retrieve a user from persistent storage using username as the
140 * key.
141 *
142 * @param username the name of the user.
143 * @return an User object.
144 * @exception UnknownEntityException if the user's account does not
145 * exist in the database.
146 * @exception DataBackendException if there is a problem accessing the
147 * storage.
148 */
149 public User retrieve( String username )
150 throws UnknownEntityException, DataBackendException
151 {
152 Criteria criteria = new Criteria();
153 criteria.add( TurbineUserPeer.USERNAME, username );
154 List users;
155 try
156 {
157 users = TurbineUserPeer.doSelect(criteria);
158 }
159 catch(Exception e)
160 {
161 throw new DataBackendException("Failed to retrieve user '" +
162 username + "'", e);
163 }
164 if ( users.size() > 1 )
165 {
166 throw new DataBackendException(
167 "Multiple Users with same username '" + username + "'");
168 }
169 if ( users.size() == 1 )
170 {
171 return (User)users.get(0);
172 }
173 throw new UnknownEntityException("Unknown user '" + username + "'");
174 }
175
176 /***
177 * Retrieve a set of users that meet the specified criteria.
178 *
179 * As the keys for the criteria, you should use the constants that
180 * are defined in {@link User} interface, plus the names
181 * of the custom attributes you added to your user representation
182 * in the data storage. Use verbatim names of the attributes -
183 * without table name prefix in case of DB implementation.
184 *
185 * @param criteria The criteria of selection.
186 * @return a List of users meeting the criteria.
187 * @throws DataBackendException if there is a problem accessing the
188 * storage.
189 */
190 public User[] retrieve( Criteria criteria )
191 throws DataBackendException
192 {
193 Iterator keys = criteria.keySet().iterator();
194 while(keys.hasNext())
195 {
196 String key = (String)keys.next();
197 // set the table name for all attached criterion
198 Criteria.Criterion[] criterion = criteria
199 .getCriterion(key).getAttachedCriterion();
200 for (int i=0;i<criterion.length;i++)
201 {
202 String table = criterion[i].getTable();
203 if ( table == null || "".equals(table) )
204 {
205 criterion[i].setTable(TurbineUserPeer.getTableName());
206 }
207 }
208 }
209 List users = new ArrayList(0);
210 try
211 {
212 users = TurbineUserPeer.doSelect(criteria);
213 }
214 catch(Exception e)
215 {
216 throw new DataBackendException("Failed to retrieve users", e);
217 }
218 return (User[])users.toArray(new User[0]);
219 }
220
221 /***
222 * Retrieve a user from persistent storage using username as the
223 * key, and authenticate the user. The implementation may chose
224 * to authenticate to the server as the user whose data is being
225 * retrieved.
226 *
227 * @param username the name of the user.
228 * @param password the user supplied password.
229 * @return an User object.
230 * @exception PasswordMismatchException if the supplied password was
231 * incorrect.
232 * @exception UnknownEntityException if the user's account does not
233 * exist in the database.
234 * @exception DataBackendException if there is a problem accessing the
235 * storage.
236 */
237 public User retrieve( String username, String password )
238 throws PasswordMismatchException, UnknownEntityException,
239 DataBackendException
240 {
241 User user = retrieve(username);
242 authenticate(user, password);
243 return user;
244 }
245
246 /***
247 * Save an User object to persistent storage. User's account is
248 * required to exist in the storage.
249 *
250 * @param user an User object to store.
251 * @exception UnknownEntityException if the user's account does not
252 * exist in the database.
253 * @exception DataBackendException if there is a problem accessing the
254 * storage.
255 */
256 public void store(User user)
257 throws UnknownEntityException, DataBackendException
258 {
259 if(!accountExists(user))
260 {
261 throw new UnknownEntityException("The account '" +
262 user.getUserName() + "' does not exist");
263 }
264 Criteria criteria = TurbineUserPeer.buildCriteria(user);
265 try
266 {
267 TurbineUserPeer.doUpdate(criteria);
268 }
269 catch(Exception e)
270 {
271 throw new DataBackendException("Failed to save user object", e);
272 }
273 }
274
275 /***
276 * Authenticate an User with the specified password. If authentication
277 * is successful the method returns nothing. If there are any problems,
278 * exception was thrown.
279 *
280 * @param user an User object to authenticate.
281 * @param password the user supplied password.
282 * @exception PasswordMismatchException if the supplied password was
283 * incorrect.
284 * @exception UnknownEntityException if the user's account does not
285 * exist in the database.
286 * @exception DataBackendException if there is a problem accessing the
287 * storage.
288 */
289 public void authenticate( User user, String password )
290 throws PasswordMismatchException, UnknownEntityException,
291 DataBackendException
292 {
293 if(!accountExists(user))
294 {
295 throw new UnknownEntityException("The account '" +
296 user.getUserName() + "' does not exist");
297 }
298 String encrypted = TurbineSecurity.encryptPassword(password);
299 if(!user.getPassword().equals(encrypted))
300 {
301 throw new PasswordMismatchException("The passwords do not match");
302 }
303 }
304
305 /***
306 * Change the password for an User.
307 *
308 * @param user an User to change password for.
309 * @param password the new password.
310 * @exception PasswordMismatchException if the supplied password was
311 * incorrect.
312 * @exception UnknownEntityException if the user's account does not
313 * exist in the database.
314 * @exception DataBackendException if there is a problem accessing the
315 * storage.
316 */
317 public void changePassword( User user, String oldPassword,
318 String newPassword )
319 throws PasswordMismatchException, UnknownEntityException,
320 DataBackendException
321 {
322 String encrypted = TurbineSecurity.encryptPassword(oldPassword);
323 if(!accountExists(user))
324 {
325 throw new UnknownEntityException("The account '" +
326 user.getUserName() + "' does not exist");
327 }
328 if(!user.getPassword().equals(encrypted))
329 {
330 throw new PasswordMismatchException(
331 "The supplied old password for '" + user.getUserName() +
332 "' was incorrect");
333 }
334 user.setPassword(TurbineSecurity.encryptPassword(newPassword));
335 // save the changes in the database imediately, to prevent the password
336 // being 'reverted' to the old value if the user data is lost somehow
337 // before it is saved at session's expiry.
338 store(user);
339 }
340
341 /***
342 * Forcibly sets new password for an User.
343 *
344 * This is supposed by the administrator to change the forgotten or
345 * compromised passwords. Certain implementatations of this feature
346 * would require administrative level access to the authenticating
347 * server / program.
348 *
349 * @param user an User to change password for.
350 * @param password the new password.
351 * @exception UnknownEntityException if the user's record does not
352 * exist in the database.
353 * @exception DataBackendException if there is a problem accessing the
354 * storage.
355 */
356 public void forcePassword( User user, String password )
357 throws UnknownEntityException, DataBackendException
358 {
359 if(!accountExists(user))
360 {
361 throw new UnknownEntityException("The account '" +
362 user.getUserName() + "' does not exist");
363 }
364 user.setPassword(TurbineSecurity.encryptPassword(password));
365 // save the changes in the database immediately, to prevent the
366 // password being 'reverted' to the old value if the user data
367 // is lost somehow before it is saved at session's expiry.
368 store(user);
369 }
370
371 /***
372 * Creates new user account with specified attributes.
373 *
374 * @param user the object describing account to be created.
375 * @throws DataBackendException if there was an error accessing
376 the data backend.
377 * @throws EntityExistsException if the user account already exists.
378 */
379 public void createAccount( User user, String initialPassword )
380 throws EntityExistsException, DataBackendException
381 {
382 if(accountExists(user))
383 {
384 throw new EntityExistsException("The account '" +
385 user.getUserName() + "' already exists");
386 }
387 String encrypted = TurbineSecurity.encryptPassword(initialPassword);
388 user.setPassword(encrypted);
389 Criteria criteria = TurbineUserPeer.buildCriteria(user);
390 try
391 {
392 // we can safely assume that BaseObject derivate is used as User
393 // implementation with this UserManager
394 ((BaseObject)user).setPrimaryKey(
395 TurbineUserPeer.doInsert(criteria));
396 }
397 catch(Exception e)
398 {
399 throw new DataBackendException("Failed to create account '" +
400 user.getUserName() + "'", e);
401 }
402 }
403
404 /***
405 * Removes an user account from the system.
406 *
407 * @param user the object describing the account to be removed.
408 * @throws DataBackendException if there was an error accessing
409 the data backend.
410 * @throws UnknownEntityException if the user account is not present.
411 */
412 public void removeAccount( User user )
413 throws UnknownEntityException, DataBackendException
414 {
415 if(!accountExists(user))
416 {
417 throw new UnknownEntityException("The account '" +
418 user.getUserName() + "' does not exist");
419 }
420 Criteria criteria = new Criteria();
421 criteria.add(TurbineUserPeer.USERNAME, user.getUserName());
422 try
423 {
424 TurbineUserPeer.doDelete(criteria);
425 }
426 catch(Exception e)
427 {
428 throw new DataBackendException("Failed to remove account '" +
429 user.getUserName() + "'", e);
430 }
431 }
432 }
This page was automatically generated by Maven