/**
  * @depends testLoginHistory
  */
 public function testLoginHistoryPagination()
 {
     //Perform 20 more login
     $this->email = $this->valid_test_email;
     $this->password = $this->valid_test_password;
     $i = 1;
     while ($i <= 20) {
         $this->login();
         $i++;
     }
     //Fetch paginated records (page 1)
     $loginHistory = (new User())->getLoginHistory($this->email, 1, 10);
     $properties = ['first', 'before', 'items', 'current', 'last', 'next', 'total_pages', 'total_items', 'limit'];
     $response = Utils::validateObjectHasAllProperties($properties, $loginHistory);
     $this->assertTrue($response);
     $this->assertEquals(10, count($loginHistory->items));
     $this->assertEquals(1, $loginHistory->current);
     $this->assertEquals(1, $loginHistory->before);
     $this->assertEquals(2, $loginHistory->next);
     //fetch next set of records (page 2)
     $loginHistory = (new User())->getLoginHistory($this->email, 2, 10);
     $this->assertEquals(10, count($loginHistory->items));
     $this->assertEquals(2, $loginHistory->current);
     $this->assertEquals(1, $loginHistory->before);
     //page 3 should be empty
     $loginHistory = (new User())->getLoginHistory($this->email, 3, 10);
     $this->assertEquals(0, count($loginHistory->items));
 }
 public function testLogin()
 {
     //login user without email and password. This should throw an invalid user exception
     $this->email = "";
     $this->password = "";
     $this->loginAndCatchAuthenticationException();
     //set a valid email, and a wrong password
     $this->email = $this->valid_test_email;
     $this->password = '******';
     $this->loginAndCatchAuthenticationException();
     //set an invalid email, and a valid password
     $this->email = '*****@*****.**';
     $this->password = $this->valid_test_password;
     $this->loginAndCatchAuthenticationException();
     //Use valid credentials but an account that is inactive
     $this->email = $this->valid_test_email_2;
     $this->password = $this->valid_test_password;
     $this->loginAndCatchAuthenticationException();
     //Use valid credentials and an account that is active
     $this->email = $this->valid_test_email;
     $this->password = $this->valid_test_password;
     $response = $this->login();
     $this->assertNotEmpty($response, "Test Login Assertion: Valid email and valid password");
     $this->assertEquals($this->sample_user_type_name, $response->UserType->name);
     $relationShips = ['PasswordChanges', 'PasswordResets', 'LoginHistory', 'UserType'];
     //check that all of the following relationships are valid
     foreach ($relationShips as $aRelationShip) {
         $response->{$aRelationShip};
     }
     $requiredAttributes = ['id', 'email', 'password', 'status', 'created_at', 'updated_at', 'user_type_id'];
     $validate = Utils::validateObjectHasAllProperties($requiredAttributes, $response);
     $this->assertTrue($validate);
 }
 public function testResetPassword()
 {
     $user = new User();
     //generate a token that expires
     $token = $user->generateResetPasswordToken($this->valid_test_email);
     //throw an exception when an invalid token is used
     $wrongToken = Utils::generateRandomString(20);
     $this->throwResetPasswordException($wrongToken);
     //generate a token that expires using a negative timestamp so that the tokens expiry date is before the current time
     $expiredToken = $user->generateResetPasswordToken($this->valid_test_email, null, true, -(4 * 24 * 3600));
     $this->throwResetPasswordException($expiredToken);
     //reset the password with a valid token
     $newPassword = User::generateRandomPassword();
     $response = $user->resetPassword($this->valid_test_email, $newPassword, $token);
     $this->assertTrue($response);
     //authenticate with new password
     $response = $user->authenticate($this->valid_test_email, $newPassword);
     $this->assertNotEmpty($response);
     //try to use the same token again even when it has expired
     $this->throwResetPasswordException($token);
 }
 /**
  * Test for user type/role creation
  */
 public function testUserTypeCreation()
 {
     //Create a user type without a name (exception expected)
     $this->exception('', UserTypeException::class);
     //create two user types
     $admin = $this->createUserType('admin');
     $this->assertNotEmpty($admin);
     $user = $this->createUserType('user');
     $this->assertNotEmpty($user);
     //create another user type with the same name (exception expected)
     $this->exception('user', UserTypeException::class);
     //fetch all user types
     $userTypes = (new UserType())->getUserTypes();
     $this->assertNotEmpty($userTypes);
     $this->assertEquals(2, count($userTypes->toArray()));
     $requiredProperties = ['id', 'name', 'created_at', 'updated_at'];
     foreach ($userTypes as $type) {
         $response = Utils::validateObjectHasAllProperties($requiredProperties, $type);
         $this->assertTrue($response);
     }
 }
 /**
  * Set field before validation check
  */
 public function beforeValidationOnCreate()
 {
     $this->date_logged = Utils::getCurrentDateTime();
 }
