Coverage report

  %line %branch
org.apache.turbine.services.security.torque.TorqueUserManager
80% 
86% 

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

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