Coverage report

  %line %branch
org.apache.turbine.services.security.torque.TorqueUserManager
79% 
91% 

 1  
 package org.apache.turbine.services.security.torque;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2004 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.util.ArrayList;
 20  
 import java.util.Iterator;
 21  
 import java.util.List;
 22  
 
 23  
 import org.apache.commons.configuration.Configuration;
 24  
 
 25  
 import org.apache.commons.lang.StringUtils;
 26  
 
 27  
 import org.apache.commons.logging.Log;
 28  
 import org.apache.commons.logging.LogFactory;
 29  
 
 30  
 import org.apache.torque.om.Persistent;
 31  
 import org.apache.torque.util.Criteria;
 32  
 
 33  
 import org.apache.turbine.om.security.User;
 34  
 import org.apache.turbine.services.InitializationException;
 35  
 import org.apache.turbine.services.security.TurbineSecurity;
 36  
 import org.apache.turbine.services.security.UserManager;
 37  
 import org.apache.turbine.util.security.DataBackendException;
 38  
 import org.apache.turbine.util.security.EntityExistsException;
 39  
 import org.apache.turbine.util.security.PasswordMismatchException;
 40  
 import org.apache.turbine.util.security.UnknownEntityException;
 41  
 
 42  
 /**
 43  
  * An UserManager performs {@link org.apache.turbine.om.security.User}
 44  
  * objects related tasks on behalf of the
 45  
  * {@link org.apache.turbine.services.security.BaseSecurityService}.
 46  
  *
 47  
  * This implementation uses a relational database for storing user data. It
 48  
  * expects that the User interface implementation will be castable to
 49  
  * {@link org.apache.torque.om.BaseObject}.
 50  
  *
 51  
  * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
 52  
  * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
 53  
  * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
 54  
  * @author <a href="mailto:cberry@gluecode.com">Craig D. Berry</a>
 55  
  * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
 56  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 57  
  * @version $Id: TorqueUserManager.java,v 1.3.2.4 2004/10/08 12:09:44 henning Exp $
 58  
  */
 59  8
 public class TorqueUserManager
 60  
     implements UserManager
 61  
 {
 62  
     /** Logging */
 63  16
     private static Log log = LogFactory.getLog(TorqueUserManager.class);
 64  
 
 65  
     /**
 66  
      * Initializes the UserManager
 67  
      *
 68  
      * @param conf A Configuration object to init this Manager
 69  
      *
 70  
      * @throws InitializationException When something went wrong.
 71  
      */
 72  
     public void init(Configuration conf)
 73  
         throws InitializationException
 74  
     {
 75  8
         UserPeerManager.init(conf);
 76  8
     }
 77  
 
 78  
     /**
 79  
      * Check whether a specified user's account exists.
 80  
      *
 81  
      * The login name is used for looking up the account.
 82  
      *
 83  
      * @param user The user to be checked.
 84  
      * @return true if the specified account exists
 85  
      * @throws DataBackendException if there was an error accessing
 86  
      *         the data backend.
 87  
      */
 88  
     public boolean accountExists(User user)
 89  
         throws DataBackendException
 90  
     {
 91  53
         return accountExists(user.getName());
 92  
     }
 93  
 
 94  
     /**
 95  
      * Check whether a specified user's account exists.
 96  
      *
 97  
      * The login name is used for looking up the account.
 98  
      *
 99  
      * @param userName The name of the user to be checked.
 100  
      * @return true if the specified account exists
 101  
      * @throws DataBackendException if there was an error accessing
 102  
      *         the data backend.
 103  
      */
 104  
     public boolean accountExists(String userName)
 105  
         throws DataBackendException
 106  
     {
 107  57
         Criteria criteria = new Criteria();
 108  57
         criteria.add(UserPeerManager.getNameColumn(), userName);
 109  
         List users;
 110  
         try
 111  
         {
 112  57
             users = UserPeerManager.doSelect(criteria);
 113  
         }
 114  0
         catch (Exception e)
 115  
         {
 116  0
             throw new DataBackendException(
 117  
                 "Failed to check account's presence", e);
 118  57
         }
 119  57
         if (users.size() > 1)
 120  
         {
 121  0
             throw new DataBackendException(
 122  
                 "Multiple Users with same username '" + userName + "'");
 123  
         }
 124  57
         return (users.size() == 1);
 125  
     }
 126  
 
 127  
     /**
 128  
      * Retrieve a user from persistent storage using username as the
 129  
      * key.
 130  
      *
 131  
      * @param userName the name of the user.
 132  
      * @return an User object.
 133  
      * @exception UnknownEntityException if the user's account does not
 134  
      *            exist in the database.
 135  
      * @exception DataBackendException if there is a problem accessing the
 136  
      *            storage.
 137  
      */
 138  
     public User retrieve(String userName)
 139  
         throws UnknownEntityException, DataBackendException
 140  
     {
 141  40
         Criteria criteria = new Criteria();
 142  40
         criteria.add(UserPeerManager.getNameColumn(), userName);
 143  
 
 144  40
         List users = retrieveList(criteria);;
 145  
 
 146  40
         if (users.size() > 1)
 147  
         {
 148  0
             throw new DataBackendException(
 149  
                 "Multiple Users with same username '" + userName + "'");
 150  
         }
 151  40
         if (users.size() == 1)
 152  
         {
 153  38
             return (User) users.get(0);
 154  
         }
 155  2
         throw new UnknownEntityException("Unknown user '" + userName + "'");
 156  
     }
 157  
 
 158  
     /**
 159  
      * Retrieve a user from persistent storage using the primary key
 160  
      *
 161  
      * @param key The primary key object
 162  
      * @return an User object.
 163  
      * @throws UnknownEntityException if the user's record does not
 164  
      *         exist in the database.
 165  
      * @throws DataBackendException if there is a problem accessing the
 166  
      *         storage.
 167  
      */
 168  
     public User retrieveById(Object key)
 169  
             throws UnknownEntityException, DataBackendException
 170  
     {
 171  3
         Criteria criteria = new Criteria();
 172  3
         criteria.add(UserPeerManager.getIdColumn(), key);
 173  
 
 174  3
         List users = retrieveList(criteria);
 175  
 
 176  3
         if (users.size() > 1)
 177  
         {
 178  0
             throw new DataBackendException(
 179  
                 "Multiple Users with same unique Key '" + String.valueOf(key) + "'");
 180  
         }
 181  3
         if (users.size() == 1)
 182  
         {
 183  2
             return (User) users.get(0);
 184  
         }
 185  1
         throw new UnknownEntityException("Unknown user with key '" + String.valueOf(key) + "'");
 186  
     }
 187  
 
 188  
     /**
 189  
      * @deprecated Use <a href="#retrieveList">retrieveList</a> instead.
 190  
      *
 191  
      * @param criteria The criteria of selection.
 192  
      * @return a List of users meeting the criteria.
 193  
      * @throws DataBackendException if there is a problem accessing the
 194  
      *         storage.
 195  
      */
 196  
     public User[] retrieve(Criteria criteria)
 197  
         throws DataBackendException
 198  
     {
 199  1
         return (User [])retrieveList(criteria).toArray(new User[0]);
 200  
     }
 201  
 
 202  
     /**
 203  
      * Retrieve a list of users that meet the specified criteria.
 204  
      *
 205  
      * As the keys for the criteria, you should use the constants that
 206  
      * are defined in {@link User} interface, plus the names
 207  
      * of the custom attributes you added to your user representation
 208  
      * in the data storage. Use verbatim names of the attributes -
 209  
      * without table name prefix in case of Torque implementation.
 210  
      *
 211  
      * @param criteria The criteria of selection.
 212  
      * @return a List of users meeting the criteria.
 213  
      * @throws DataBackendException if there is a problem accessing the
 214  
      *         storage.
 215  
      */
 216  
     public List retrieveList(Criteria criteria)
 217  
         throws DataBackendException
 218  
     {
 219  70
         for (Iterator keys = criteria.keySet().iterator(); keys.hasNext(); )
 220  
         {
 221  43
             String key = (String) keys.next();
 222  
 
 223  
             // set the table name for all attached criterion
 224  43
             Criteria.Criterion[] criterion = criteria
 225  
                 .getCriterion(key).getAttachedCriterion();
 226  
 
 227  86
             for (int i = 0; i < criterion.length; i++)
 228  
             {
 229  43
                 if (StringUtils.isEmpty(criterion[i].getTable()))
 230  
                 {
 231  0
                     criterion[i].setTable(UserPeerManager.getTableName());
 232  
                 }
 233  
             }
 234  
         }
 235  70
         List users = null;
 236  
         try
 237  
         {
 238  70
             users = UserPeerManager.doSelect(criteria);
 239  
         }
 240  0
         catch (Exception e)
 241  
         {
 242  0
             throw new DataBackendException("Failed to retrieve users", e);
 243  70
         }
 244  70
         return users;
 245  
     }
 246  
 
 247  
     /**
 248  
      * Retrieve a user from persistent storage using username as the
 249  
      * key, and authenticate the user. The implementation may chose
 250  
      * to authenticate to the server as the user whose data is being
 251  
      * retrieved.
 252  
      *
 253  
      * @param userName the name of the user.
 254  
      * @param password the user supplied password.
 255  
      * @return an User object.
 256  
      * @exception PasswordMismatchException if the supplied password was
 257  
      *            incorrect.
 258  
      * @exception UnknownEntityException if the user's account does not
 259  
      *            exist in the database.
 260  
      * @exception DataBackendException if there is a problem accessing the
 261  
      *            storage.
 262  
      */
 263  
     public User retrieve(String userName, String password)
 264  
         throws PasswordMismatchException, UnknownEntityException,
 265  
                DataBackendException
 266  
     {
 267  4
         User user = retrieve(userName);
 268  4
         authenticate(user, password);
 269  2
         return user;
 270  
     }
 271  
 
 272  
     /**
 273  
      * Save an User object to persistent storage. User's account is
 274  
      * required to exist in the storage.
 275  
      *
 276  
      * @param user an User object to store.
 277  
      * @exception UnknownEntityException if the user's account does not
 278  
      *            exist in the database.
 279  
      * @exception DataBackendException if there is a problem accessing the
 280  
      *            storage.
 281  
      */
 282  
     public void store(User user)
 283  
         throws UnknownEntityException, DataBackendException
 284  
     {
 285  11
         if (!accountExists(user))
 286  
         {
 287  2
             throw new UnknownEntityException("The account '" +
 288  
                                              user.getName() + "' does not exist");
 289  
         }
 290  
 
 291  
         try
 292  
         {
 293  
             // this is to mimic the old behavior of the method, the user
 294  
             // should be new that is passed to this method.  It would be
 295  
             // better if this was checked, but the original code did not
 296  
             // care about the user's state, so we set it to be appropriate
 297  9
             ((Persistent) user).setNew(false);
 298  9
             ((Persistent) user).setModified(true);
 299  9
             ((Persistent) user).save();
 300  
         }
 301  0
         catch (Exception e)
 302  
         {
 303  0
             throw new DataBackendException("Failed to save user object", e);
 304  9
         }
 305  9
     }
 306  
 
 307  
     /**
 308  
      * Saves User data when the session is unbound. The user account is required
 309  
      * to exist in the storage.
 310  
      *
 311  
      * LastLogin, AccessCounter, persistent pull tools, and any data stored
 312  
      * in the permData hashtable that is not mapped to a column will be saved.
 313  
      *
 314  
      * @exception UnknownEntityException if the user's account does not
 315  
      *            exist in the database.
 316  
      * @exception DataBackendException if there is a problem accessing the
 317  
      *            storage.
 318  
      */
 319  
     public void saveOnSessionUnbind(User user)
 320  
         throws UnknownEntityException, DataBackendException
 321  
     {
 322  0
         if (!user.hasLoggedIn())
 323  
         {
 324  0
             return;
 325  
         }
 326  0
         store(user);
 327  0
     }
 328  
 
 329  
 
 330  
     /**
 331  
      * Authenticate an User with the specified password. If authentication
 332  
      * is successful the method returns nothing. If there are any problems,
 333  
      * exception was thrown.
 334  
      *
 335  
      * @param user an User object to authenticate.
 336  
      * @param password the user supplied password.
 337  
      * @exception PasswordMismatchException if the supplied password was
 338  
      *            incorrect.
 339  
      * @exception UnknownEntityException if the user's account does not
 340  
      *            exist in the database.
 341  
      * @exception DataBackendException if there is a problem accessing the
 342  
      *            storage.
 343  
      */
 344  
     public void authenticate(User user, String password)
 345  
         throws PasswordMismatchException, UnknownEntityException,
 346  
                DataBackendException
 347  
     {
 348  6
         if (!accountExists(user))
 349  
         {
 350  1
             throw new UnknownEntityException("The account '" +
 351  
                                              user.getName() + "' does not exist");
 352  
         }
 353  
 
 354  
         // log.debug("Supplied Pass: " + password);
 355  
         // log.debug("User Pass: " + user.getPassword());
 356  
 
 357  
         /*
 358  
          * Unix crypt needs the existing, encrypted password text as
 359  
          * salt for checking the supplied password. So we supply it
 360  
          * into the checkPassword routine
 361  
          */
 362  
 
 363  5
         if (!TurbineSecurity.checkPassword(password, user.getPassword()))
 364  
         {
 365  2
             throw new PasswordMismatchException("The passwords do not match");
 366  
         }
 367  3
     }
 368  
 
 369  
     /**
 370  
      * Change the password for an User. The user must have supplied the
 371  
      * old password to allow the change.
 372  
      *
 373  
      * @param user an User to change password for.
 374  
      * @param oldPassword The old password to verify
 375  
      * @param newPassword The new password to set
 376  
      * @exception PasswordMismatchException if the supplied password was
 377  
      *            incorrect.
 378  
      * @exception UnknownEntityException if the user's account does not
 379  
      *            exist in the database.
 380  
      * @exception DataBackendException if there is a problem accessing the
 381  
      *            storage.
 382  
      */
 383  
     public void changePassword(User user, String oldPassword,
 384  
                                String newPassword)
 385  
         throws PasswordMismatchException, UnknownEntityException,
 386  
                DataBackendException
 387  
     {
 388  4
         if (!accountExists(user))
 389  
         {
 390  0
             throw new UnknownEntityException("The account '" +
 391  
                                              user.getName() + "' does not exist");
 392  
         }
 393  
 
 394  4
         if (!TurbineSecurity.checkPassword(oldPassword, user.getPassword()))
 395  
         {
 396  2
             throw new PasswordMismatchException(
 397  
                 "The supplied old password for '" + user.getName() +
 398  
                 "' was incorrect");
 399  
         }
 400  2
         user.setPassword(TurbineSecurity.encryptPassword(newPassword));
 401  
         // save the changes in the database imediately, to prevent the password
 402  
         // being 'reverted' to the old value if the user data is lost somehow
 403  
         // before it is saved at session's expiry.
 404  2
         store(user);
 405  2
     }
 406  
 
 407  
     /**
 408  
      * Forcibly sets new password for an User.
 409  
      *
 410  
      * This is supposed by the administrator to change the forgotten or
 411  
      * compromised passwords. Certain implementatations of this feature
 412  
      * would require administrative level access to the authenticating
 413  
      * server / program.
 414  
      *
 415  
      * @param user an User to change password for.
 416  
      * @param password the new password.
 417  
      * @exception UnknownEntityException if the user's record does not
 418  
      *            exist in the database.
 419  
      * @exception DataBackendException if there is a problem accessing the
 420  
      *            storage.
 421  
      */
 422  
     public void forcePassword(User user, String password)
 423  
         throws UnknownEntityException, DataBackendException
 424  
     {
 425  4
         if (!accountExists(user))
 426  
         {
 427  0
             throw new UnknownEntityException("The account '" +
 428  
                                              user.getName() + "' does not exist");
 429  
         }
 430  4
         user.setPassword(TurbineSecurity.encryptPassword(password));
 431  
         // save the changes in the database immediately, to prevent the
 432  
         // password being 'reverted' to the old value if the user data
 433  
         // is lost somehow before it is saved at session's expiry.
 434  4
         store(user);
 435  4
     }
 436  
 
 437  
     /**
 438  
      * Creates new user account with specified attributes.
 439  
      *
 440  
      * @param user The object describing account to be created.
 441  
      * @param initialPassword the password for the new account
 442  
      * @throws DataBackendException if there was an error accessing
 443  
      the data backend.
 444  
      * @throws EntityExistsException if the user account already exists.
 445  
      */
 446  
     public void createAccount(User user, String initialPassword)
 447  
         throws EntityExistsException, DataBackendException
 448  
     {
 449  6
         if(StringUtils.isEmpty(user.getName()))
 450  
         {
 451  2
             throw new DataBackendException("Could not create "
 452  
                                            + "an user with empty name!");
 453  
         }
 454  
 
 455  4
         if (accountExists(user))
 456  
         {
 457  2
             throw new EntityExistsException("The account '" +
 458  
                                             user.getName() + "' already exists");
 459  
         }
 460  2
         user.setPassword(TurbineSecurity.encryptPassword(initialPassword));
 461  
 
 462  
         try
 463  
         {
 464  
             // this is to mimic the old behavior of the method, the user
 465  
             // should be new that is passed to this method.  It would be
 466  
             // better if this was checked, but the original code did not
 467  
             // care about the user's state, so we set it to be appropriate
 468  2
             ((Persistent) user).setNew(true);
 469  2
             ((Persistent) user).setModified(true);
 470  2
             ((Persistent) user).save();
 471  
         }
 472  0
         catch (Exception e)
 473  
         {
 474  0
             throw new DataBackendException("Failed to create account '" +
 475  
                                            user.getName() + "'", e);
 476  2
         }
 477  2
     }
 478  
 
 479  
     /**
 480  
      * Removes an user account from the system.
 481  
      *
 482  
      * @param user the object describing the account to be removed.
 483  
      * @throws DataBackendException if there was an error accessing
 484  
      the data backend.
 485  
      * @throws UnknownEntityException if the user account is not present.
 486  
      */
 487  
     public void removeAccount(User user)
 488  
         throws UnknownEntityException, DataBackendException
 489  
     {
 490  3
         if (!accountExists(user))
 491  
         {
 492  1
             throw new UnknownEntityException("The account '" +
 493  
                                              user.getName() + "' does not exist");
 494  
         }
 495  2
         Criteria criteria = new Criteria();
 496  2
         criteria.add(UserPeerManager.getNameColumn(), user.getName());
 497  
         try
 498  
         {
 499  2
             UserPeerManager.doDelete(criteria);
 500  
         }
 501  0
         catch (Exception e)
 502  
         {
 503  0
             throw new DataBackendException("Failed to remove account '" +
 504  
                                            user.getName() + "'", e);
 505  2
         }
 506  2
     }
 507  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.