Example #6
0
 /**
  * @param int $userId
  * @param string $newPassword
  * @param null $resetPasswordToken token to expire if call is from password reset
  * @return bool
  * @throws PasswordChangeException
  */
 public function updatePassword($userId, $newPassword, $resetPasswordToken = null)
 {
     $transactionManager = new TransactionManager();
     try {
         //use a transaction as we would be updating more than one table
         $transaction = $transactionManager->get();
         $this->setTransaction($transaction);
         $user = User::findFirst($userId);
         if ($user == false) {
             $transaction->rollback(ErrorMessages::PASSWORD_UPDATE_FAILED);
         }
         $previousPassword = $user->password;
         $user->password = Utils::encryptPassword($newPassword);
         if (!$user->save()) {
             $transaction->rollback(ErrorMessages::PASSWORD_UPDATE_FAILED);
         }
         $userPasswordChange = new UserPasswordChange();
         $userPasswordChange->setTransaction($transaction);
         $userPasswordChange->setDateChanged(date("Y-m-d H:i:s"));
         $userPasswordChange->setUserId($userId);
         $userPasswordChange->setPasswordHash($previousPassword);
         if (!$userPasswordChange->save()) {
             $transaction->rollback(ErrorMessages::PASSWORD_UPDATE_FAILED);
         }
         if (!empty($resetPasswordToken) && !(new UserPasswordReset())->expireToken($resetPasswordToken)) {
             $transaction->rollback(ErrorMessages::TOKEN_EXPIRY_FAILED);
         }
         $transaction->commit();
         return true;
     } catch (TransactionFailed $e) {
         throw new PasswordChangeException($e->getMessage());
     }
 }
 /**
  * check if the new password does not correspond to the previous max passwords
  * We use max-1 in the query because we are assuming that the user's current password is
  * inclusive of the last max passwords used and this has already been checked above
  *
  * @param int $userId
  * @param string $newPassword
  * @param int $max
  * @throws PasswordChangeException
  */
 public static function validateNewPassword($userId, $newPassword, $max = self::MAX_PASSWORD_CHANGES_BEFORE_REUSE)
 {
     $recentPasswords = UserPasswordChange::query()->where("user_id = :user_id:")->bind(["user_id" => $userId])->orderBy("date_changed DESC")->limit($max - 1)->execute()->toArray();
     foreach ($recentPasswords as $aRecentPassword) {
         if (Utils::verifyPassword($newPassword, $aRecentPassword['password_hash'])) {
             throw new PasswordChangeException("You cannot use any of your last {$max} passwords");
         }
     }
 }
 public function __construct($message, $code = 0, Exception $previous = null)
 {
     $messages = Utils::getMessagesFromStringOrArray($message);
     // make sure everything is assigned properly
     parent::__construct($messages, $code, $previous);
 }
 /**
  * @param int $user_id
  * @param int $tokenLength
  * @param int $expires
  * @param boolean $expiry
  * @return string
  * @throws ResetPasswordException
  */
 public function generateToken($user_id, $tokenLength, $expires, $expiry)
 {
     if ($tokenLength > self::MAX_TOKEN_LENGTH) {
         throw new ResetPasswordException(sprintf(ErrorMessages::RESET_PASSWORD_TOKEN_TOO_LONG, UserPasswordReset::MAX_TOKEN_LENGTH));
     }
     if ($tokenLength < self::MIN_TOKEN_LENGTH) {
         throw new ResetPasswordException(sprintf(ErrorMessages::RESET_PASSWORD_TOKEN_TOO_SHORT, UserPasswordReset::MIN_TOKEN_LENGTH));
     }
     $tokenLength = $tokenLength - 10;
     //append a timestamp
     $token = Utils::generateRandomString($tokenLength, false);
     if ($this->tokenExists($token)) {
         return $this->generateToken($user_id, $tokenLength, $expires, $expiry);
     }
     $token = $token . time();
     $this->setUserId($user_id);
     $this->setExpires((int) $expires);
     $this->setDateOfExpiry($expires ? time() + $expiry : null);
     $this->setToken($token);
     $this->setDateRequested(date("Y-m-d H:i:s"));
     if (!$this->create()) {
         throw new ResetPasswordException(ErrorMessages::RESET_PASSWORD_FAILED);
     }
     return $token;
 }
Example #10
0
 public function beforeValidationOnUpdate()
 {
     $this->updated_at = Utils::getCurrentDateTime();
 }