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