From 989525733e5a6f2487ef6d83ea481736657ebf50 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 30 Jan 2014 00:25:23 -0200 Subject: [PATCH 001/115] Destroyed everything in order to rebuild and start again --- public/.gitkeep | 0 src/Zizaco/Confide/Confide.php | 324 ----------- .../Confide/ConfideEloquentRepository.php | 287 ---------- src/Zizaco/Confide/ConfideFacade.php | 12 - src/Zizaco/Confide/ConfideRepository.php | 104 ---- src/Zizaco/Confide/ConfideServiceProvider.php | 93 ---- src/Zizaco/Confide/ConfideUser.php | 476 ---------------- src/Zizaco/Confide/ObjectProvider.php | 17 - tests/ConfideEloquentRepositoryTest.php | 525 ------------------ tests/ConfideTest.php | 380 ------------- tests/ConfideUserTest.php | 246 -------- 11 files changed, 2464 deletions(-) delete mode 100644 public/.gitkeep delete mode 100644 src/Zizaco/Confide/Confide.php delete mode 100644 src/Zizaco/Confide/ConfideEloquentRepository.php delete mode 100644 src/Zizaco/Confide/ConfideFacade.php delete mode 100644 src/Zizaco/Confide/ConfideRepository.php delete mode 100644 src/Zizaco/Confide/ConfideServiceProvider.php delete mode 100644 src/Zizaco/Confide/ConfideUser.php delete mode 100644 src/Zizaco/Confide/ObjectProvider.php delete mode 100644 tests/ConfideEloquentRepositoryTest.php delete mode 100644 tests/ConfideTest.php delete mode 100644 tests/ConfideUserTest.php diff --git a/public/.gitkeep b/public/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php deleted file mode 100644 index 1077296..0000000 --- a/src/Zizaco/Confide/Confide.php +++ /dev/null @@ -1,324 +0,0 @@ -repo = $repo; - $this->app = app(); - } - - /** - * Returns the Laravel application - * - * @return Illuminate\Foundation\Application - */ - public function app() - { - return $this->app; - } - - /** - * Returns an object of the model set in auth config - * - * @return object - */ - public function model() - { - return $this->repo->model(); - } - - /** - * Get the currently authenticated user or null. - * - * @return Zizaco\Confide\ConfideUser|null - */ - public function user() - { - return $this->app['auth']->user(); - } - - /** - * Set the user confirmation to true. - * - * @param string $code - * @return bool - */ - public function confirm( $code ) - { - return $this->repo->confirm( $code ); - } - - /** - * Attempt to log a user into the application with - * password and identity field(s), usually email or username. - * - * @param array $credentials - * @param bool $confirmed_only - * @param mixed $identity_columns - * @return boolean Success - */ - public function logAttempt( $credentials, $confirmed_only = false, $identity_columns = array() ) - { - // If identity columns is not provided, use all columns of credentials - // except password and remember. - if(empty($identity_columns)) - { - $identity_columns = array_diff( - array_keys($credentials), - array('password','remember') - ); - } - - // Check for throttle limit then log-in - if(! $this->reachedThrottleLimit( $credentials ) ) - { - $user = $this->repo->getUserByIdentity($credentials, $identity_columns); - - if( - $user && - ($user->confirmed || ! $confirmed_only ) && - $this->app['hash']->check( - $credentials['password'], - $user->password - ) - ) - { - $remember = isset($credentials['remember']) ? $credentials['remember'] : false; - - $this->app['auth']->login( $user, $remember ); - return true; - } - } - - $this->throttleCount( $credentials ); - - return false; - } - - /** - * Checks if the credentials has been throttled by too - * much failed login attempts - * - * @param array $credentials - * @return mixed Value. - */ - public function isThrottled( $credentials ) - { - // Check how many failed tries have been done - $attempt_key = $this->attemptCacheKey( $credentials ); - $attempts = $this->app['cache']->get($attempt_key, 0); - - if( $attempts >= $this->app['config']->get('confide::throttle_limit') ) - { - return true; - } - else - { - return false; - } - } - - /** - * Send email with information about password reset - * - * @param string $email - * @return bool - */ - public function forgotPassword( $email ) - { - $user = $this->repo->getUserByMail( $email ); - if( $user ) - { - $user->forgotPassword(); - return true; - } - else - { - return false; - } - } - - /** - * Checks to see if the user has a valid token. - * - * @param $token - * @return bool - */ - public function isValidToken( $token ) - { - $count = $this->repo->getPasswordRemindersCount( $token ); - - return ($count != 0); - } - - /** - * Change user password - * - * @return string - */ - public function resetPassword( $params ) - { - $token = array_get($params, 'token', ''); - $email = $this->repo->getEmailByReminderToken( $token ); - $user = $this->repo->getUserByMail( $email ); - - if( $user ) - { - if($user->resetPassword( $params )) - { - // Password reset success, remove token from database - $this->repo->deleteEmailByReminderToken( $token ); - - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - - /** - * Log the user out of the application. - * - * @return void - */ - public function logout() - { - $this->app['auth']->logout(); - } - - /** - * Display the default login view - * - * @deprecated - * @return Illuminate\View\View - */ - public function makeLoginForm() - { - return $this->app['view']->make($this->app['config']->get('confide::login_form')); - } - - /** - * Display the default signup view - * - * @deprecated - * @return Illuminate\View\View - */ - public function makeSignupForm() - { - return $this->app['view']->make( $this->app['config']->get('confide::signup_form') ); - } - - /** - * Display the forget password view - * - * @deprecated - * @return Illuminate\View\View - */ - public function makeForgotPasswordForm() - { - return $this->app['view']->make( $this->app['config']->get('confide::forgot_password_form') ); - } - - /** - * Display the forget password view - * - * @deprecated - * @return Illuminate\View\View - */ - public function makeResetPasswordForm( $token ) - { - return $this->app['view']->make( $this->app['config']->get('confide::reset_password_form') , array('token'=>$token)); - } - - /** - * Check whether the controller's action exists. - * Returns the url if it does. Otherwise false. - * @param $controllerAction - * @return string - */ - public function checkAction( $action, $parameters = array(), $absolute = true ) - { - try { - $url = $this->app['url']->action($action, $parameters, $absolute); - } catch( InvalidArgumentException $e ) { - return false; - } - - return $url; - } - - /** - * Returns the name of the cache key that will be used - * to store the failed attempts - * - * @param array $credentials. - * @return string. - */ - protected function attemptCacheKey( $credentials ) - { - return 'confide_flogin_attempt_' - .$this->app['request']->server('REMOTE_ADDR') - .$credentials[$this->app['config']->get('confide::login_cache_field')]; - } - - /** - * Checks if the current IP / email has reached the throttle - * limit - * - * @param array $credentials - * @return bool Value. - */ - protected function reachedThrottleLimit( $credentials ) - { - $attempt_key = $this->attemptCacheKey( $credentials ); - $attempts = $this->app['cache']->get($attempt_key, 0); - - return $attempts >= $this->app['config']->get('confide::throttle_limit'); - } - - /** - * Increment IP / email throttle count - * - * @param array $credentials - * @return void - */ - protected function throttleCount( $credentials ) - { - $attempt_key = $this->attemptCacheKey( $credentials ); - $attempts = $this->app['cache']->get($attempt_key, 0); - - $this->app['cache']->put($attempt_key, $attempts+1, $this->app['config']->get('confide::throttle_time_period')); // used throttling login attempts - } -} diff --git a/src/Zizaco/Confide/ConfideEloquentRepository.php b/src/Zizaco/Confide/ConfideEloquentRepository.php deleted file mode 100644 index 24a3b8a..0000000 --- a/src/Zizaco/Confide/ConfideEloquentRepository.php +++ /dev/null @@ -1,287 +0,0 @@ -app = app(); - } - - /** - * Returns the model set in auth config - * - * @return mixed Instantiated object of the 'auth.model' class - */ - public function model() - { - if (! $this->model) - { - $this->model = $this->app['config']->get('auth.model'); - } - - if(is_object($this->model)) - { - return $this->model; - } - elseif(is_string($this->model)) - { - return new $this->model; - } - - throw new \Exception("Model not specified in config/auth.php", 639); - } - - /** - * Set the user confirmation to true. - * - * @param string $code - * @return bool - */ - public function confirm( $code ) - { - $user = $this->model()->where('confirmation_code', '=', $code)->get()->first(); - if( $user ) - { - return $user->confirm(); - } - else - { - return false; - } - } - - /** - * Find a user by the given email - * - * @param string $email The email to be used in the query - * @return ConfideUser User object - */ - public function getUserByMail( $email ) - { - $user = $this->model()->where('email', '=', $email)->get()->first(); - - return $user; - } - - /** - * Find a user by it's credentials. Perform a 'where' within - * the fields contained in the $identityColumns. - * - * @param array $credentials An array containing the attributes to search for - * @param mixed $identityColumns Array of attribute names or string (for one atribute) - * @return ConfideUser User object - */ - public function getUserByIdentity( $credentials, $identityColumns = array('email') ) - { - if(empty($credentials)) - { - return null; - } - - $identityColumns = (array)$identityColumns; - - $user = $this->model(); - - $first = true; - foreach ($identityColumns as $attribute) { - - if(isset($credentials[$attribute])) - { - if($first) - { - $user = $user->where($attribute, $credentials[$attribute]); - $first = false; - } - else - { - $user = $user->orWhere($attribute, $credentials[$attribute]); - } - } - } - - $user = $user->get(); - - if(! empty($user)) { - return $user->first(); - } - - return null; - } - - /** - * Get password reminders count by the given token - * - * @param string $token - * @return int Password reminders count - */ - public function getPasswordRemindersCount( $token ) - { - $count = $this->app['db']->connection()->table('password_reminders') - ->where('token','=',$token)->count(); - - return $count; - } - - /** - * Get email of password reminder by the given token - * - * @param string $token - * @return string Email - */ - public function getEmailByReminderToken( $token ) - { - $email = $this->app['db']->connection()->table('password_reminders') - ->select('email')->where('token','=',$token) - ->first(); - - if ($email && is_object($email)) - { - $email = $email->email; - } - elseif ($email && is_array($email)) - { - $email = $email['email']; - } - - return $email; - } - - /** - * Remove password reminder from database by the given token - * - * @param string $token - * @return void - */ - public function deleteEmailByReminderToken( $token ) - { - $this->app['db']->connection()->table('password_reminders') - ->select('email')->where('token','=',$token) - ->delete(); - } - - /** - * Change the password of the given user. Make sure to hash - * the $password before calling this method. - * - * @param ConfideUser $user An existent user - * @param string $password The password hash to be used - * @return boolean Success - */ - public function changePassword( $user, $password ) - { - $usersTable = $user->getTable(); - $id = $user->getKey(); - $idColumn = $user->getKeyName(); - - $this->app['db']->connection()->table($usersTable) - ->where($idColumn,$id)->update(array('password'=>$password)); - // I.E: DB::table('users')->where('id',3)->update(array('password'=>$password)); - - return true; - } - - /** - * Generate a token for password change and saves it in - * the 'password_reminders' table with the email of the - * user. - * - * @param ConfideUser $user An existent user - * @return string Password reset token - */ - public function forgotPassword( $user ) - { - $token = md5( uniqid(mt_rand(), true) ); - - $values = array( - 'email'=> $user->email, - 'token'=> $token, - 'created_at'=> new \DateTime - ); - - $this->app['db']->connection()->table('password_reminders') - ->insert( $values ); - // I.E: - // DB::table('password_reminders')->insert(array( - // 'email'=> $this->email, - // 'token'=> $token, - // 'created_at'=> new \DateTime - //)); - - return $token; - } - - /** - * Checks if an non saved user has duplicated credentials - * (email and/or username) - * - * @param ConfideUser $user The non-saved user to be checked - * @return int The number of duplicated entry founds. Probably 0 or 1. - */ - public function userExists( $user ) - { - $usersTable = $user->getTable(); - - $query = $this->app['db']->connection()->table($usersTable) - ->where('email',$user->email); - - if($user->username) - { - $query = $query->orWhere('username',$user->username); - } - - $count = $query->count(); - // I.E: DB::table('users')->where('email', 'bob@sample.com')->orWhere('username', 'bob')->count(); - - return $count; - } - - /** - * Set the 'confirmed' column of the given user to 1 - * - * @param ConfideUser $user An existent user - * @return boolean Success - */ - public function confirmUser( $user ) - { - $usersTable = $user->getTable(); - $id = $user->getKey(); - $idColumn = $user->getKeyName(); - - $this->app['db']->connection()->table($usersTable) - ->where($idColumn,$id)->update(array('confirmed'=>1)); - // I.E: DB::table('users')->where('id',3)->update(array('confirmed'=>1)); - - return true; - } - - public function validate(array $rules = array(), array $customMessages = array()) - { - return $this->model()->validate($rules, $customMessages); - } - -} diff --git a/src/Zizaco/Confide/ConfideFacade.php b/src/Zizaco/Confide/ConfideFacade.php deleted file mode 100644 index cb78b4d..0000000 --- a/src/Zizaco/Confide/ConfideFacade.php +++ /dev/null @@ -1,12 +0,0 @@ -package('zizaco/confide'); - } - - /** - * Register the service provider. - * - * @return void - */ - public function register() - { - $this->registerRepository(); - - $this->registerConfide(); - - $this->registerCommands(); - } - - /** - * Register the repository that will handle all the database interaction. - * - * @return void - */ - protected function registerRepository() - { - $this->app->bind('confide.repository', function($app) - { - return new ConfideEloquentRepository; - }); - } - - /** - * Register the application bindings. - * - * @return void - */ - protected function registerConfide() - { - $this->app->bind('confide', function($app) - { - return new Confide($app->make('confide.repository')); - }); - } - - /** - * Register the artisan commands. - * - * @return void - */ - protected function registerCommands() - { - $this->app['command.confide.controller'] = $this->app->share(function($app) - { - return new ControllerCommand($app); - }); - - $this->app['command.confide.routes'] = $this->app->share(function($app) - { - return new RoutesCommand($app); - }); - - $this->app['command.confide.migration'] = $this->app->share(function($app) - { - return new MigrationCommand($app); - }); - - $this->commands( - 'command.confide.controller', - 'command.confide.routes', - 'command.confide.migration' - ); - } - -} diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php deleted file mode 100644 index c259244..0000000 --- a/src/Zizaco/Confide/ConfideUser.php +++ /dev/null @@ -1,476 +0,0 @@ - 'required|alpha_dash|unique:users', - 'email' => 'required|email|unique:users', - 'password' => 'required|between:4,11|confirmed', - 'password_confirmation' => 'between:4,11', - ); - - /** - * Create a new ConfideUser instance. - */ - public function __construct( array $attributes = array() ) - { - parent::__construct( $attributes ); - - if ( ! static::$app ) - static::$app = app(); - - $this->table = static::$app['config']->get('auth.table'); - } - - /** - * Get the unique identifier for the user. - * - * @return mixed - */ - public function getAuthIdentifier() - { - return $this->getKey(); - } - - /** - * Get the password for the user. - * - * @return string - */ - public function getAuthPassword() - { - return $this->password; - } - - /** - * Confirm the user (usually means that the user) - * email is valid. - * - * @return bool - */ - public function confirm() - { - $this->confirmed = 1; - - // ConfideRepository will update the database - static::$app['confide.repository'] - ->confirmUser( $this ); - - return true; - } - - /** - * Send email with information about password reset - * - * @return string - */ - public function forgotPassword() - { - // ConfideRepository will generate token (and save it into database) - $token = static::$app['confide.repository'] - ->forgotPassword( $this ); - - $view = static::$app['config']->get('confide::email_reset_password'); - - $this->sendEmail( 'confide::confide.email.password_reset.subject', $view, array('user'=>$this, 'token'=>$token) ); - - return true; - } - - /** - * Change user password - * - * @param $params - * @return string - */ - public function resetPassword( $params ) - { - $password = array_get($params, 'password', ''); - $passwordConfirmation = array_get($params, 'password_confirmation', ''); - - if ( $password == $passwordConfirmation ) - { - return static::$app['confide.repository'] - ->changePassword( $this, static::$app['hash']->make($password) ); - } - else{ - return false; - } - } - - /** - * Overwrite the Ardent save method. Saves model into - * database - * - * @param array $rules:array - * @param array $customMessages - * @param array $options - * @param \Closure $beforeSave - * @param \Closure $afterSave - * @return bool - */ - public function save( array $rules = array(), array $customMessages = array(), array $options = array(), \Closure $beforeSave = null, \Closure $afterSave = null ) - { - $duplicated = false; - - if(! $this->id) - { - $duplicated = static::$app['confide.repository']->userExists( $this ); - } - - if(! $duplicated) - { - return $this->real_save( $rules, $customMessages, $options, $beforeSave, $afterSave ); - } - else - { - static::$app['confide.repository']->validate(); - $this->validationErrors->add( - 'duplicated', - static::$app['translator']->get('confide::confide.alerts.duplicated_credentials') - ); - - return false; - } - } - - /** - * Ardent method overloading: - * Before save the user. Generate a confirmation - * code if is a new user. - * - * @param bool $forced - * @return bool - */ - public function beforeSave($forced = false) - { - if ( empty($this->id) ) - { - $this->confirmation_code = md5( uniqid(mt_rand(), true) ); - } - - /* - * Remove password_confirmation field before save to - * database. - */ - if ( isset($this->password_confirmation) ) - { - unset( $this->password_confirmation ); - } - - return true; - } - - /** - * Ardent method overloading: - * After save, delivers the confirmation link email. - * code if is a new user. - * - * @param $success - * @param bool $forced - * @return bool - */ - public function afterSave($success=true, $forced = false) - { - if (! $this->confirmed && ! static::$app['cache']->get('confirmation_email_'.$this->id) ) - { - // on behalf or the config file we should send and email or not - if (static::$app['config']->get('confide::signup_email') == true) - { - $view = static::$app['config']->get('confide::email_account_confirmation'); - $this->sendEmail( 'confide::confide.email.account_confirmation.subject', $view, array('user' => $this) ); - } - // Save in cache that the email has been sent. - $signup_cache = (int)static::$app['config']->get('confide::signup_cache'); - if ($signup_cache !== 0) - { - static::$app['cache']->put('confirmation_email_'.$this->id, true, $signup_cache); - } - } - - return true; - } - - /** - * Runs the real eloquent save method or returns - * true if it's under testing. Because Eloquent - * and Ardent save methods are not Confide's - * responsibility. - * - * @param array $rules - * @param array $customMessages - * @param array $options - * @param \Closure $beforeSave - * @param \Closure $afterSave - * @return bool - */ - protected function real_save( array $rules = array(), array $customMessages = array(), array $options = array(), \Closure $beforeSave = null, \Closure $afterSave = null ) - { - if ( defined('CONFIDE_TEST') ) - { - $this->beforeSave(); - $this->afterSave(true); - return true; - } - else{ - - /* - * This will make sure that a non modified password - * will not trigger validation error. - * @fixed Pull #110 - */ - if( isset($rules['password']) && $this->password == $this->getOriginal('password') ) - { - unset($rules['password']); - unset($rules['password_confirmation']); - } - - return parent::save( $rules, $customMessages, $options, $beforeSave, $afterSave ); - } - } - - /** - * Add the namespace 'confide::' to view hints. - * this makes possible to send emails using package views from - * the command line. - * - * @return void - */ - protected static function fixViewHint() - { - if (isset(static::$app['view.finder'])) - static::$app['view.finder']->addNamespace('confide', __DIR__.'/../../views'); - } - - /** - * Send email using the lang sentence as subject and the viewname - * - * @param mixed $subject_translation - * @param mixed $view_name - * @param array $params - * @return voi. - */ - protected function sendEmail( $subject_translation, $view_name, $params = array() ) - { - if ( static::$app['config']->getEnvironment() == 'testing' ) - return; - - static::fixViewHint(); - - $user = $this; - - static::$app['mailer']->send($view_name, $params, function($m) use ($subject_translation, $user) - { - $m->to( $user->email ) - ->subject( ConfideUser::$app['translator']->get($subject_translation) ); - }); - } - - /* - |-------------------------------------------------------------------------- - | Deprecated variables and methods - |-------------------------------------------------------------------------- - | - */ - - /** - * Rules for when updating a user. - * - * @deprecated - * @var array - */ - protected $updateRules = array( - 'username' => 'required|alpha_dash', - 'email' => 'required|email', - 'password' => 'between:4,11|confirmed', - 'password_confirmation' => 'between:4,11', - ); - - /** - * Alias of save but uses updateRules instead of rules. - * @deprecated use updateUnique() instead - * @param array $rules - * @param array $customMessages - * @param array $options - * @param Closure $beforeSave - * @param Closure $afterSave - * @return bool - */ - public function amend( array $rules = array(), array $customMessages = array(), array $options = array(), \Closure $beforeSave = null, \Closure $afterSave = null ) - { - if (empty($rules)) { - $rules = $this->getUpdateRules(); - } - return $this->save( $rules, $customMessages, $options, $beforeSave, $afterSave ); - } - - /** - * [Deprecated] Generates UUID and checks it for uniqueness against a table/column. - * - * @deprecated - * @param $table - * @param $field - * @return string - */ - protected function generateUuid($table, $field) - { - return md5( uniqid(mt_rand(), true) ); - } - - /** - * [Deprecated] - * - * @deprecated - */ - public function getUpdateRules() - { - return $this->updateRules; - } - - /** - * [Deprecated] Parses the two given users and compares the unique fields. - * - * @deprecated - * @param $oldUser - * @param $updatedUser - * @param array $rules - */ - public function prepareRules($oldUser, $updatedUser, $rules=array()) - { - if(empty($rules)) { - $rules = $this->getRules(); - } - - foreach($rules as $rule => $validation) { - // get the rules with unique. - if (strpos($validation, 'unique')) { - // Compare old vs new - if($oldUser->$rule != $updatedUser->$rule) { - // Set update rule to creation rule - $updateRules = $this->getUpdateRules(); - $updateRules[$rule] = $validation; - $this->setUpdateRules($updateRules); - } - } - } - } - - /** - * [Deprecated] - * - * @deprecated - */ - public function getRules() - { - return self::$rules; - } - - /** - * [Deprecated] - * - * @deprecated - */ - public function setUpdateRules($set) - { - $this->updateRules = $set; - } - - /** - * [Deprecated] Find an user by it's credentials. Perform a 'where' within - * the fields contained in the $identityColumns. - * - * @deprecated Use ConfideRepository getUserByIdentity instead. - * @param array $credentials An array containing the attributes to search for - * @param mixed $identityColumns Array of attribute names or string (for one atribute) - * @return ConfideUser User object - */ - public function getUserFromCredsIdentity($credentials, $identity_columns = array('username', 'email')) - { - return static::$app['confide.repository']->getUserByIdentity($credentials, $identity_columns); - } - - /** - * [Deprecated] Checks if an user exists by it's credentials. Perform a 'where' within - * the fields contained in the $identityColumns. - * - * @deprecated Use ConfideRepository getUserByIdentity instead. - * @param array $credentials An array containing the attributes to search for - * @param mixed $identityColumns Array of attribute names or string (for one atribute) - * @return boolean Exists? - */ - public function checkUserExists($credentials, $identity_columns = array('username', 'email')) - { - $user = static::$app['confide.repository']->getUserByIdentity($credentials, $identity_columns); - - if ($user) { - return true; - } else { - return false; - } - } - - /** - * [Deprecated] Checks if an user is confirmed by it's credentials. Perform a 'where' within - * the fields contained in the $identityColumns. - * - * @deprecated Use ConfideRepository getUserByIdentity instead. - * @param array $credentials An array containing the attributes to search for - * @param mixed $identityColumns Array of attribute names or string (for one atribute) - * @return boolean Is confirmed? - */ - public function isConfirmed($credentials, $identity_columns = array('username', 'email')) - { - $user = static::$app['confide.repository']->getUserByIdentity($credentials, $identity_columns); - - if (! is_null($user) and $user->confirmed) { - return true; - } else { - return false; - } - } -} diff --git a/src/Zizaco/Confide/ObjectProvider.php b/src/Zizaco/Confide/ObjectProvider.php deleted file mode 100644 index b7ec2c5..0000000 --- a/src/Zizaco/Confide/ObjectProvider.php +++ /dev/null @@ -1,17 +0,0 @@ -mockApp(); - $this->repo = new ConfideEloquentRepository(); - - // Set the app attribute with mock - $this->repo->app = $app; - } - - public function tearDown() - { - m::close(); - } - - public function testGetModel() - { - // Make sure to return the wanted value from config - $config = m::mock('Illuminate\Config\Repository'); - $config->shouldReceive('get') - ->with('auth.model') - ->andReturn( '_mockedUser' ) - ->once(); - $this->repo->app['config'] = $config; - - // Mocks an user - $confide_user = $this->mockConfideUser(); - - // Runs the `model()` method - $user = $this->repo->model(); - - // Assert the result - $this->assertInstanceOf('_mockedUser', $user); - } - - public function testShouldConfirm() - { - // Make sure that our user will recieve confirm - $confide_user = m::mock(new _mockedUser); - $confide_user->shouldReceive('confirm') // Should receive confirm - ->andReturn( true ) - ->once() - - ->getMock()->shouldReceive('where') // Should query for the model - ->with('confirmation_code', '=', '123123') - ->andReturn( $confide_user ) - ->once() - - ->getMock()->shouldReceive('get') - ->andReturn( $confide_user ) - ->once() - - ->getMock()->shouldReceive('first') - ->andReturn( $confide_user ) - ->once(); - - // This will make sure that the mocked user will be returned - // when calling `model()` (that will occur inside `repo->confirm()`) - $this->repo->model = $confide_user; - - $this->assertTrue( $this->repo->confirm( '123123' ) ); - } - - public function testShouldGetByEmail() - { - // Make sure that our user will recieve confirm - $confide_user = m::mock(new _mockedUser); - $confide_user->shouldReceive('where') // Should query for the model - ->with('email', '=', 'lol@sample.com') - ->andReturn( $confide_user ) - ->once() - - ->getMock()->shouldReceive('get') - ->andReturn( $confide_user ) - ->once() - - ->getMock()->shouldReceive('first') - ->andReturn( $confide_user ) - ->once(); - - // This will make sure that the mocked user will be returned - // when calling `model()` (that will occur inside `repo->confirm()`) - $this->repo->model = $confide_user; - - $this->assertEquals( $confide_user, $this->repo->getUserByMail( 'lol@sample.com' ) ); - } - - public function testShouldGetByIdentity() - { - // Make sure that our user will be returned when querying - $confide_user = m::mock(new _mockedUser); - - $confide_user->email = 'lol@sample.com'; - $confide_user->username = 'LoL'; - - $confide_user->shouldReceive('where') // Should query for the model - ->with('email', 'lol@sample.com') - ->andReturn( $confide_user ) - ->atLeast(1) - - ->getMock()->shouldReceive('where') - ->with('username', 'LoL') - ->andReturn( $confide_user ) - ->once() - - ->getMock()->shouldReceive('orWhere') - ->with('username', 'LoL') - ->andReturn( $confide_user ) - ->once() - - ->getMock()->shouldReceive('get') - ->andReturn( $confide_user ) - ->atLeast(1) - - ->getMock()->shouldReceive('first') - ->andReturn( $confide_user ) - ->atLeast(1); - - // This will make sure that the mocked user will be returned - // when calling `model()` (that will occur inside `repo->confirm()`) - $this->repo->model = $confide_user; - - // Parameters to search for - $values = array( - 'email' => 'lol@sample.com', - 'username' => 'LoL', - ); - - // Identity - $identity = array( 'email','username' ); - - // Using array - $this->assertEquals( - $confide_user, $this->repo->getUserByIdentity( $values, $identity ) - ); - - // Using string - $this->assertEquals( - $confide_user, $this->repo->getUserByIdentity( $values, 'email' ) - ); - - // Using string for username - $this->assertEquals( - $confide_user, $this->repo->getUserByIdentity( $values, 'username' ) - ); - - // When passing empty credentials should return null - $this->assertEquals( - null, $this->repo->getUserByIdentity( array() ) - ); - } - - public function testShouldGetPasswordRemindersCountByToken() - { - // Make sure that our user will recieve confirm - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') // Should query for the password reminders with the given token - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with('password_reminders') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('where') - ->with('token', '=', '456456') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('count') - ->andReturn( 1 ) - ->once(); - - $this->repo->app['db'] = $database; - - $this->assertEquals( 1, $this->repo->getPasswordRemindersCount( '456456' ) ); - } - - public function testShouldGetPasswordReminderEmailByToken() - { - // Make sure that our user will recieve confirm - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') // Should query for the password reminders with the given token - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with('password_reminders') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('select') - ->with('email') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('where') - ->with('token', '=', '456456') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('first') - ->andReturn('lol@sample.com') - ->once(); - - $this->repo->app['db'] = $database; - - $this->assertEquals( 'lol@sample.com', $this->repo->getEmailByReminderToken( '456456' ) ); - } - - public function testShouldDeletePasswordReminderEmailByToken() - { - // Make sure that our user will recieve confirm - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') // Should query for the password reminders with the given token - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with('password_reminders') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('select') - ->with('email') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('where') - ->with('token', '=', '456456') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('delete') - ->once(); - - $this->repo->app['db'] = $database; - - $this->assertNull( $this->repo->deleteEmailByReminderToken( '456456' ) ); - } - - public function testShouldChangePassword() - { - // Make sure that the mock will return the table name - $confide_user = m::mock(new _mockedUser); - $confide_user->shouldReceive('getTable') - ->andReturn( 'users' ) - ->once() - - ->getMock()->shouldReceive('getKey') - ->andReturn( '3' ) - ->once() - - ->getMock()->shouldReceive('getKeyName') - ->andReturn( 'id' ) - ->once(); - - // Mocks DB in order to check for the following query: - // DB::table('users')->where('id',3)->update(array('password'=>'lol')); - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with( 'users' ) - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('where') - ->with('id','3') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('update') - ->with(array('password'=>'secret')) - ->andReturn( 0 ) - ->once(); - - $this->repo->app['db'] = $database; - - // Actually change the user password - $this->assertTrue( - $this->repo->changePassword($confide_user, 'secret') - ); - } - - public function testShouldForgotPassword() - { - // Make sure that the mock will return the table name - $confide_user = m::mock(new _mockedUser); - - $confide_user->email = 'bob@sample.com'; - - $timeStamp = new \DateTime; - - // Mocks DB in order to check for the following query: - // DB::table('password_reminders')->insert(array( - // 'email'=> $this->email, - // 'token'=> $token, - // 'created_at'=> new \DateTime - //)); - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with( 'password_reminders' ) - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('insert') - ->andReturn( true ) - ->once(); - - $this->repo->app['db'] = $database; - - // Actually checks if the token is returned - $this->assertNotNull( - $this->repo->forgotPassword($confide_user) - ); - } - - public function testUserExists() - { - // Make sure that the mock will return the table name - $confide_user = m::mock(new _mockedUser); - - $confide_user->username = 'Bob'; - $confide_user->email = 'bob@sample.com'; - - $confide_user->shouldReceive('getTable') - ->andReturn( 'users' ) - ->once(); - - // Mocks DB in order to check for the following query: - // DB::table('users')->where('email', 'bob@sample.com')->orWhere('username', 'bob')->count(); - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with( 'users' ) - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('where') - ->with('email', 'bob@sample.com') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('orWhere') - ->with('username', 'Bob') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('count') - ->andReturn( 1 ) - ->once(); - - $this->repo->app['db'] = $database; - - // Actually checks if the user exists - $this->assertEquals( - 1, - $this->repo->userExists($confide_user) - ); - } - - public function testShouldConfirmUser() - { - // Make sure that the mock will return the table name - $confide_user = m::mock(new _mockedUser); - $confide_user->shouldReceive('getTable') - ->andReturn( 'users' ) - ->once() - - ->getMock()->shouldReceive('getKey') - ->andReturn( '3' ) - ->once() - - ->getMock()->shouldReceive('getKeyName') - ->andReturn( 'id' ) - ->once(); - - // Mocks DB in order to check for the following query: - // DB::table('users')->where('id',3)->update(array('confirmed'=>1)); - $database = m::mock('DatabaseManager'); - $database->shouldReceive('connection') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('table') - ->with( 'users' ) - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('where') - ->with('id','3') - ->andReturn( $database ) - ->once() - - ->getMock()->shouldReceive('update') - ->with(array('confirmed'=>1)) - ->andReturn( 0 ) - ->once(); - - $this->repo->app['db'] = $database; - - // Actually change the user password - $this->assertTrue( - $this->repo->confirmUser($confide_user) - ); - } - - /** - * Returns a mocked ConfideUser object for testing purposes - * only - * - * @return Illuminate\Auth\UserInterface A mocked confide user - */ - private function mockConfideUser() - { - $confide_user = m::mock( 'Illuminate\Auth\UserInterface' ); - $confide_user->username = 'uname'; - $confide_user->password = '123123'; - $confide_user->confirmed = 0; - $confide_user->shouldReceive('where','get', 'orWhere','first', 'all','getUserFromCredsIdentity') - ->andReturn( $confide_user ); - - return $confide_user; - } - - /** - * Mocks the application components that - * are not Confide's responsibility - * - * @return object Mocked laravel application - */ - private function mockApp() - { - // Mocks the application components that - // are not Confide's responsibility - $app = array(); - - $app['config'] = m::mock( 'Config' ); - $app['config']->shouldReceive( 'get' ) - ->with( 'auth.table' ) - ->andReturn( 'users' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'auth.model' ) - ->andReturn( '_mockedUser' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'app.key' ) - ->andReturn( '123' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'confide::throttle_limit' ) - ->andReturn( 9 ); - - $app['config']->shouldReceive( 'get' ) - ->andReturn( 'confide::login' ); - - $app['mail'] = m::mock( 'Mail' ); - $app['mail']->shouldReceive('send') - ->andReturn( null ); - - $app['hash'] = m::mock( 'Hash' ); - $app['hash']->shouldReceive('make') - ->andReturn( 'aRandomHash' ); - - $app['cache'] = m::mock( 'Cache' ); - $app['cache']->shouldReceive('get') - ->andReturn( 0 ); - $app['cache']->shouldReceive('put'); - - $app['auth'] = m::mock( 'Auth' ); - $app['auth']->shouldReceive('login') - ->andReturn( true ); - - $app['request'] = m::mock( 'Request' ); - $app['request']->shouldReceive('server') - ->andReturn( null ); - - $app['db'] = m::mock( 'DatabaseManager' ); - $app['db']->shouldReceive('connection') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('table') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('select') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('where') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('first') - ->andReturn( $app['db'] ); - $app['db']->email = 'test@example.com'; - - $app['db']->shouldReceive('delete') - ->andReturn( true ); - - return $app; - } - -} - -class _mockedUser {} diff --git a/tests/ConfideTest.php b/tests/ConfideTest.php deleted file mode 100644 index 228be54..0000000 --- a/tests/ConfideTest.php +++ /dev/null @@ -1,380 +0,0 @@ -mockApp(); - $repo = m::mock(new ConfideEloquentRepository); - - $this->confide = new Confide($repo); - - // Set the app attribute with mock - $this->confide->app = $app; - } - - public function testGetModel() - { - // Mocks an User object - $modelObject = $this->mockConfideUser(); - - // Mocks the repository - // Repository should receive model and return an existent user - $this->confide->repo->shouldReceive('model') - ->andReturn($modelObject) - ->once(); - - $user = $this->confide->model(); - - $this->assertEquals( $modelObject, $user ); - } - - public function testShouldGetUser() - { - $confide_user = $this->mockConfideUser(); - - // Laravel auth component should return user - $auth = m::mock('Illuminate\Auth\Guard'); - $auth->shouldReceive('user') - ->andReturn( $confide_user ) - ->once(); - $this->confide->app['auth'] = $auth; - - $this->assertEquals( $confide_user, $this->confide->user() ); - } - - public function testShouldConfirm() - { - // Mocks the repository - // Confirm method of repository should be called with confirm code - // The actual confirmation is tested within ConfideRepositoryTest ;) - $this->confide->repo->shouldReceive('confirm') - ->with('123123') - ->andReturn(true) - ->once(); - - $this->assertTrue( $this->confide->confirm( '123123' ) ); - } - - public function testShouldLogAttempt() - { - $confide_user = $this->mockConfideUser(); - - $this->confide->repo->model = $confide_user; - - $credentials = array( - 'email'=>'mail', - 'username'=>'uname', - 'password'=>'123123' - ); - - // Considering a valid hash check from hash component - $hash = m::mock('Illuminate\Hashing\HasherInterface'); - $hash->shouldReceive('check') - ->andReturn( true ); - $this->confide->app['hash'] = $hash; - - // Mocks the repository - // Repository should receive model and return an existent user - $this->confide->repo->shouldReceive('getUserByIdentity') - ->andReturn($confide_user); - - $this->confide->repo->shouldReceive('model') - ->andReturn($confide_user); - - $this->assertTrue( - $this->confide->logAttempt( $credentials ) - ); - - // Should not login with unconfirmed user. - $this->assertFalse( - $this->confide->logAttempt( $credentials, true ) - ); - - $confide_user->confirmed = 1; - - // Should login because now the user is confirmed - $this->assertTrue( - $this->confide->logAttempt( $credentials, true ) - ); - } - - public function testShouldThrottleLogAttempt() - { - $tries = 15; - - $this->confide->app['request'] = m::mock( 'Request' ); - $this->confide->app['request']->shouldReceive('server') - ->andReturn( '12.34.56.78' ); - - $confide_user = $this->mockConfideUser(); - $confide_user->shouldReceive('get','first') - ->andReturn( null ); - - // Mocks the repository - // Repository should receive getUserByIdentity and return an existent user - $this->confide->repo->shouldReceive('getUserByIdentity') - ->andReturn($confide_user); - - $this->confide->app['hash']->shouldReceive('check') - ->andReturn( false ); - - for ($i=0; $i < $tries; $i++) { - - // Simulates cache values - $this->useCacheForThrottling($i); - - // Make shure the login is not happening anyway - $this->assertFalse( - $this->confide->logAttempt( array('email'=>'wrong', 'username'=>'wrong', 'password'=>'wrong') ) - ); - } - - // Check if the credentials has been throttled - $this->assertTrue( - $this->confide->isThrottled( array('email'=>'wrong', 'password'=>'wrong') ) - ); - } - - public function testShouldForgotPassword() - { - // Mocks an User object - $confide_user = $this->mockConfideUser(); - $confide_user->shouldReceive('forgotPassword') - ->once(); - - // Mocks the repository - // Repository should receive model and return an existent user - $this->confide->repo->shouldReceive('getUserByMail') - ->with( 'user@sample.com' ) - ->andReturn($confide_user) - ->once(); - - $result = $this->confide->forgotPassword( 'user@sample.com' ); - - $this->assertTrue( $result ); - } - - public function testIsValidToken() - { - // Mocks the repository - // Repository should receive model and return an existent user - $this->confide->repo->shouldReceive('getPasswordRemindersCount') - ->with( '123' ) - ->andReturn(true) - ->once(); - - $this->assertTrue( $this->confide->isValidToken('123') ); - } - - public function testShouldResetPassword() - { - $params = array( 'token'=>'123', 'user'=>'somebody' ); - - // Mocks an User object - $confide_user = $this->mockConfideUser(); - $confide_user->shouldReceive('resetPassword') - ->with( $params ) - ->andReturn(true) - ->once(); - - // Mocks the repository - // Repository should run methods related to password reset - $this->confide->repo - ->shouldReceive('getEmailByReminderToken') - ->with( '123' ) - ->andReturn('somebody@sample.com') - ->once() - - ->getMock() - ->shouldReceive('getUserByMail') - ->with( 'somebody@sample.com' ) - ->andReturn($confide_user) - ->once() - - ->getMock() - ->shouldReceive('deleteEmailByReminderToken') - ->with( '123' ) - ->andReturn(true) - ->once(); - - $this->assertTrue( - $this->confide->resetPassword( $params ) - ); - } - - public function testShouldLogout() - { - // Make shure auth logout method is called - $auth = m::mock('Illuminate\Auth\Guard'); - $auth->shouldReceive('logout') - ->once(); - - $this->confide->app['auth'] = $auth; - $this->assertNull( $this->confide->logout() ); - } - - public function testShouldMakeForms() - { - // Make shure view make method is called 3 times - $view = m::mock('Illuminate\View\Environment\View'); - $view->shouldReceive('make') - ->andReturn( 'Content' ) - ->times( 3 ); - - $this->confide->app['view'] = $view; - - $this->assertNotNull( $this->confide->MakeLoginForm() ); - $this->assertNotNull( $this->confide->makeSignupForm() ); - $this->assertNotNull( $this->confide->makeForgotPasswordForm() ); - } - - public function testShouldCheckAction() - { - // Make shure auth logout method is called - $url = m::mock('Url'); - $url->shouldReceive('action') - ->with('a@b','b','c') - ->andReturn('a/b') - ->once(); - - $this->confide->app['url'] = $url; - $this->assertNotNull( $this->confide->checkAction('a@b','b','c') ); - } - - private function mockConfideUser() - { - $confide_user = m::mock( 'Illuminate\Auth\UserInterface' ); - $confide_user->username = 'uname'; - $confide_user->password = '123123'; - $confide_user->confirmed = 0; - $confide_user->shouldReceive('where','get', 'orWhere','first', 'all','getUserFromCredsIdentity') - ->andReturn( $confide_user ); - - return $confide_user; - } - - private function mockApp() - { - // Mocks the application components that - // are not Confide's responsibility - $app = array(); - - $app['config'] = m::mock( 'Config' ); - $app['config']->shouldReceive( 'get' ) - ->with( 'auth.table' ) - ->andReturn( 'users' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'auth.model' ) - ->andReturn( 'User' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'app.key' ) - ->andReturn( '123' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'confide::throttle_limit' ) - ->andReturn( 9 ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'confide::login_cache_field' ) - ->andReturn( 'email' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'confide::throttle_time_period' ) - ->andReturn( 2 ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'confide::password_field', 'password' ) - ->andReturn( 'password' ); - - $app['config']->shouldReceive( 'get' ) - ->andReturn( 'confide::login' ); - - $app['mail'] = m::mock( 'Mail' ); - $app['mail']->shouldReceive('send') - ->andReturn( null ); - - $app['hash'] = m::mock( 'Hash' ); - $app['hash']->shouldReceive('make') - ->andReturn( 'aRandomHash' ); - - $app['cache'] = m::mock( 'Cache' ); - $app['cache']->shouldReceive('get') - ->andReturn( 0 ); - $app['cache']->shouldReceive('put'); - - $app['auth'] = m::mock( 'Auth' ); - $app['auth']->shouldReceive('login') - ->andReturn( true ); - - $app['request'] = m::mock( 'Request' ); - $app['request']->shouldReceive('server') - ->andReturn( null ); - - $app['db'] = m::mock( 'DatabaseManager' ); - $app['db']->shouldReceive('connection') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('table') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('select') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('where') - ->andReturn( $app['db'] ); - $app['db']->shouldReceive('first') - ->andReturn( $app['db'] ); - $app['db']->email = 'test@example.com'; - - $app['db']->shouldReceive('delete') - ->andReturn( true ); - - return $app; - } - - private function useCacheForThrottling( $value ) - { - $cache = m::mock('Illuminate\Cache\Store'); - $cache->shouldReceive('put') - ->with( "confide_flogin_attempt_12.34.56.78wrong", $value+1, 2 ) - ->once(); - $cache->shouldReceive('get') - ->andReturn( $value ); - $this->confide->app['cache'] = $cache; - } - - /** - * the ObjectProvider getObject method should - * be called with $class to return $object. - * - * @param string $class - * @param mixed $obj - * @return void - */ - private function objProviderShouldReturn( $class, $obj ) - { - $obj_provider = m::mock('ObjectProvider'); - $obj_provider->shouldReceive('getObject') - ->with($class) - ->andReturn( $obj ); - - $this->confide->objectRepository = $obj_provider; - } -} diff --git a/tests/ConfideUserTest.php b/tests/ConfideUserTest.php deleted file mode 100644 index 193f89c..0000000 --- a/tests/ConfideUserTest.php +++ /dev/null @@ -1,246 +0,0 @@ -mockApp(); - - $this->confide_user = new ConfideUser; - } - - private function populateUser() - { - $this->confide_user->username = 'uname'; - $this->confide_user->password = '123123'; - $this->confide_user->email = 'mail@sample.com'; - $this->confide_user->confirmation_code = '456456'; - $this->confide_user->confirmed = true; - } - - public function testShouldGetAuthPassword() - { - $this->populateUser(); - - $this->assertEquals( $this->confide_user->password, $this->confide_user->getAuthPassword() ); - } - - public function testShouldConfirm() - { - $this->populateUser(); - - // Should call confirmUser of the repository - ConfideUser::$app['confide.repository'] = m::mock( 'ConfideRepository' ); - ConfideUser::$app['confide.repository']->shouldReceive('confirmUser') - ->with( $this->confide_user ) - ->andReturn( true ) - ->once(); - - $this->assertTrue( $this->confide_user->confirm() ); - - $this->assertEquals( 1, $this->confide_user->confirmed ); - } - - public function testShouldSendForgotPassword() - { - // Should call forgotPassword of the repository - ConfideUser::$app['confide.repository'] = m::mock( 'ConfideRepository' ); - ConfideUser::$app['confide.repository']->shouldReceive('forgotPassword') - ->with( $this->confide_user ) - ->andReturn( true ) - ->once(); - - // Should send an email once - ConfideUser::$app['mailer'] = m::mock( 'Mail' ); - ConfideUser::$app['mailer']->shouldReceive('send') - ->andReturn( null ) - ->atLeast(1); - - $this->populateUser(); - - $old_password = $this->confide_user->password; - - $this->assertTrue( $this->confide_user->forgotPassword() ); - } - - public function testShouldChangePassword() - { - $credentials = array( - 'email'=>'mail@sample.com', - 'password'=>'987987', - 'password_confirmation'=>'987987' - ); - - // Should call changePassword of the repository - ConfideUser::$app['confide.repository'] = m::mock( 'ConfideRepository' ); - ConfideUser::$app['confide.repository']->shouldReceive('changePassword') - ->with( $this->confide_user, 'aRandomHash' ) - ->andReturn( true ) - ->once(); - - $this->populateUser(); - - $old_password = $this->confide_user->password; - - $this->assertTrue( $this->confide_user->resetPassword( $credentials ) ); - } - - public function testShouldNotSaveDuplicated() - { - // Make sure that userExists return 1 to simulates a duplicated user - ConfideUser::$app['confide.repository'] = m::mock( 'ConfideRepository' ); - ConfideUser::$app['confide.repository']->shouldReceive('userExists') - ->with( $this->confide_user ) - ->andReturn( 1 ) - ->once(); - - ConfideUser::$app['confide.repository']->shouldReceive('validate') - ->andReturn( true ) - ->once(); - - $this->populateUser(); - $this->confide_user->confirmation_code = ''; - $this->confide_user->confirmed = false; - - $this->assertFalse( $this->confide_user->save() ); - } - - public function testShouldGenerateConfirmationCodeOnSave() - { - // Make sure that userExists return 0 - ConfideUser::$app['confide.repository'] = m::mock( 'ConfideRepository' ); - ConfideUser::$app['confide.repository']->shouldReceive('userExists') - ->with( $this->confide_user ) - ->andReturn( 0 ) - ->once(); - - // Should send an email once - ConfideUser::$app['mailer'] = m::mock( 'Mail' ); - ConfideUser::$app['mailer']->shouldReceive('send') - ->andReturn( null ) - ->once(); - - $this->populateUser(); - $this->confide_user->confirmation_code = ''; - $this->confide_user->confirmed = false; - - $old_cc = $this->confide_user->confirmation_code; - - $this->assertTrue( $this->confide_user->save() ); - - $new_cc = $this->confide_user->confirmation_code; - - // Should have generated a new confirmation code - $this->assertNotEquals( $old_cc, $new_cc ); - } - - public function testShouldNotGenerateConfirmationCodeIfExists() - { - $this->populateUser(); - - // Considering the model was already saved (this will make sure to - // not trigger the ConfideRepository::userExists method) - $this->confide_user->id = 1; - - $old_cc = $this->confide_user->confirmation_code; - - $this->assertTrue( $this->confide_user->save() ); - - $new_cc = $this->confide_user->confirmation_code; - - // Should not change confirmation code - $this->assertEquals( $old_cc, $new_cc ); - } - - private function mockApp() - { - // Mocks the application components - $app = array(); - - $app['config'] = m::mock( 'Config' ); - $app['config']->shouldReceive( 'get' ) - ->with( 'auth.table' ) - ->andReturn( 'users' ); - - $app['config']->shouldReceive( 'getEnvironment' ) - ->andReturn( 'production' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'app.key' ) - ->andReturn( '123' ); - - $app['config']->shouldReceive( 'get' ) - ->with( 'confide::throttle_limit' ) - ->andReturn( 9 ); - - $app['config']->shouldReceive( 'get' ) - ->andReturn( 'confide::login' ); - - $app['mailer'] = m::mock( 'Mail' ); - $app['mailer']->shouldReceive('send') - ->andReturn( null ); - - $app['hash'] = m::mock( 'Hash' ); - $app['hash']->shouldReceive('make') - ->andReturn( 'aRandomHash' ); - - $app['cache'] = m::mock( 'Cache' ); - $app['cache']->shouldReceive('get') - ->andReturn( false ); - $app['cache']->shouldReceive('put') - ->andReturn( true ); - - $app['translator'] = m::mock( 'Translator' ); - $app['translator']->shouldReceive('get') - ->andReturn( 'aTranslatedString' ); - - $app['db'] = m::mock( 'DatabaseManager' ); - $app['db']->shouldReceive('connection') - ->andReturn( $app['db'] ); - - $app['db']->shouldReceive('table') - ->andReturn( $app['db'] ); - - $app['db']->shouldReceive('insert') - ->andReturn( $app['db'] ); - - $app['db']->shouldReceive('where') - ->andReturn( $app['db'] ); - - $app['db']->shouldReceive('first') - ->andReturn( $app['db'] ); - - $app['db']->shouldReceive('update') - ->andReturn( true ); - - return $app; - } - -} From b95e68e6f4bbf016209f133f749694f966fd92b8 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 30 Jan 2014 00:26:11 -0200 Subject: [PATCH 002/115] Updated composer.json in order to remove the 'laravelbook/ardent' as a dependency. --- composer.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/composer.json b/composer.json index a4e857b..40c8e97 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,6 @@ "authors": [ { "name": "Zizaco Zizuini", - "email": "zizaco@gmail.com", "homepage": "http://www.zizaco.net" }, { @@ -17,7 +16,6 @@ "require": { "php": ">=5.3.0", "illuminate/support": "4.1.x", - "laravelbook/ardent": "2.4.x" }, "require-dev": { "mockery/mockery": "0.7.2", From 2722cde4b68885731381e9d4c5b6fc0e4166f8e8 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 30 Jan 2014 00:51:28 -0200 Subject: [PATCH 003/115] Initial implementation of Confide\EloquentRepository. --- composer.json | 2 +- src/Zizaco/Confide/EloquentRepository.php | 54 ++++++++++++++++++ .../Zizaco/Confide/EloquentRepositoryTest.php | 55 +++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/Zizaco/Confide/EloquentRepository.php create mode 100644 tests/Zizaco/Confide/EloquentRepositoryTest.php diff --git a/composer.json b/composer.json index 40c8e97..7108cd4 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php": ">=5.3.0", - "illuminate/support": "4.1.x", + "illuminate/support": "4.1.x" }, "require-dev": { "mockery/mockery": "0.7.2", diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php new file mode 100644 index 0000000..59fec5c --- /dev/null +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -0,0 +1,54 @@ +app = $app ?: app(); + } + + /** + * Returns the model set in auth config + * + * @return mixed Instantiated object of the 'auth.model' class + */ + public function model() + { + if (! $this->model) + { + $this->model = $this->app['config']->get('auth.model'); + } + + if ($this->model) { + return $this->app[$this->model]; + } + + throw new \Exception("Wrong model specified in config/auth.php", 639); + } +} diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php new file mode 100644 index 0000000..accc35e --- /dev/null +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -0,0 +1,55 @@ +app['config'] = m::mock('Illuminate\Config\Repository'); + + /** + * Expectation + */ + + // Make sure to return the wanted value from config + $repo->app['config']->shouldReceive('get') + ->with('auth.model') + ->once() + ->andReturn($modelClassName); + + // When requesting the _mockedUser in the IoC, return + // the correct object. + $repo->app[$modelClassName] = $user; + + /** + * Assertion + */ + $this->assertEquals($user, $repo->model()); + } + +} From 01f82b54a3ec9be5b9c2f722611d0b84284b369c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 30 Jan 2014 01:48:55 -0200 Subject: [PATCH 004/115] Added some querying methods to Confide\EloquentRepository --- src/Zizaco/Confide/EloquentRepository.php | 78 +++++++- .../Zizaco/Confide/EloquentRepositoryTest.php | 174 ++++++++++++++++-- 2 files changed, 239 insertions(+), 13 deletions(-) diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index 59fec5c..87a9ed3 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -40,8 +40,7 @@ public function __construct($app = null) */ public function model() { - if (! $this->model) - { + if (! $this->model) { $this->model = $this->app['config']->get('auth.model'); } @@ -51,4 +50,79 @@ public function model() throw new \Exception("Wrong model specified in config/auth.php", 639); } + + /** + * Find a user by one of the fields given as $identity. + * If one of the fields in the $identity array matches the user + * will be retrieved. + * @param array $identity An array of attributes and values to search for + * @return COnfideUser User object + */ + public function getUserByIdentity($identity) + { + $user = $this->model(); + + $firstWhere = true; + foreach ($identity as $attribute => $value) { + + if ($firstWhere) { + $user = $user->where($attribute, '=', $value); + } else { + $user = $user->orWhere($attribute, '=', $value); + } + + $firstWhere = false; + } + + $user = $user->get()->first(); + + return $user; + } + + /** + * Find a user by the given email + * + * @param string $email The email to be used in the query + * @return ConfideUser User object + */ + public function getUserByEmail($email) + { + return $this->getUserByIdentity(['email'=>$email]); + } + + /** + * Find a user by the given email or username + * + * @param string $emailOrUsername Username of email to be used in the query + * @return ConfideUser User object + */ + public function getUserByEmailOrUsername($emailOrUsername) + { + $identity = [ + 'email' => $emailOrUsername, + 'username' => $emailOrUsername + ]; + + return $this->getUserByIdentity($identity); + } + + /** + * Update the confirmation status of a user to true if a user + * is found with the given confirmation code. + * + * @param string $code + * @return bool Success + */ + public function confirmByCode($code) + { + $identity = ['confirmation_code' => $code]; + + $user = $this->getUserByIdentity($identity); + + if ($user) { + return $this->confirmUser($user); + } else { + return false; + } + } } diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index accc35e..1464b66 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -22,20 +22,23 @@ public function tearDown() m::close(); } - public function testGetModel() + public function testShouldGetModel() { - /** - * Set - */ + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ $modelClassName = '_mockedUser'; $user = m::mock($modelClassName); $repo = new EloquentRepository([]); $repo->app['config'] = m::mock('Illuminate\Config\Repository'); - /** - * Expectation - */ - + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ // Make sure to return the wanted value from config $repo->app['config']->shouldReceive('get') ->with('auth.model') @@ -46,10 +49,159 @@ public function testGetModel() // the correct object. $repo->app[$modelClassName] = $user; - /** - * Assertion - */ + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ $this->assertEquals($user, $repo->model()); } + public function testShouldGetUserByIdentity() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $identity = [ + 'email' => 'someone@somewhere.com', + 'something' => 'somevalue' + ]; + $model = m::mock('_mockedUser'); + $user = m::mock('_mockedUser'); + $repo = m::mock('Zizaco\Confide\EloquentRepository[model]',[]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Repo model method should return the model instance + $repo->shouldReceive('model') + ->andReturn($model); + + // Should query for the user using each credential + $firstWhere = true; + foreach ($identity as $attribute => $value) { + $model->shouldReceive(($firstWhere) ? 'where' : 'orWhere') + ->with($attribute, '=', $value) + ->once() + ->andReturn($model); + + $firstWhere = false; + } + + $model->shouldReceive('get') + ->once() + ->andReturn($model); + + $model->shouldReceive('first') + ->once() + ->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + // Should return the user + $this->assertEquals($user, $repo->getUserByIdentity($identity)); + } + + public function testShouldGetUserByEmail() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $email = 'someone@somewhere.com'; + $user = m::mock('_mockedUser'); + $repo = m::mock('Zizaco\Confide\EloquentRepository[getUserByIdentity]',[]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Repo model method should return the model instance + $repo->shouldReceive('getUserByIdentity') + ->with(['email'=>$email]) + ->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + // Should return the user + $this->assertEquals($user, $repo->getUserByEmail($email)); + } + + public function testShouldGetUserByEmailOrUsername() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $username = 'Someone'; + $user = m::mock('_mockedUser'); + $repo = m::mock('Zizaco\Confide\EloquentRepository[getUserByIdentity]',[]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Repo model method should return the model instance + $repo->shouldReceive('getUserByIdentity') + ->with(['email'=>$username, 'username'=>$username]) + ->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + // Should return the user + $this->assertEquals($user, $repo->getUserByEmailOrUsername($username)); + } + + public function testShouldConfirmByCode() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $confirmCode = 123123; + $user = m::mock('_mockedUser'); + $repo = m::mock('Zizaco\Confide\EloquentRepository[getUserByIdentity,confirmUser]',[]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Should query for the user + $repo->shouldReceive('getUserByIdentity') + ->with(['confirmation_code' => $confirmCode]) + ->andReturn($user); + + // Should call the confirmUser method with the user + // instance + $repo->shouldReceive('confirmUser') + ->with($user) + ->once() + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($repo->confirmByCode($confirmCode)); + } } From f109a3bf3f9b031d4d0aefaf781f25125fda50df Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 30 Jan 2014 07:59:29 -0200 Subject: [PATCH 005/115] Added Confide\EloquentPasswordService in order to handle password reminders and reset. --- .../Confide/EloquentPasswordService.php | 54 +++++++++++ src/Zizaco/Confide/EloquentRepository.php | 4 +- .../Confide/EloquentPasswordServiceTest.php | 92 +++++++++++++++++++ .../Zizaco/Confide/EloquentRepositoryTest.php | 7 -- 4 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 src/Zizaco/Confide/EloquentPasswordService.php create mode 100644 tests/Zizaco/Confide/EloquentPasswordServiceTest.php diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php new file mode 100644 index 0000000..9567e43 --- /dev/null +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -0,0 +1,54 @@ +app = $app ?: app(); + } + + /** + * Generate a token for password change and saves it in + * the 'password_reminders' table with the email of the + * user. + * + * @param RemindableInterface $user An existent user + * @return string Password reset token + */ + public function requestChangePassword(RemindableInterface $user) + { + $email = $user->getReminderEmail(); + $token = $this->generateToken(); + + $values = array( + 'email'=> $email, + 'token'=> $token, + 'created_at'=> new \DateTime + ); + + $this->app['db'] + ->connection() + ->table('password_reminders') + ->insert( $values ); + + return $token; + } +} diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index 87a9ed3..f63c79d 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -1,7 +1,7 @@ app['db'] = $db; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Since the user implements the RemindableInterface. + // See: http://laravel.com/docs/security#password-reminders-and-reset + $user->shouldReceive('getReminderEmail') + ->andReturn($userEmail); + + // The PasswordService generate token method is the responsible + // for generating tokens + $passService->shouldReceive('generateToken') + ->andReturn($generatedToken); + + // Mocks DB in order to check for the following query: + // DB::table('password_reminders')->insert(array( + // 'email'=> $email, + // 'token'=> $token, + // 'created_at'=> new \DateTime + //)); + $db->shouldReceive('connection') + ->once() + ->andReturn( $db ); + + $db->shouldReceive('table') + ->with( 'password_reminders' ) + ->once() + ->andReturn( $db ); + + $db->shouldReceive('insert') + ->with([ + 'email' => $userEmail, + 'token' => $generatedToken, + 'created_at' => new \DateTime + ]) + ->once() + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + $generatedToken, + $passService->requestChangePassword($user) + ); + } +} diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index 1464b66..f9bf618 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -5,13 +5,6 @@ class EloquentRepositoryTest extends PHPUnit_Framework_TestCase { - /** - * ConfideRepository instance - * - * @var Zizaco\Confide\ConfideRepository - */ - protected $repo; - /** * Calls Mockery::close * From c8339d6cab40e7be3b04116b8993d4db07365c16 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Fri, 31 Jan 2014 21:13:51 -0200 Subject: [PATCH 006/115] Updated Mockery version in order to be able to allow mocking protected methods. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7108cd4..1990c38 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "illuminate/support": "4.1.x" }, "require-dev": { - "mockery/mockery": "0.7.2", + "mockery/mockery": "0.9.*@dev", "illuminate/database": "4.1.x", "illuminate/auth": "4.1.x" }, From 7489f2a17c8b46973daeebe5d065797e39871d2c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Fri, 31 Jan 2014 21:14:50 -0200 Subject: [PATCH 007/115] Updated the requestChangePassword test and added getEmailByToken method into EloquentPasswordService --- .../Confide/EloquentPasswordService.php | 32 +++++++++- .../Confide/EloquentPasswordServiceTest.php | 60 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 9567e43..bcea4ed 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -47,8 +47,38 @@ public function requestChangePassword(RemindableInterface $user) $this->app['db'] ->connection() ->table('password_reminders') - ->insert( $values ); + ->insert($values); return $token; } + + public function getEmailByToken($token) + { + $email = $this->app['db'] + ->connection() + ->table('password_reminders') + ->select('email')->where('token','=',$token) + ->first(); + + if ($email && is_object($email)) + { + $email = $email->email; + } + elseif ($email && is_array($email)) + { + $email = $email['email']; + } + + return $email; + } + + /** + * Generates a random password change token + * + * @return string + */ + protected function generateToken() + { + return md5(uniqid(mt_rand(), true)); + } } diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index ff1bbad..66ac31e 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -38,6 +38,8 @@ public function testSouldRequestChangePassword() $passService = m::mock('Zizaco\Confide\EloquentPasswordService[generateToken]',[]); $db = m::mock('connection'); + $passService->shouldAllowMockingProtectedMethods(); + $passService->app['db'] = $db; /* @@ -89,4 +91,62 @@ public function testSouldRequestChangePassword() $passService->requestChangePassword($user) ); } + + public function testShouldGetEmailByToken() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $userEmail = 'someone@somewhere.com'; + $token = '123456789'; + $passService = new EloquentPasswordService; + $db = m::mock('connection'); + + $passService->app['db'] = $db; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Mocks DB in order to check for the following query: + // DB::table('password_reminders') + // ->select('email') + // ->where('token','=',$token) + // ->first(); + $db->shouldReceive('connection') + ->once() + ->andReturn( $db ); + + $db->shouldReceive('table') + ->with('password_reminders') + ->andReturn( $db ) + ->once(); + + $db->shouldReceive('select') + ->with('email') + ->andReturn( $db ) + ->once(); + + $db->shouldReceive('where') + ->with('token', '=', $token) + ->andReturn( $db ) + ->once(); + + $db->shouldReceive('first') + ->once() + ->andReturn(['email' => $userEmail]); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + $userEmail, + $passService->getEmailByToken($token) + ); + } } From 7511fb1784e6fe360c106e7c17bee0517ff7a40d Mon Sep 17 00:00:00 2001 From: Zizaco Date: Fri, 31 Jan 2014 21:53:06 -0200 Subject: [PATCH 008/115] Changed the line where the brackets are openned. Wow --- tests/Zizaco/Confide/EloquentPasswordServiceTest.php | 3 ++- tests/Zizaco/Confide/EloquentRepositoryTest.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index 66ac31e..919a25f 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -4,7 +4,8 @@ use PHPUnit_Framework_TestCase; use Illuminate\Auth\Reminders\RemindableInterface; -class EloquentPasswordServiceTest extends PHPUnit_Framework_TestCase { +class EloquentPasswordServiceTest extends PHPUnit_Framework_TestCase +{ /** * ConfideRepository instance diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index f9bf618..793ff88 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -3,8 +3,8 @@ use Mockery as m; use PHPUnit_Framework_TestCase; -class EloquentRepositoryTest extends PHPUnit_Framework_TestCase { - +class EloquentRepositoryTest extends PHPUnit_Framework_TestCase +{ /** * Calls Mockery::close * From de6f08d0ab2b96acec93f241646af1ace81c72af Mon Sep 17 00:00:00 2001 From: Zizaco Date: Fri, 31 Jan 2014 21:53:55 -0200 Subject: [PATCH 009/115] Initial implementation of ServiceProvider with awesome testing in order to register the classes correctly. --- src/Zizaco/Confide/ServiceProvider.php | 70 ++++++++++++ tests/Zizaco/Confide/ServiceProviderTest.php | 114 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 src/Zizaco/Confide/ServiceProvider.php create mode 100644 tests/Zizaco/Confide/ServiceProviderTest.php diff --git a/src/Zizaco/Confide/ServiceProvider.php b/src/Zizaco/Confide/ServiceProvider.php new file mode 100644 index 0000000..abb5c2f --- /dev/null +++ b/src/Zizaco/Confide/ServiceProvider.php @@ -0,0 +1,70 @@ +package('zizaco/confide'); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + $this->registerRepository(); + + $this->registerConfide(); + + $this->registerCommands(); + } + + /** + * Register the repository that will handle all the database interaction. + * + * @return void + */ + protected function registerRepository() + { + $this->app->bind('confide.repository', function($app) + { + return new EloquentRepository; + }); + } + + /** + * Register the application bindings. + * + * @return void + */ + protected function registerConfide() + { + + } + + /** + * Register the artisan commands. + * + * @return void + */ + protected function registerCommands() + { + + } +} diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php new file mode 100644 index 0000000..0f7a8b7 --- /dev/null +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -0,0 +1,114 @@ +shouldReceive('package') + ->with('zizaco/confide') + ->once(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->boot(); + } + + public function testShouldRegister() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $sp = m::mock( + 'Zizaco\Confide\ServiceProvider'. + '[registerRepository,registerConfide,registerCommands]', + ['something'] + ); + $sp->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $sp->shouldReceive( + 'registerRepository','registerConfide', + 'registerCommands' + ) + ->once(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->register(); + } + + public function testShouldRegisterRepository() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $test = $this; + $app = m::mock('LaravelApp'); + $sp = new ServiceProvider($app); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app->shouldReceive('bind') + ->once()->andReturnUsing( + // Make sure that the name is 'confide.repository' + // and that the closure passed returns the correct + // kind of object. + function($name, $closure) use ($test, $app) { + $test->assertEquals('confide.repository', $name); + $test->assertInstanceOf( + 'Zizaco\Confide\EloquentRepository', + $closure($app) + ); + } + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->register(); + } +} From a31dba784f3991c713fa90a1975c0b465b7aa103 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Fri, 31 Jan 2014 22:36:39 -0200 Subject: [PATCH 010/115] Initial implementation of Interfaces for Repository and PasswordService in order to be able to implement other compatible services. --- src/Zizaco/Confide/EloquentPasswordService.php | 4 ++-- src/Zizaco/Confide/EloquentRepository.php | 4 ++-- src/Zizaco/Confide/PasswordServiceInterface.php | 6 ++++++ src/Zizaco/Confide/RepositoryInterface.php | 6 ++++++ src/Zizaco/Confide/ServiceProvider.php | 4 ++++ 5 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/Zizaco/Confide/PasswordServiceInterface.php create mode 100644 src/Zizaco/Confide/RepositoryInterface.php diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index bcea4ed..9f13d44 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -5,12 +5,12 @@ /** * A service that abstracts all user password management related methods */ -class EloquentPasswordService +class EloquentPasswordService implements PasswordServiceInterface { /** * Laravel application * - * @var Illuminate\Foundation\Application + * @var \Illuminate\Foundation\Application */ public $app; diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index f63c79d..4d3c2f0 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -4,12 +4,12 @@ * A service that abstracts all database interactions that happens * in Confide using Eloquent */ -class EloquentRepository +class EloquentRepository implements RepositoryInterface { /** * Laravel application * - * @var Illuminate\Foundation\Application + * @var \Illuminate\Foundation\Application */ public $app; diff --git a/src/Zizaco/Confide/PasswordServiceInterface.php b/src/Zizaco/Confide/PasswordServiceInterface.php new file mode 100644 index 0000000..58dfe4b --- /dev/null +++ b/src/Zizaco/Confide/PasswordServiceInterface.php @@ -0,0 +1,6 @@ + Date: Fri, 31 Jan 2014 22:37:14 -0200 Subject: [PATCH 011/115] Added Confide class the main entry point to the Confide usage. --- src/Zizaco/Confide/Confide.php | 81 ++++++++++++++++++++ tests/Zizaco/Confide/ConfideTest.php | 107 +++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 src/Zizaco/Confide/Confide.php create mode 100644 tests/Zizaco/Confide/ConfideTest.php diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php new file mode 100644 index 0000000..fb038a7 --- /dev/null +++ b/src/Zizaco/Confide/Confide.php @@ -0,0 +1,81 @@ +repo = $repo; + $this->passService = $passService; + $this->app = $app ?: app(); + } + + /** + * Returns an object of the model set in auth config + * + * @return mixed + */ + public function model() + { + return $this->repo->model(); + } + + /** + * Get the currently authenticated user or null. + * + * @return \Zizaco\Confide\ConfideUserInterface|null + */ + public function user() + { + return $this->app['auth']->user(); + } + + /** + * Sets the confirmation code of the user with the + * matching code to true. + * + * @param string $code + * @return bool Success + */ + public function confirm( $code ) + { + return $this->repo->confirmByCode($code); + } +} diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php new file mode 100644 index 0000000..55eb9c4 --- /dev/null +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -0,0 +1,107 @@ +shouldReceive('model') + ->once()->andReturn($modelInstance); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($modelInstance, $confide->model()); + } + + public function testShouldGetUser() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $confide = new Confide($repo, $passService, $app); + $user = m::mock('_mockedUser'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app['auth']->shouldReceive('user') + ->once()->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($user, $confide->user()); + } + + public function testShouldConfirm() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $confide = new Confide($repo, $passService, $app); + $modelInstance = m::mock('_mockedUser'); + $code = '12345'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $repo->shouldReceive('confirmByCode') + ->once()->with($code) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->confirm($code)); + } +} From 294b120ae21615b8b9d698e5e362c56cfca432ef Mon Sep 17 00:00:00 2001 From: Zizaco Date: Fri, 31 Jan 2014 23:38:33 -0200 Subject: [PATCH 012/115] Added logAttempt method to Confide main class in order to actually log in. --- src/Zizaco/Confide/Confide.php | 59 +++- tests/Zizaco/Confide/ConfideTest.php | 393 +++++++++++++++++++++++++++ 2 files changed, 451 insertions(+), 1 deletion(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index fb038a7..760c575 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -74,8 +74,65 @@ public function user() * @param string $code * @return bool Success */ - public function confirm( $code ) + public function confirm($code) { return $this->repo->confirmByCode($code); } + + /** + * Attempt to log a user into the application with + * password and identity field(s), usually email or username. + * + * @param array $input Array containing at least 'username' or 'email' and 'password'. Optionally the 'remember' boolean. + * @param bool $mustBeConfirmed If true, the user must have confirmed his email account in order to log-in. + * @return boolean Success + */ + public function logAttempt($input, $mustBeConfirmed = true) + { + $remember = $this->extractRememberFromArray($input); + $emailOrUsername = $this->extractIdentityFromArray($input); + $user = $this->repo->getUserByEmailOrUsername($emailOrUsername); + + if ($user) { + if (! $user->confirmed && $mustBeConfirmed ) + return false; + + $correctPassword = $this->app['hash']->check( + isset($input['password']) ? $input['password'] : false, + $user->password + ); + + if (! $correctPassword) + return false; + + $this->app['auth']->login($user, $remember); + return true; + } + + return false; + } + + protected function extractRememberFromArray($input) + { + if (isset($input['remember'])) { + $remember = $input['remember']; + } else { + $remember = false; + } + + return $remember; + } + + protected function extractIdentityFromArray($input) + { + if (isset($input['email'])) { + $emailOrUsername = $input['email']; + } elseif (isset($input['username'])) { + $emailOrUsername = $input['username']; + } else { + return false; + } + + return $emailOrUsername; + } } diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index 55eb9c4..65e4d04 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -104,4 +104,397 @@ public function testShouldConfirm() */ $this->assertTrue($confide->confirm($code)); } + + public function testShouldDoLogAttempt() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $app['hash'] = m::mock('Hash'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray,extractIdentityFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $user = m::mock('_mockedUser'); + $user->confirmed = true; + $user->email = 'someone@somewhere.com'; + $user->password = 'secret'; + + $remember = true; + $input = [ + 'email'=>$user->email, + 'password'=>$user->password, + 'remember'=>$remember + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->with($input)->andReturn(true); + + $confide->shouldReceive('extractIdentityFromArray') + ->with($input)->andReturn($user->email); + + $repo->shouldReceive('getUserByEmailOrUsername') + ->once()->with('someone@somewhere.com') + ->andReturn($user); + + $app['hash']->shouldReceive('check') + ->once()->with($user->password, $user->password) + ->andReturn(true); + + $app['auth']->shouldReceive('login') + ->once()->with($user, $remember) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->logAttempt($input)); + } + + public function testShouldFailLogAttemptIfUserNotFound() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $app['hash'] = m::mock('Hash'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray,extractIdentityFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $user = m::mock('_mockedUser'); + $user->confirmed = true; + $user->email = 'someone@somewhere.com'; + $user->password = 'secret'; + + $remember = true; + $input = [ + 'email'=>$user->email, + 'password'=>$user->password, + 'remember'=>$remember + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->with($input)->andReturn(true); + + $confide->shouldReceive('extractIdentityFromArray') + ->with($input)->andReturn($user->email); + + $repo->shouldReceive('getUserByEmailOrUsername') + ->once()->with('someone@somewhere.com') + ->andReturn(false); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertFalse($confide->logAttempt($input)); + } + + public function testShouldFailLogAttemptIfUserNotConfirmed() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $app['hash'] = m::mock('Hash'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray,extractIdentityFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $user = m::mock('_mockedUser'); + $user->confirmed = false; + $user->email = 'someone@somewhere.com'; + $user->password = 'secret'; + + $remember = true; + $input = [ + 'email'=>$user->email, + 'password'=>$user->password, + 'remember'=>$remember + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->with($input)->andReturn(true); + + $confide->shouldReceive('extractIdentityFromArray') + ->with($input)->andReturn($user->email); + + $repo->shouldReceive('getUserByEmailOrUsername') + ->once()->with('someone@somewhere.com') + ->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertFalse($confide->logAttempt($input)); + } + + public function testShouldFailLogAttemptIfWrongPass() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $app['hash'] = m::mock('Hash'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray,extractIdentityFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $user = m::mock('_mockedUser'); + $user->confirmed = true; + $user->email = 'someone@somewhere.com'; + $user->password = 'secret'; + + $remember = true; + $input = [ + 'email'=>$user->email, + 'password'=>$user->password, + 'remember'=>$remember + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->with($input)->andReturn(true); + + $confide->shouldReceive('extractIdentityFromArray') + ->with($input)->andReturn($user->email); + + $repo->shouldReceive('getUserByEmailOrUsername') + ->once()->with('someone@somewhere.com') + ->andReturn($user); + + $app['hash']->shouldReceive('check') + ->once()->with($user->password, $user->password) + ->andReturn(false); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertFalse($confide->logAttempt($input)); + } + + public function testShouldDoLogAttemptIfNotConfirmed() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $app['hash'] = m::mock('Hash'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray,extractIdentityFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $user = m::mock('_mockedUser'); + $user->confirmed = false; + $user->email = 'someone@somewhere.com'; + $user->password = 'secret'; + + $remember = true; + $input = [ + 'email'=>$user->email, + 'password'=>$user->password, + 'remember'=>$remember + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->with($input)->andReturn(true); + + $confide->shouldReceive('extractIdentityFromArray') + ->with($input)->andReturn($user->email); + + $repo->shouldReceive('getUserByEmailOrUsername') + ->once()->with('someone@somewhere.com') + ->andReturn($user); + + $app['hash']->shouldReceive('check') + ->once()->with($user->password, $user->password) + ->andReturn(true); + + $app['auth']->shouldReceive('login') + ->once()->with($user, $remember) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->logAttempt($input, false)); + } + + public function testShouldExtractRememberFromArray() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $inputWithoutRemember = []; + $inputWithRemember = [ + 'remember' => true + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue( + $confide->extractRememberFromArray($inputWithRemember) + ); + $this->assertFalse( + $confide->extractRememberFromArray($inputWithoutRemember) + ); + } + + public function testShouldExtractIdentityFromArray() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractIdentityFromArray]', + [$repo, $passService, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $emptyId = ['garbage'=>'dontNeed']; + $userId = ['username' => 'someone', 'garbage'=>'dontNeed']; + $emailId = ['email' => 'someone@somewhere.com', 'garbage'=>'dontNeed']; + $bothId = ['email' => 'someone@somewhere.com', 'username' => 'someone', 'garbage'=>'dontNeed']; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractIdentityFromArray') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + false, + $confide->extractIdentityFromArray($emptyId) + ); + $this->assertEquals( + 'someone', + $confide->extractIdentityFromArray($userId) + ); + $this->assertEquals( + 'someone@somewhere.com', + $confide->extractIdentityFromArray($emailId) + ); + $this->assertEquals( + 'someone@somewhere.com', + $confide->extractIdentityFromArray($bothId) + ); + } } From 12d564d993bdebc1a8776b63306664894b25cacf Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 00:05:38 -0200 Subject: [PATCH 013/115] Added forgotPassword method to the main Confide class. --- src/Zizaco/Confide/Confide.php | 29 +++++++++++++----- tests/Zizaco/Confide/ConfideTest.php | 44 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 760c575..01c8b26 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -115,24 +115,39 @@ public function logAttempt($input, $mustBeConfirmed = true) protected function extractRememberFromArray($input) { if (isset($input['remember'])) { - $remember = $input['remember']; + return $input['remember']; } else { - $remember = false; + return false; } - - return $remember; } protected function extractIdentityFromArray($input) { if (isset($input['email'])) { - $emailOrUsername = $input['email']; + return $input['email']; } elseif (isset($input['username'])) { - $emailOrUsername = $input['username']; + return $input['username']; } else { return false; } + } + + /** + * If an user with the given email exists then generate + * a token for password change and saves it in the + * 'password_reminders' table with the email of the + * user. + * + * @param string $email + * @return bool + */ + public function forgotPassword($email) + { + $user = $this->repo->getUserByEmail($email); - return $emailOrUsername; + if ($user) + return $this->passService->requestChangePassword($user); + + return false; } } diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index 65e4d04..0d15124 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -497,4 +497,48 @@ public function testShouldExtractIdentityFromArray() $confide->extractIdentityFromArray($bothId) ); } + + public function testShouldForgotPassword() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $confide = new Confide($repo, $passService, $app); + $user = m::mock('_mockedUser'); + $user->email = 'someone@somewhere.com'; + $generatedToken = '12345'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $repo->shouldReceive('getUserByEmail') + ->once()->with($user->email) + ->andReturn($user); + + $repo->shouldReceive('getUserByEmail') + ->andReturn(false); + + $passService->shouldReceive('requestChangePassword') + ->once()->with($user) + ->andReturn($generatedToken); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + $generatedToken, + $confide->forgotPassword($user->email) + ); + + $this->assertFalse($confide->forgotPassword('wrong@somewhere.com')); + } } From f3a1a936b49caa0499e1929785329ce96e5e9758 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 00:49:00 -0200 Subject: [PATCH 014/115] Added logout, getUserByResetPasswordToken and view rendering helpers into Confide class. --- src/Zizaco/Confide/Confide.php | 83 ++++++++++++++++- tests/Zizaco/Confide/ConfideTest.php | 131 +++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 1 deletion(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 01c8b26..4ebc1ce 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -139,7 +139,7 @@ protected function extractIdentityFromArray($input) * user. * * @param string $email - * @return bool + * @return string $token */ public function forgotPassword($email) { @@ -150,4 +150,85 @@ public function forgotPassword($email) return false; } + + /** + * Returns a user that corresponds to the given reset + * password token or false if there is no user with the + * given token. + * @param string $token + * @return ConfideUser + */ + public function userByResetPasswordToken($token) + { + $email = $this->passService->getEmailByToken($token); + + if ($email) { + return $this->repo->getUserByEmail($email); + } + + return false; + } + + /** + * Log the user out of the application. + * + * @return void + */ + public function logout() + { + return $this->app['auth']->logout(); + } + + /** + * Display the default login view + * + * @return \Illuminate\View\View + */ + public function makeLoginForm() + { + return $this->app['view'] + ->make( + $this->app['config']->get('confide::login_form') + ); + } + + /** + * Display the default signup view + * + * @return \Illuminate\View\View + */ + public function makeSignupForm() + { + return $this->app['view'] + ->make( + $this->app['config']->get('confide::signup_form') + ); + } + + /** + * Display the forget password view + * + * @return \Illuminate\View\View + */ + public function makeForgotPasswordForm() + { + return $this->app['view'] + ->make( + $this->app['config']->get('confide::forgot_password_form') + ); + } + + /** + * Display the forget password view + * + * @return \Illuminate\View\View + */ + public function makeResetPasswordForm( $token ) + { + return $this->app['view'] + ->make( + $this->app['config']->get('confide::reset_password_form'), + array('token'=>$token) + ); + } } diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index 0d15124..571b999 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -509,6 +509,7 @@ public function testShouldForgotPassword() $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $confide = new Confide($repo, $passService, $app); + $user = m::mock('_mockedUser'); $user->email = 'someone@somewhere.com'; $generatedToken = '12345'; @@ -541,4 +542,134 @@ public function testShouldForgotPassword() $this->assertFalse($confide->forgotPassword('wrong@somewhere.com')); } + + public function testShouldGetUserByPasswordResetToken() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $confide = new Confide($repo, $passService, $app); + + $user = m::mock('_mockedUser'); + $user->email = 'someone@somewhere.com'; + $token = '12345'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $passService->shouldReceive('getEmailByToken') + ->once()->with($token) + ->andReturn($user->email); + + $passService->shouldReceive('getEmailByToken') + ->andReturn(false); + + $repo->shouldReceive('getUserByEmail') + ->once()->with($user->email) + ->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + $user, + $confide->userByResetPasswordToken($token) + ); + + $this->assertFalse( + $confide->userByResetPasswordToken('wrong') + ); + } + + public function testShouldDoLogout() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $confide = new Confide($repo, $passService, $app); + $user = m::mock('_mockedUser'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app['auth']->shouldReceive('logout') + ->once()->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->logout()); + } + + public function testShouldMakeViews() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['config'] = m::mock('Config'); + $app['view'] = m::mock('ViewEnv'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $confide = new Confide($repo, $passService, $app); + $token = '12345'; + $view = m::mock('View'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app['view']->shouldReceive('make') + ->once()->with('view.confide::login_form') + ->andReturn($view); + $app['view']->shouldReceive('make') + ->once()->with('view.confide::signup_form') + ->andReturn($view); + $app['view']->shouldReceive('make') + ->once()->with('view.confide::forgot_password_form') + ->andReturn($view); + $app['view']->shouldReceive('make') + ->once()->with( + 'view.confide::reset_password_form', + ['token'=>$token] + ) + ->andReturn($view); + + $app['config']->shouldReceive('get') + ->times(4)->andReturnUsing(function($name){ + return 'view.'.$name; + }); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($view, $confide->makeLoginForm()); + $this->assertEquals($view, $confide->makeSignupForm()); + $this->assertEquals($view, $confide->makeForgotPasswordForm()); + $this->assertEquals($view, $confide->makeResetPasswordForm($token)); + } } From e199d87e8d7ea70e21e0bde4d331126fa892c024 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 01:12:42 -0200 Subject: [PATCH 015/115] Added Confide Facade and the registerConfide implementation to the ServiceProvider in order to make the main Confide class available to the application. --- src/Zizaco/Confide/Facade.php | 17 +++++++ src/Zizaco/Confide/ServiceProvider.php | 9 +++- tests/Zizaco/Confide/ServiceProviderTest.php | 50 +++++++++++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/Zizaco/Confide/Facade.php diff --git a/src/Zizaco/Confide/Facade.php b/src/Zizaco/Confide/Facade.php new file mode 100644 index 0000000..cf8d84d --- /dev/null +++ b/src/Zizaco/Confide/Facade.php @@ -0,0 +1,17 @@ +app->bind('confide', function($app) + { + return new Confide( + $app->make('confide.repository'), + $app->make('confide.password'), + $app + ); + }); } /** diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php index 0f7a8b7..834e2b9 100644 --- a/tests/Zizaco/Confide/ServiceProviderTest.php +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -83,7 +83,7 @@ public function testShouldRegisterRepository() */ $test = $this; $app = m::mock('LaravelApp'); - $sp = new ServiceProvider($app); + $sp = m::mock('Zizaco\Confide\ServiceProvider', [$app]); /* |------------------------------------------------------------ @@ -109,6 +109,52 @@ function($name, $closure) use ($test, $app) { | Assertion |------------------------------------------------------------ */ - $sp->register(); + $sp->registerRepository(); + } + + public function testShouldRegisterConfide() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $test = $this; + $app = m::mock('LaravelApp'); + $sp = m::mock('Zizaco\Confide\ServiceProvider', [$app]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app->shouldReceive('make') + ->once()->with('confide.repository') + ->andReturn(new EloquentRepository); + + $app->shouldReceive('make') + ->once()->with('confide.password') + ->andReturn(new EloquentPasswordService); + + $app->shouldReceive('bind') + ->once()->andReturnUsing( + // Make sure that the name is 'confide.repository' + // and that the closure passed returns the correct + // kind of object. + function($name, $closure) use ($test, $app) { + $test->assertEquals('confide', $name); + $test->assertInstanceOf( + 'Zizaco\Confide\Confide', + $closure($app) + ); + } + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->registerConfide(); } } From 3b565c89fff0ddc5a191636e326391a444d691a3 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 01:15:13 -0200 Subject: [PATCH 016/115] Added the PasswordService to the ServiceProvider. --- src/Zizaco/Confide/ServiceProvider.php | 17 +++++++- tests/Zizaco/Confide/ServiceProviderTest.php | 42 +++++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/Zizaco/Confide/ServiceProvider.php b/src/Zizaco/Confide/ServiceProvider.php index 802846c..4a83af4 100644 --- a/src/Zizaco/Confide/ServiceProvider.php +++ b/src/Zizaco/Confide/ServiceProvider.php @@ -34,6 +34,8 @@ public function register() { $this->registerRepository(); + $this->registerPasswordService(); + $this->registerConfide(); $this->registerCommands(); @@ -48,7 +50,20 @@ protected function registerRepository() { $this->app->bind('confide.repository', function($app) { - return new EloquentRepository; + return new EloquentRepository($app); + }); + } + + /** + * Register the repository that will handle all the database interaction. + * + * @return void + */ + protected function registerPasswordService() + { + $this->app->bind('confide.password', function($app) + { + return new EloquentPasswordService($app); }); } diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php index 834e2b9..8f23094 100644 --- a/tests/Zizaco/Confide/ServiceProviderTest.php +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -50,7 +50,7 @@ public function testShouldRegister() */ $sp = m::mock( 'Zizaco\Confide\ServiceProvider'. - '[registerRepository,registerConfide,registerCommands]', + '[registerRepository,registerPasswordService,registerConfide,registerCommands]', ['something'] ); $sp->shouldAllowMockingProtectedMethods(); @@ -62,7 +62,7 @@ public function testShouldRegister() */ $sp->shouldReceive( 'registerRepository','registerConfide', - 'registerCommands' + 'registerCommands','registerPasswordService' ) ->once(); @@ -112,6 +112,44 @@ function($name, $closure) use ($test, $app) { $sp->registerRepository(); } + public function testShouldRegisterPasswordService() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $test = $this; + $app = m::mock('LaravelApp'); + $sp = m::mock('Zizaco\Confide\ServiceProvider', [$app]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app->shouldReceive('bind') + ->once()->andReturnUsing( + // Make sure that the name is 'confide.password' + // and that the closure passed returns the correct + // kind of object. + function($name, $closure) use ($test, $app) { + $test->assertEquals('confide.password', $name); + $test->assertInstanceOf( + 'Zizaco\Confide\EloquentPasswordService', + $closure($app) + ); + } + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->registerPasswordService(); + } + public function testShouldRegisterConfide() { /* From c96e1714ff5cd6f475682d45c7eabaaa46dd7794 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 11:03:01 -0200 Subject: [PATCH 017/115] Added package information to class docblocks. --- src/Zizaco/Confide/Confide.php | 2 ++ src/Zizaco/Confide/EloquentPasswordService.php | 2 ++ src/Zizaco/Confide/EloquentRepository.php | 2 ++ src/Zizaco/Confide/Facade.php | 1 + 4 files changed, 7 insertions(+) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 4ebc1ce..100daf8 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -4,6 +4,8 @@ * This class is the main entry point to use the confide * services. Usually this is the only service class that the * application will interact directly with. + * + * @package Zizaco\Confide */ class Confide { diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 9f13d44..811efb2 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -4,6 +4,8 @@ /** * A service that abstracts all user password management related methods + * + * @package Zizaco\Confide */ class EloquentPasswordService implements PasswordServiceInterface { diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index 4d3c2f0..c3f778a 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -3,6 +3,8 @@ /** * A service that abstracts all database interactions that happens * in Confide using Eloquent + * + * @package Zizaco\Confide */ class EloquentRepository implements RepositoryInterface { diff --git a/src/Zizaco/Confide/Facade.php b/src/Zizaco/Confide/Facade.php index cf8d84d..c398342 100644 --- a/src/Zizaco/Confide/Facade.php +++ b/src/Zizaco/Confide/Facade.php @@ -4,6 +4,7 @@ /** * @see \Zizaco\Confide\Facade + * @package Zizaco\Confide */ class Facade extends IlluminateFacade { From eddc8daaaf86dc5624fa547f16650b1bed7b6107 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 11:04:10 -0200 Subject: [PATCH 018/115] Added LoginThrottleService in order to throttles too many failed login attempts. --- .../Confide/CacheLoginThrottleService.php | 74 ++++++++++++++++ .../Confide/LoginThrottleServiceInterface.php | 6 ++ .../Confide/CacheLoginThrottleServiceTest.php | 87 +++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 src/Zizaco/Confide/CacheLoginThrottleService.php create mode 100644 src/Zizaco/Confide/LoginThrottleServiceInterface.php create mode 100644 tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php new file mode 100644 index 0000000..16695be --- /dev/null +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -0,0 +1,74 @@ +app = $app ?: app(); + } + + /** + * Increments the count for the given identity by one and + * also returns the current value for that identity. + * + * @param mixed $identity The login identity + * @return integer How many times that same identity was used + */ + public function throttleIdentity($identity) + { + // If is an array, remove password, remember and then + // transforms it into a string. + if (is_array($identity)) + { + unset($identity['password']); + unset($identity['remember']); + $identity = serialize($identity); + } + + // Increments and also retuns the current count + return $this->countThrottle($identity); + } + + /** + * Increments the count for the given string by one stores + * it into cache and returns the current value for that + * identity. + * + * @param string $identityString + * @return integer How many times that same string was used + */ + protected function countThrottle($identityString) + { + $count = $this->app['cache'] + ->get('login_throttling:'.md5($identityString), 0); + + $count++; + + $ttl = $this->app['config']->get('confide::throttle_time_period'); + + $this->app['cache'] + ->put('login_throttling:'.md5($identityString), $count, $ttl); + + return $count; + } +} diff --git a/src/Zizaco/Confide/LoginThrottleServiceInterface.php b/src/Zizaco/Confide/LoginThrottleServiceInterface.php new file mode 100644 index 0000000..8cfd64a --- /dev/null +++ b/src/Zizaco/Confide/LoginThrottleServiceInterface.php @@ -0,0 +1,6 @@ +'someone@somewhere.com','password'=>'123']; + + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle]',[]); + $throttleService->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $throttleService->shouldReceive('countThrottle') + ->once()->with(serialize(['email'=>'someone@somewhere.com'])) + ->andReturn(5); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals(5, $throttleService->throttleIdentity($identity)); + } + + public function testShouldCountThrottle() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $idString = serialize(['email'=>'someone@somewhere.com']); + $cache = m::mock('Cache'); + $config = m::mock('Config'); + $app = ['cache'=>$cache, 'config'=>$config]; + + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle]',[$app]); + + $ttl = 3; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $cache->shouldReceive('get') + ->once()->with('login_throttling:'.md5($idString), 0) + ->andReturn(1); + + $config->shouldReceive('get') + ->once()->with('confide::throttle_time_period') + ->andReturn($ttl); + + $cache->shouldReceive('put') + ->once()->with('login_throttling:'.md5($idString), 2, $ttl) + ->andReturn(1); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals(2, $throttleService->countThrottle($idString)); + } +} From da635fb2f8f0ee09477fc6cf262ac0ac195a7581 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 11:10:15 -0200 Subject: [PATCH 019/115] Added the throttle service to the service provider in order to register the service into IoC container. --- .../Confide/CacheLoginThrottleService.php | 4 +- src/Zizaco/Confide/ServiceProvider.php | 23 ++++++++- tests/Zizaco/Confide/ServiceProviderTest.php | 47 +++++++++++++++++-- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php index 16695be..cae4b40 100644 --- a/src/Zizaco/Confide/CacheLoginThrottleService.php +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -1,8 +1,8 @@ registerPasswordService(); + $this->registerLoginThrottleService(); + $this->registerConfide(); $this->registerCommands(); } /** - * Register the repository that will handle all the database interaction. + * Register the repository that will handle all the database + * interaction. * * @return void */ @@ -55,7 +58,8 @@ protected function registerRepository() } /** - * Register the repository that will handle all the database interaction. + * Register the service that abstracts all user password management + * related methods * * @return void */ @@ -67,6 +71,21 @@ protected function registerPasswordService() }); } + /** + * Register the service that Throttles login after + * too many failed attempts. This is a secure measure in + * order to avoid brute force attacks. + * + * @return void + */ + protected function registerLoginThrottleService() + { + $this->app->bind('confide.throttle', function($app) + { + return new CacheLoginThrottleService($app); + }); + } + /** * Register the application bindings. * diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php index 8f23094..193cfa0 100644 --- a/tests/Zizaco/Confide/ServiceProviderTest.php +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -50,7 +50,9 @@ public function testShouldRegister() */ $sp = m::mock( 'Zizaco\Confide\ServiceProvider'. - '[registerRepository,registerPasswordService,registerConfide,registerCommands]', + '[registerRepository,registerPasswordService,'. + 'registerConfide,registerCommands,'. + 'registerLoginThrottleService]', ['something'] ); $sp->shouldAllowMockingProtectedMethods(); @@ -62,7 +64,8 @@ public function testShouldRegister() */ $sp->shouldReceive( 'registerRepository','registerConfide', - 'registerCommands','registerPasswordService' + 'registerCommands','registerPasswordService', + 'registerLoginThrottleService' ) ->once(); @@ -150,6 +153,44 @@ function($name, $closure) use ($test, $app) { $sp->registerPasswordService(); } + public function testShouldRegisterLoginThrottleService() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $test = $this; + $app = m::mock('LaravelApp'); + $sp = m::mock('Zizaco\Confide\ServiceProvider', [$app]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app->shouldReceive('bind') + ->once()->andReturnUsing( + // Make sure that the name is 'confide.password' + // and that the closure passed returns the correct + // kind of object. + function($name, $closure) use ($test, $app) { + $test->assertEquals('confide.throttle', $name); + $test->assertInstanceOf( + 'Zizaco\Confide\CacheLoginThrottleService', + $closure($app) + ); + } + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->registerLoginThrottleService(); + } + public function testShouldRegisterConfide() { /* @@ -176,7 +217,7 @@ public function testShouldRegisterConfide() $app->shouldReceive('bind') ->once()->andReturnUsing( - // Make sure that the name is 'confide.repository' + // Make sure that the name is 'confide' // and that the closure passed returns the correct // kind of object. function($name, $closure) use ($test, $app) { From 22ca68800ab643cac052c8b3d069a8d88d97cd57 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 11:18:41 -0200 Subject: [PATCH 020/115] Added the LoginThrottleServiceInterface dependency injection to the main Confide class. --- src/Zizaco/Confide/Confide.php | 24 +++++++---- src/Zizaco/Confide/ServiceProvider.php | 1 + tests/Zizaco/Confide/ConfideTest.php | 42 +++++++++++++------- tests/Zizaco/Confide/ServiceProviderTest.php | 6 ++- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 100daf8..492bbf3 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -30,23 +30,33 @@ class Confide */ public $passService; + /** + * Confide login throttling service instance + * + * @var \Zizaco\Confide\LoginThrottleServiceInterface + */ + public $loginThrottler; + /** * Create a new Confide class * - * @param \Zizaco\Confide\RepositoryInterface $repo - * @param \Zizaco\Confide\PasswordServiceInterface $passService + * @param \Zizaco\Confide\RepositoryInterface $repo + * @param \Zizaco\Confide\PasswordServiceInterface $passService + * @param \Zizaco\Confide\LoginThrottleServiceInterface $loginThrottler * @param \Illuminate\Foundation\Application $app Laravel application object * @return void */ public function __construct( - RepositoryInterface $repo, - PasswordServiceInterface $passService, + RepositoryInterface $repo, + PasswordServiceInterface $passService, + LoginThrottleServiceInterface $loginThrottler, $app = null ) { - $this->repo = $repo; - $this->passService = $passService; - $this->app = $app ?: app(); + $this->repo = $repo; + $this->passService = $passService; + $this->loginThrottler = $loginThrottler; + $this->app = $app ?: app(); } /** diff --git a/src/Zizaco/Confide/ServiceProvider.php b/src/Zizaco/Confide/ServiceProvider.php index 366633b..3bf89eb 100644 --- a/src/Zizaco/Confide/ServiceProvider.php +++ b/src/Zizaco/Confide/ServiceProvider.php @@ -98,6 +98,7 @@ protected function registerConfide() return new Confide( $app->make('confide.repository'), $app->make('confide.password'), + $app->make('confide.throttle'), $app ); }); diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index 571b999..c7a95cc 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -25,7 +25,8 @@ public function testShouldGetModel() $app = []; $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $modelInstance = m::mock('_mockedUser'); /* @@ -55,7 +56,8 @@ public function testShouldGetUser() $app['auth'] = m::mock('Auth'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $user = m::mock('_mockedUser'); /* @@ -84,7 +86,8 @@ public function testShouldConfirm() $app = []; $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $modelInstance = m::mock('_mockedUser'); $code = '12345'; @@ -117,11 +120,12 @@ public function testShouldDoLogAttempt() $app['hash'] = m::mock('Hash'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractRememberFromArray,extractIdentityFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -180,11 +184,12 @@ public function testShouldFailLogAttemptIfUserNotFound() $app['hash'] = m::mock('Hash'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractRememberFromArray,extractIdentityFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -235,11 +240,12 @@ public function testShouldFailLogAttemptIfUserNotConfirmed() $app['hash'] = m::mock('Hash'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractRememberFromArray,extractIdentityFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -290,11 +296,12 @@ public function testShouldFailLogAttemptIfWrongPass() $app['hash'] = m::mock('Hash'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractRememberFromArray,extractIdentityFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -349,11 +356,12 @@ public function testShouldDoLogAttemptIfNotConfirmed() $app['hash'] = m::mock('Hash'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractRememberFromArray,extractIdentityFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -410,11 +418,12 @@ public function testShouldExtractRememberFromArray() $app = []; $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractRememberFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -454,11 +463,12 @@ public function testShouldExtractIdentityFromArray() $app = []; $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( 'Zizaco\Confide\Confide'. '[extractIdentityFromArray]', - [$repo, $passService, $app] + [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -508,7 +518,8 @@ public function testShouldForgotPassword() $app = []; $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $user = m::mock('_mockedUser'); $user->email = 'someone@somewhere.com'; @@ -553,7 +564,8 @@ public function testShouldGetUserByPasswordResetToken() $app = []; $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $user = m::mock('_mockedUser'); $user->email = 'someone@somewhere.com'; @@ -601,7 +613,8 @@ public function testShouldDoLogout() $app['auth'] = m::mock('Auth'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $user = m::mock('_mockedUser'); /* @@ -632,7 +645,8 @@ public function testShouldMakeViews() $app['view'] = m::mock('ViewEnv'); $repo = m::mock('Zizaco\Confide\RepositoryInterface'); $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); - $confide = new Confide($repo, $passService, $app); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = new Confide($repo, $passService, $loginThrottler, $app); $token = '12345'; $view = m::mock('View'); diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php index 193cfa0..c266240 100644 --- a/tests/Zizaco/Confide/ServiceProviderTest.php +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -171,7 +171,7 @@ public function testShouldRegisterLoginThrottleService() */ $app->shouldReceive('bind') ->once()->andReturnUsing( - // Make sure that the name is 'confide.password' + // Make sure that the name is 'confide.throttle' // and that the closure passed returns the correct // kind of object. function($name, $closure) use ($test, $app) { @@ -215,6 +215,10 @@ public function testShouldRegisterConfide() ->once()->with('confide.password') ->andReturn(new EloquentPasswordService); + $app->shouldReceive('make') + ->once()->with('confide.throttle') + ->andReturn(new CacheLoginThrottleService); + $app->shouldReceive('bind') ->once()->andReturnUsing( // Make sure that the name is 'confide' From 2ad9871f56b54f90e8afec8df957fa5eb6ec8bea Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 11:47:32 -0200 Subject: [PATCH 021/115] Added the login throttling feature to Confide::logAttempt method. --- src/Zizaco/Confide/Confide.php | 20 ++++ tests/Zizaco/Confide/ConfideTest.php | 138 ++++++++++++++++++++++++++- 2 files changed, 153 insertions(+), 5 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 492bbf3..e285be7 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -103,6 +103,10 @@ public function logAttempt($input, $mustBeConfirmed = true) { $remember = $this->extractRememberFromArray($input); $emailOrUsername = $this->extractIdentityFromArray($input); + + if (!$this->loginThrottling($emailOrUsername)) + return false; + $user = $this->repo->getUserByEmailOrUsername($emailOrUsername); if ($user) { @@ -144,6 +148,22 @@ protected function extractIdentityFromArray($input) } } + protected function loginThrottling($identity) + { + $count = $this->loginThrottler + ->throttleIdentity($identity); + + if ($count >= $this->app['config']->get('confide::throttle_limit')) + return false; + + // Throttling delay! + // See: http://www.codinghorror.com/blog/2009/01/dictionary-attacks-101.html + if($count > 3) + sleep(($count-1)); + + return true; + } + /** * If an user with the given email exists then generate * a token for password change and saves it in the diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index c7a95cc..bdc9089 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -124,7 +124,7 @@ public function testShouldDoLogAttempt() $confide = m::mock( 'Zizaco\Confide\Confide'. - '[extractRememberFromArray,extractIdentityFromArray]', + '[extractRememberFromArray,extractIdentityFromArray,loginThrottling]', [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -152,6 +152,10 @@ public function testShouldDoLogAttempt() $confide->shouldReceive('extractIdentityFromArray') ->with($input)->andReturn($user->email); + $confide->shouldReceive('loginThrottling') + ->once()->with($user->email) + ->andReturn(true); + $repo->shouldReceive('getUserByEmailOrUsername') ->once()->with('someone@somewhere.com') ->andReturn($user); @@ -172,6 +176,62 @@ public function testShouldDoLogAttempt() $this->assertTrue($confide->logAttempt($input)); } + public function testShouldFailLogAttemptIfThrottled() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $app['auth'] = m::mock('Auth'); + $app['hash'] = m::mock('Hash'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractRememberFromArray,extractIdentityFromArray,loginThrottling]', + [$repo, $passService, $loginThrottler, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $user = m::mock('_mockedUser'); + $user->confirmed = true; + $user->email = 'someone@somewhere.com'; + $user->password = 'secret'; + + $remember = true; + $input = [ + 'email'=>$user->email, + 'password'=>$user->password, + 'remember'=>$remember + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractRememberFromArray') + ->with($input)->andReturn(true); + + $confide->shouldReceive('extractIdentityFromArray') + ->with($input)->andReturn($user->email); + + $confide->shouldReceive('loginThrottling') + ->once()->with($user->email) + ->andReturn(false); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertFalse($confide->logAttempt($input)); + } + public function testShouldFailLogAttemptIfUserNotFound() { /* @@ -188,7 +248,7 @@ public function testShouldFailLogAttemptIfUserNotFound() $confide = m::mock( 'Zizaco\Confide\Confide'. - '[extractRememberFromArray,extractIdentityFromArray]', + '[extractRememberFromArray,extractIdentityFromArray,loginThrottling]', [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -216,6 +276,10 @@ public function testShouldFailLogAttemptIfUserNotFound() $confide->shouldReceive('extractIdentityFromArray') ->with($input)->andReturn($user->email); + $confide->shouldReceive('loginThrottling') + ->once()->with($user->email) + ->andReturn(true); + $repo->shouldReceive('getUserByEmailOrUsername') ->once()->with('someone@somewhere.com') ->andReturn(false); @@ -244,7 +308,7 @@ public function testShouldFailLogAttemptIfUserNotConfirmed() $confide = m::mock( 'Zizaco\Confide\Confide'. - '[extractRememberFromArray,extractIdentityFromArray]', + '[extractRememberFromArray,extractIdentityFromArray,loginThrottling]', [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -272,6 +336,10 @@ public function testShouldFailLogAttemptIfUserNotConfirmed() $confide->shouldReceive('extractIdentityFromArray') ->with($input)->andReturn($user->email); + $confide->shouldReceive('loginThrottling') + ->once()->with($user->email) + ->andReturn(true); + $repo->shouldReceive('getUserByEmailOrUsername') ->once()->with('someone@somewhere.com') ->andReturn($user); @@ -300,7 +368,7 @@ public function testShouldFailLogAttemptIfWrongPass() $confide = m::mock( 'Zizaco\Confide\Confide'. - '[extractRememberFromArray,extractIdentityFromArray]', + '[extractRememberFromArray,extractIdentityFromArray,loginThrottling]', [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -328,6 +396,10 @@ public function testShouldFailLogAttemptIfWrongPass() $confide->shouldReceive('extractIdentityFromArray') ->with($input)->andReturn($user->email); + $confide->shouldReceive('loginThrottling') + ->once()->with($user->email) + ->andReturn(true); + $repo->shouldReceive('getUserByEmailOrUsername') ->once()->with('someone@somewhere.com') ->andReturn($user); @@ -360,7 +432,7 @@ public function testShouldDoLogAttemptIfNotConfirmed() $confide = m::mock( 'Zizaco\Confide\Confide'. - '[extractRememberFromArray,extractIdentityFromArray]', + '[extractRememberFromArray,extractIdentityFromArray,loginThrottling]', [$repo, $passService, $loginThrottler, $app] ); $confide->shouldAllowMockingProtectedMethods(); @@ -388,6 +460,10 @@ public function testShouldDoLogAttemptIfNotConfirmed() $confide->shouldReceive('extractIdentityFromArray') ->with($input)->andReturn($user->email); + $confide->shouldReceive('loginThrottling') + ->once()->with($user->email) + ->andReturn(true); + $repo->shouldReceive('getUserByEmailOrUsername') ->once()->with('someone@somewhere.com') ->andReturn($user); @@ -508,6 +584,58 @@ public function testShouldExtractIdentityFromArray() ); } + public function testShouldDoLoginThrottling() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $config = m::mock('Config'); + $app = ['config'=>$config]; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[loginThrottling]', + [$repo, $passService, $loginThrottler, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $userEmail = 'someone@somewhere.com'; + $throttledUserEmail = 'hack@me.com'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('loginThrottling') + ->passthru(); + + $config->shouldReceive('get') + ->twice()->with('confide::throttle_limit') + ->andReturn(19); + + $loginThrottler->shouldReceive('throttleIdentity') + ->once()->with($userEmail) + ->andReturn(0); + + $loginThrottler->shouldReceive('throttleIdentity') + ->once()->with($throttledUserEmail) + ->andReturn(20); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->loginThrottling($userEmail)); + $this->assertFalse($confide->loginThrottling($throttledUserEmail)); + } + public function testShouldForgotPassword() { /* From a20e28d1263e6e9912dc5bc8d4372c354e31e981 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 11:54:22 -0200 Subject: [PATCH 022/115] Added docblocks for Confide protected methods and adjusted the loginThrottling sleep time. --- src/Zizaco/Confide/Confide.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index e285be7..81c990b 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -128,6 +128,12 @@ public function logAttempt($input, $mustBeConfirmed = true) return false; } + /** + * Extracts the value of the remember key of the given + * array + * @param array $input An array containing the key 'remember' + * @return boolean + */ protected function extractRememberFromArray($input) { if (isset($input['remember'])) { @@ -137,6 +143,12 @@ protected function extractRememberFromArray($input) } } + /** + * Extracts the email or the username key of the given + * array + * @param array $input An array containing the key 'email' or 'username' + * @return mixed + */ protected function extractIdentityFromArray($input) { if (isset($input['email'])) { @@ -148,6 +160,13 @@ protected function extractIdentityFromArray($input) } } + /** + * Calls throttleIdentity of the loginThrottler and returns false + * if the throttleCount is grater then the 'throttle_limit' config. + * Also sleeps a little in order to protect from dicionary attacks. + * @param mixed $identity + * @return boolean False if the identity has reached the 'throttle_limit' + */ protected function loginThrottling($identity) { $count = $this->loginThrottler @@ -158,8 +177,8 @@ protected function loginThrottling($identity) // Throttling delay! // See: http://www.codinghorror.com/blog/2009/01/dictionary-attacks-101.html - if($count > 3) - sleep(($count-1)); + if($count > 2) + sleep(($count-1) * 400000); return true; } From 0725cb7595502eb42a215372e37f5480d9fded34 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 13:22:59 -0200 Subject: [PATCH 023/115] Added method declarations into interfaces in order to imply the interface that services should have. --- src/Zizaco/Confide/Confide.php | 2 +- .../Confide/EloquentPasswordService.php | 6 +++ .../Confide/LoginThrottleServiceInterface.php | 16 ++++++- .../Confide/PasswordServiceInterface.php | 23 ++++++++++ src/Zizaco/Confide/RepositoryInterface.php | 45 +++++++++++++++++++ tests/Zizaco/Confide/ConfideTest.php | 2 +- 6 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 81c990b..ab07d17 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -163,7 +163,7 @@ protected function extractIdentityFromArray($input) /** * Calls throttleIdentity of the loginThrottler and returns false * if the throttleCount is grater then the 'throttle_limit' config. - * Also sleeps a little in order to protect from dicionary attacks. + * Also sleeps a little in order to avoid dicionary attacks. * @param mixed $identity * @return boolean False if the identity has reached the 'throttle_limit' */ diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 811efb2..36b3c2b 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -54,6 +54,12 @@ public function requestChangePassword(RemindableInterface $user) return $token; } + /** + * Returns the email associated with the given reset + * password token + * @param string $token + * @return string Email + */ public function getEmailByToken($token) { $email = $this->app['db'] diff --git a/src/Zizaco/Confide/LoginThrottleServiceInterface.php b/src/Zizaco/Confide/LoginThrottleServiceInterface.php index 8cfd64a..ed4ebdf 100644 --- a/src/Zizaco/Confide/LoginThrottleServiceInterface.php +++ b/src/Zizaco/Confide/LoginThrottleServiceInterface.php @@ -1,6 +1,20 @@ email = 'someone@somewhere.com'; $generatedToken = '12345'; From 4b6c5f5943c8fe674e0714c351f7cb1c90882780 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 17:41:20 -0200 Subject: [PATCH 024/115] Added ConfideUser to the application in order to easly setup an User model for the developer's application. --- src/Zizaco/Confide/Confide.php | 2 +- src/Zizaco/Confide/ConfideUser.php | 107 ++++++++++++++++ tests/Zizaco/Confide/ConfideUserTest.php | 148 +++++++++++++++++++++++ 3 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 src/Zizaco/Confide/ConfideUser.php create mode 100644 tests/Zizaco/Confide/ConfideUserTest.php diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index ab07d17..c74b09d 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -80,7 +80,7 @@ public function user() } /** - * Sets the confirmation code of the user with the + * Sets the 'confirmed' field of the user with the * matching code to true. * * @param string $code diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php new file mode 100644 index 0000000..bb1f2c5 --- /dev/null +++ b/src/Zizaco/Confide/ConfideUser.php @@ -0,0 +1,107 @@ +confirmed = 1; + + return ConfideFacade::confirm($this->confirmation_code); + } + + /** + * Generates a token for password change and saves it in the + * 'password_reminders' table with the email of the + * user. + * + * @return string $token + */ + public function forgotPassword() + { + return ConfideFacade::forgotPassword($this->email); + } + + /** + * Checks if the current user is valid using the ConfideUserValidator + * + * @return boolean + */ + public function isValid() + { + // Instantiate the ConfideUserValidator and calls the + // validate method. Feel free to use your own validation + // class. + $validator = App::make('ConfideUserValidator'); + + $validator->validate($this); + } + + /** + * Overwrites the original save method in order to perform + * validation before actually saving the object. + * + * @param array $options + * @return bool + */ + public function save(array $options = array()) + { + if ($this->isValid()) { + parent::save(); + } else { + return false; + } + } + + /** + * Get the unique identifier for the user. + * + * @see \Illuminate\Auth\UserInterface + * @return mixed + */ + public function getAuthIdentifier() + { + // Get the value of the model's primary key. + return $this->getKey(); + } + + /** + * Get the password for the user. + * + * @see \Illuminate\Auth\UserInterface + * @return string + */ + public function getAuthPassword() + { + return $this->password; + } +} diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php new file mode 100644 index 0000000..10f0975 --- /dev/null +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -0,0 +1,148 @@ +confirmation_code = '12345'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + ConfideFacade::shouldReceive('confirm') + ->once()->with($user->confirmation_code) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $user->confirm(); + } + + public function testShouldForgotPassword() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new ConfideUser; + $user->email = 'someone@somewhere.com'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + ConfideFacade::shouldReceive('forgotPassword') + ->once()->with($user->email) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $user->forgotPassword(); + } + + public function testIsValid() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new ConfideUser; + $validator = m::mock('Zizaco\Confide\Validator'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + App::shouldReceive('make') + ->once()->with('ConfideUserValidator') + ->andReturn($validator); + + $validator->shouldReceive('validate') + ->once()->with($user) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $user->isValid(); + } + + public function testShouldGetAuthIdentifier() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = m::mock('Zizaco\Confide\ConfideUser[getKey]'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $user->shouldReceive('getKey') + ->once() + ->andReturn(1); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals(1, $user->getAuthIdentifier()); + } + + public function testShouldGetAuthPassword() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = m::mock('Zizaco\Confide\ConfideUser[getKey]'); + $user->password = '1234'; + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals('1234', $user->getAuthPassword()); + } +} From 94f1f9f42233ffeed8045f237aaaf59584bdc63c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 18:01:46 -0200 Subject: [PATCH 025/115] Added error method and MessageBag handling in ConfideUser and license information in DocBlock of classes. --- .../Confide/CacheLoginThrottleService.php | 1 + src/Zizaco/Confide/Confide.php | 1 + src/Zizaco/Confide/ConfideUser.php | 23 ++++++++++++++ .../Confide/EloquentPasswordService.php | 1 + src/Zizaco/Confide/EloquentRepository.php | 1 + .../Confide/LoginThrottleServiceInterface.php | 1 + .../Confide/PasswordServiceInterface.php | 1 + src/Zizaco/Confide/RepositoryInterface.php | 1 + tests/Zizaco/Confide/ConfideUserTest.php | 31 +++++++++++++++++++ 9 files changed, 61 insertions(+) diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php index cae4b40..e48754f 100644 --- a/src/Zizaco/Confide/CacheLoginThrottleService.php +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -5,6 +5,7 @@ * too many failed attempts. This is a secure measure in * order to avoid brute force attacks. * + * @license MIT * @package Zizaco\Confide */ class CacheLoginThrottleService implements LoginThrottleServiceInterface diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index c74b09d..e1d96f4 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -5,6 +5,7 @@ * services. Usually this is the only service class that the * application will interact directly with. * + * @license MIT * @package Zizaco\Confide */ class Confide diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index bb1f2c5..b9ebcf1 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -7,6 +7,7 @@ /** * Eloquent implementation of the ConfideUserInterface. * + * @license MIT * @package Zizaco\Confide */ class ConfideUser extends Eloquent implements ConfideUserInterface { @@ -25,6 +26,14 @@ class ConfideUser extends Eloquent implements ConfideUserInterface { */ protected $hidden = array('password'); + /** + * A MessageBag object that store any error regarding + * the confide User. + * + * @var \Illuminate\Support\MessageBag + */ + public $errors; + /** * Confirm the user (usually means that the user) * email is valid. Sets the confirmed attribute of @@ -82,6 +91,20 @@ public function save(array $options = array()) } } + /** + * Returns a MessageBag object that store any error + * regarding the user validation + * + * @var \Illuminate\Support\MessageBag + */ + public function errors() + { + if (!$this->errors) + $this->errors = App::make('Illuminate\Support\MessageBag'); + + return $this->errors; + } + /** * Get the unique identifier for the user. * diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 36b3c2b..b5839fa 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -5,6 +5,7 @@ /** * A service that abstracts all user password management related methods * + * @license MIT * @package Zizaco\Confide */ class EloquentPasswordService implements PasswordServiceInterface diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index c3f778a..0525c76 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -4,6 +4,7 @@ * A service that abstracts all database interactions that happens * in Confide using Eloquent * + * @license MIT * @package Zizaco\Confide */ class EloquentRepository implements RepositoryInterface diff --git a/src/Zizaco/Confide/LoginThrottleServiceInterface.php b/src/Zizaco/Confide/LoginThrottleServiceInterface.php index ed4ebdf..5c63dad 100644 --- a/src/Zizaco/Confide/LoginThrottleServiceInterface.php +++ b/src/Zizaco/Confide/LoginThrottleServiceInterface.php @@ -5,6 +5,7 @@ * too many failed attempts. This is a secure measure in * order to avoid brute force attacks. * + * @license MIT * @package Zizaco\Confide */ interface LoginThrottleServiceInterface diff --git a/src/Zizaco/Confide/PasswordServiceInterface.php b/src/Zizaco/Confide/PasswordServiceInterface.php index fa37a18..3e477dc 100644 --- a/src/Zizaco/Confide/PasswordServiceInterface.php +++ b/src/Zizaco/Confide/PasswordServiceInterface.php @@ -5,6 +5,7 @@ /** * A service that abstracts all user password management related methods * + * @license MIT * @package Zizaco\Confide */ interface PasswordServiceInterface diff --git a/src/Zizaco/Confide/RepositoryInterface.php b/src/Zizaco/Confide/RepositoryInterface.php index ec3f122..816b161 100644 --- a/src/Zizaco/Confide/RepositoryInterface.php +++ b/src/Zizaco/Confide/RepositoryInterface.php @@ -4,6 +4,7 @@ * A service that abstracts all the interactions with persistent * storage for confide * + * @license MIT * @package Zizaco\Confide */ interface RepositoryInterface diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 10f0975..251326f 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -145,4 +145,35 @@ public function testShouldGetAuthPassword() */ $this->assertEquals('1234', $user->getAuthPassword()); } + + public function testErrors() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new ConfideUser; + $newMessageBag = m::mock('Illuminate\Support\MessageBag'); + $existentMessageBag = m::mock('Illuminate\Support\MessageBag'); + $user->errors = $existentMessageBag; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + App::shouldReceive('make') + ->once()->with('Illuminate\Support\MessageBag') + ->andReturn($newMessageBag); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($existentMessageBag, $user->errors()); + $user->errors = null; + $this->assertEquals($newMessageBag, $user->errors()); + } } From 89ed8f66561a202ef62722b3ea2689cb349db779 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 18:02:53 -0200 Subject: [PATCH 026/115] Changed test name in order to be more objective. --- tests/Zizaco/Confide/ConfideUserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 251326f..73c0f4e 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -146,7 +146,7 @@ public function testShouldGetAuthPassword() $this->assertEquals('1234', $user->getAuthPassword()); } - public function testErrors() + public function testShouldGetErrors() { /* |------------------------------------------------------------ From aa878766f53a580c7adeb7580ce5b45b075e09b6 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 18:09:05 -0200 Subject: [PATCH 027/115] Dropped the support of PHP 5.3. Since Laravel 4.2 doesn't support PHP 5.3 anymore. (Thank God) --- .travis.yml | 3 +-- composer.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b51d696..0a6ef3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php -php: - - 5.3 +php: - 5.4 before_script: diff --git a/composer.json b/composer.json index 1990c38..1063cde 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": ">=5.3.0", + "php": ">=5.4.0", "illuminate/support": "4.1.x" }, "require-dev": { From 9142812c797c88e9f22d635afa77c868d5cee4a6 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 18:20:05 -0200 Subject: [PATCH 028/115] Updated ConfideUser class in order to actually be a trait in order to be "merged" into developer classes instead of directly extended since Laravel 4.2 requires PHP 5.4. --- src/Zizaco/Confide/ConfideUser.php | 17 +---------------- tests/Zizaco/Confide/ConfideUserTest.php | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index b9ebcf1..acf8c47 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -2,7 +2,6 @@ use Zizaco\Confide\Facade as ConfideFacade; use Illuminate\Support\Facades\App as App; -use Illuminate\Database\Eloquent\Model as Eloquent; /** * Eloquent implementation of the ConfideUserInterface. @@ -10,21 +9,7 @@ * @license MIT * @package Zizaco\Confide */ -class ConfideUser extends Eloquent implements ConfideUserInterface { - - /** - * The database table used by the model. - * - * @var string - */ - protected $table = 'users'; - - /** - * The attributes excluded from the model's JSON form. - * - * @var array - */ - protected $hidden = array('password'); +trait ConfideUser { /** * A MessageBag object that store any error regarding diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 73c0f4e..6530eb9 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -4,6 +4,7 @@ use PHPUnit_Framework_TestCase; use Zizaco\Confide\Facade as ConfideFacade; use Illuminate\Support\Facades\App as App; +use Illuminate\Database\Eloquent\Model as Eloquent; class ConfideUserTest extends PHPUnit_Framework_TestCase { @@ -24,7 +25,7 @@ public function testShouldConfirm() | Set |------------------------------------------------------------ */ - $user = new ConfideUser; + $user = new _ConfideUserStub; $user->confirmation_code = '12345'; /* @@ -51,7 +52,7 @@ public function testShouldForgotPassword() | Set |------------------------------------------------------------ */ - $user = new ConfideUser; + $user = new _ConfideUserStub; $user->email = 'someone@somewhere.com'; /* @@ -78,7 +79,7 @@ public function testIsValid() | Set |------------------------------------------------------------ */ - $user = new ConfideUser; + $user = new _ConfideUserStub; $validator = m::mock('Zizaco\Confide\Validator'); /* @@ -109,7 +110,7 @@ public function testShouldGetAuthIdentifier() | Set |------------------------------------------------------------ */ - $user = m::mock('Zizaco\Confide\ConfideUser[getKey]'); + $user = m::mock('Zizaco\Confide\_ConfideUserStub[getKey]'); /* |------------------------------------------------------------ @@ -135,7 +136,7 @@ public function testShouldGetAuthPassword() | Set |------------------------------------------------------------ */ - $user = m::mock('Zizaco\Confide\ConfideUser[getKey]'); + $user = m::mock('Zizaco\Confide\_ConfideUserStub[getKey]'); $user->password = '1234'; /* @@ -153,7 +154,7 @@ public function testShouldGetErrors() | Set |------------------------------------------------------------ */ - $user = new ConfideUser; + $user = new _ConfideUserStub; $newMessageBag = m::mock('Illuminate\Support\MessageBag'); $existentMessageBag = m::mock('Illuminate\Support\MessageBag'); $user->errors = $existentMessageBag; @@ -177,3 +178,11 @@ public function testShouldGetErrors() $this->assertEquals($newMessageBag, $user->errors()); } } + +/** + * A stub class that implements ConfideUserInterface and uses + * the ConfideUser trait. + */ +class _ConfideUserStub extends Eloquent implements ConfideUserInterface{ + use ConfideUser; +} From 30b05732c5c7495d5ca824614ade44db182b4824 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 18:40:05 -0200 Subject: [PATCH 029/115] Updated ConfideUser DocBlocks since it is a trait from now on. --- src/Zizaco/Confide/ConfideUser.php | 4 +++- src/Zizaco/Confide/ConfideUserInterface.php | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index acf8c47..d893c82 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -4,8 +4,10 @@ use Illuminate\Support\Facades\App as App; /** - * Eloquent implementation of the ConfideUserInterface. + * This is a trait containing a initial implementation of the + * methods declared in the ConfideUserInterface. * + * @see \Zizaco\Confide\ConfideUserInterface * @license MIT * @package Zizaco\Confide */ diff --git a/src/Zizaco/Confide/ConfideUserInterface.php b/src/Zizaco/Confide/ConfideUserInterface.php index ecf81d3..a0b53fb 100644 --- a/src/Zizaco/Confide/ConfideUserInterface.php +++ b/src/Zizaco/Confide/ConfideUserInterface.php @@ -2,6 +2,17 @@ use Illuminate\Auth\UserInterface; +/** + * Interface that declares the methods that must be + * present in the User method that is going to be used + * with Confide. + * If you are looking for a implementation for this + * methods see ConfideUser trait. + * + * @see \Zizaco\Confide\ConfideUser + * @license MIT + * @package Zizaco\Confide + */ interface ConfideUserInterface extends UserInterface { /** From 80abb673ea11f7cfe7e8c65c589a3eb0df9b98cc Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 21:48:33 -0200 Subject: [PATCH 030/115] Deleted confide commands in order to rewrite then from the ground up. --- src/commands/ControllerCommand.php | 151 ---------------------- src/commands/MigrationCommand.php | 119 ----------------- src/commands/RoutesCommand.php | 158 ----------------------- tests/Zizaco/Confide/ConfideUserTest.php | 2 + 4 files changed, 2 insertions(+), 428 deletions(-) delete mode 100644 src/commands/ControllerCommand.php delete mode 100644 src/commands/MigrationCommand.php delete mode 100644 src/commands/RoutesCommand.php diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php deleted file mode 100644 index f244d88..0000000 --- a/src/commands/ControllerCommand.php +++ /dev/null @@ -1,151 +0,0 @@ -addNamespace('confide',substr(__DIR__,0,-8).'views'); - } - - /** - * Execute the console command. - * - * @return void - */ - public function fire() - { - $name = $this->prepareName($this->option('name')); - $restful = $this->option('restful'); - - $this->line(''); - $this->info( "Controller name: $name".(($restful) ? "\nRESTful: Yes" : '') ); - $message = "An authentication ".(($restful) ? 'RESTful ' : '')."controller template with the name $name.php". - " will be created in app/controllers directory and will NOT overwrite any ". - " file."; - - $this->comment( $message ); - $this->line(''); - - if ( $this->confirm("Proceed with the controller creation? [Yes|no]") ) - { - $this->line(''); - - $this->info( "Creating $name..." ); - if( $this->createController( $name, $restful ) ) - { - $this->info( "$name.php Successfully created!" ); - } - else{ - $this->error( - "Coudn't create app/controllers/$name.php.\nCheck the". - " write permissions within the controllers directory". - " or if $name.php already exists. (This command will". - " not overwrite any file. delete the existing $name.php". - " if you wish to continue)." - ); - } - - $this->line(''); - - } - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions() - { - $app = app(); - - return array( - array('name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', $app['config']->get('auth.model')), - array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'), - ); - } - - /** - * Prepare the controller name - * - * @param string $name - * @return string - */ - protected function prepareName($name = '') - { - $name = ( $name != '') ? ucfirst($name) : 'User'; - - if( substr($name,-10) == 'controller' ) - { - $name = substr($name, 0, -10).'Controller'; - } - else - { - $name .= 'Controller'; - } - - return $name; - } - - /** - * Create the controller - * - * @param string $name - * @return bool - */ - protected function createController( $name = '', $restful = false ) - { - $app = app(); - - $controller_file = $this->laravel->path."/controllers/$name.php"; - $output = $app['view']->make('confide::generators.controller') - ->with('name', $name) - ->with('restful', $restful) - ->render(); - - if( ! file_exists( $controller_file ) ) - { - $fs = fopen($controller_file, 'x'); - if ( $fs ) - { - fwrite($fs, $output); - fclose($fs); - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - -} diff --git a/src/commands/MigrationCommand.php b/src/commands/MigrationCommand.php deleted file mode 100644 index 20f027d..0000000 --- a/src/commands/MigrationCommand.php +++ /dev/null @@ -1,119 +0,0 @@ -addNamespace('confide',substr(__DIR__,0,-8).'views'); - } - - /** - * Execute the console command. - * - * @return void - */ - public function fire() - { - $table = lcfirst($this->option('table')); - - $this->line(''); - $this->info( "Table name: $table" ); - $message = "A migration that creates the $table table will". - " be created in app/database/migrations directory"; - - $this->comment( $message ); - $this->line(''); - - if ( $this->confirm("Proceed with the migration creation? [Yes|no]") ) - { - $this->line(''); - - $this->info( "Creating migration..." ); - if( $this->createMigration( $table ) ) - { - $this->info( "Migration successfully created!" ); - } - else{ - $this->error( - "Coudn't create migration.\n Check the write permissions". - " within the app/database/migrations directory." - ); - } - - $this->line(''); - - } - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions() - { - $app = app(); - - return array( - array('table', null, InputOption::VALUE_OPTIONAL, 'Table name.', $app['config']->get('auth.table')), - ); - } - - /** - * Create the migration - * - * @param string $name - * @return bool - */ - protected function createMigration( $table = 'users' ) - { - $app = app(); - $migration_file = $this->laravel->path."/database/migrations/".date('Y_m_d_His')."_confide_setup_users_table.php"; - $output = $app['view']->make('confide::generators.migration')->with('table', $table)->render(); - - if( ! file_exists( $migration_file ) ) - { - $fs = fopen($migration_file, 'x'); - if ( $fs ) - { - fwrite($fs, $output); - fclose($fs); - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - -} diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php deleted file mode 100644 index 68c2df3..0000000 --- a/src/commands/RoutesCommand.php +++ /dev/null @@ -1,158 +0,0 @@ -addNamespace('confide',substr(__DIR__,0,-8).'views'); - } - - /** - * Execute the console command. - * - * @return void - */ - public function fire() - { - $name = $this->prepareName($this->option('controller')); - $restful = $this->option('restful'); - - $this->line(''); - $this->info( "Routes file: app/routes.php" ); - - if(! $restful) - { - $message = "The default Confide routes (to use with the Controller template)". - " will be appended to your routes.php file."; - } - else - { - $message = "A single route to handle every action in a RESTful controller". - " will be appended to your routes.php file. This may be used with a confide". - " controller generated using [-r|--restful] option."; - } - - - $this->comment( $message ); - $this->line(''); - - if ( $this->confirm("Proceed with the append? [Yes|no]") ) - { - $this->line(''); - - $this->info( "Appending routes..." ); - if( $this->appendRoutes( $name, $restful ) ) - { - $this->info( "app/routes.php Patched successfully!" ); - } - else{ - $this->error( - "Coudn't append content to app/routes.php\nCheck the". - " write permissions within the file." - ); - } - - $this->line(''); - - } - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions() - { - $app = app(); - - return array( - array('controller', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', $app['config']->get('auth.model')), - array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'), - ); - } - - /** - * Prepare the controller name - * - * @param string $name - * @return string - */ - protected function prepareName( $name = '' ) - { - $name = ( $name != '') ? ucfirst($name) : 'User'; - - if( substr($name,-10) == 'controller' ) - { - $name = substr($name, 0, -10).'Controller'; - } - else - { - $name .= 'Controller'; - } - - return $name; - } - - /** - * Create the controller - * - * @param string $name - * @return bool - */ - protected function appendRoutes( $name = '', $restful = false ) - { - $app = app(); - $routes_file = $this->laravel->path.'/routes.php'; - $confide_routes = $app['view']->make('confide::generators.routes') - ->with('name', $name) - ->with('restful', $restful) - ->render(); - - if( file_exists( $routes_file ) ) - { - $fs = fopen($routes_file, 'a'); - if ( $fs ) - { - fwrite($fs, $confide_routes); - $this->line($confide_routes); - fclose($fs); - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - -} diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 6530eb9..1f0a369 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -182,6 +182,8 @@ public function testShouldGetErrors() /** * A stub class that implements ConfideUserInterface and uses * the ConfideUser trait. + * + * @see \Zizaco\Confide\ConfideUser */ class _ConfideUserStub extends Eloquent implements ConfideUserInterface{ use ConfideUser; From d520efe0fa442b7cf409d69c1edee6a0dfec2653 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 1 Feb 2014 22:24:20 -0200 Subject: [PATCH 031/115] Initial implementation of Confide's generate controller command. --- composer.json | 3 +- src/commands/ControllerCommand.php | 67 ++++++++++++++++++++++++ tests/commands/ControllerCommandTest.php | 60 +++++++++++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/commands/ControllerCommand.php create mode 100644 tests/commands/ControllerCommandTest.php diff --git a/composer.json b/composer.json index 1063cde..0c9af69 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "require-dev": { "mockery/mockery": "0.9.*@dev", "illuminate/database": "4.1.x", - "illuminate/auth": "4.1.x" + "illuminate/auth": "4.1.x", + "illuminate/console": "4.1.x" }, "suggest": { "zizaco/entrust":"add Role-based Permissions to Laravel 4" diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php new file mode 100644 index 0000000..569fd90 --- /dev/null +++ b/src/commands/ControllerCommand.php @@ -0,0 +1,67 @@ +app = $app ?: app(); + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return array( + array('name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', $this->app['config']->get('auth.model')), + array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'), + array('--repository', '-R', InputOption::VALUE_NONE, 'Generate a User Repository class.'), + ); + } + + /** + * Execute the console command. + * + * @return void + */ + public function fire() + { + + } +} diff --git a/tests/commands/ControllerCommandTest.php b/tests/commands/ControllerCommandTest.php new file mode 100644 index 0000000..be097ea --- /dev/null +++ b/tests/commands/ControllerCommandTest.php @@ -0,0 +1,60 @@ +$config]; + $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); + $options = [ + ['name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'User'], + ['--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'], + ['--repository', '-R', InputOption::VALUE_NONE, 'Generate a User Repository class.'], + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $config->shouldReceive('get') + ->once()->with('auth.model') + ->andReturn('User'); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($options, $command->getOptions()); + } +} From 2ae4fb909dbd5ca434394679bd9f38968edc0e66 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 2 Feb 2014 12:04:44 -0200 Subject: [PATCH 032/115] ControllerCommand now extends Support\GenerateCommand in order to abstract common file generation behavior to a parent class. --- .../Confide/Support/GenerateCommand.php | 15 ++++ src/commands/ControllerCommand.php | 42 ++++++++++- tests/commands/ControllerCommandTest.php | 72 ++++++++++++++++++- 3 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 src/Zizaco/Confide/Support/GenerateCommand.php diff --git a/src/Zizaco/Confide/Support/GenerateCommand.php b/src/Zizaco/Confide/Support/GenerateCommand.php new file mode 100644 index 0000000..0700fb0 --- /dev/null +++ b/src/Zizaco/Confide/Support/GenerateCommand.php @@ -0,0 +1,15 @@ +app['config']->get('auth.model')), + array('name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'Users'), array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'), array('--repository', '-R', InputOption::VALUE_NONE, 'Generate a User Repository class.'), ); @@ -62,6 +70,34 @@ protected function getOptions() */ public function fire() { + // Prepare variables + $class = $this->getClassName($this->option('name')); + $namespace = $this->getNamespace($this->option('name')); + $model = $this->app['config']->get('auth.model'); + $restful = $this->option('restful'); + $repository = $this->option('repository'); + $viewVars = compact( + 'class','namespace','model','restful','repository' + ); + + // Prompt + $this->line(''); + $this->info("Controller name: $class".(($restful) ? "\nRESTful: Yes" : '') ); + $this->comment("An authentication ".(($restful) ? 'RESTful ' : '')."controller template with the name ".($namespace ? $namespace.'\\' : '')."$class.php". + " will be created in app/controllers directory"); + $this->line(''); + + if ( $this->confirm("Proceed with the controller creation? [Yes|no]") ) + { + // Generate + $filename = 'controllers/'.($namespace ? $namespace.'/' : '').$class.'.php'; + $this->generateFile($filename, 'generators.controller', $viewVars); + + if ($repository) { + $filename = 'models/'.$model.'Repository.php'; + $this->generateFile($filename, 'generators.repository', $viewVars); + } + } } } diff --git a/tests/commands/ControllerCommandTest.php b/tests/commands/ControllerCommandTest.php index be097ea..9ab1c46 100644 --- a/tests/commands/ControllerCommandTest.php +++ b/tests/commands/ControllerCommandTest.php @@ -36,25 +36,93 @@ public function testSouldGetOptions() $app = ['config'=>$config]; $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); $options = [ - ['name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'User'], + ['name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'Users'], ['--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'], ['--repository', '-R', InputOption::VALUE_NONE, 'Generate a User Repository class.'], ]; + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($options, $command->getOptions()); + } + + public function testSouldFire() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $config = m::mock('Config'); + $app = ['config'=>$config]; + $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); + $viewVars = [ + 'class' => "UsersController", + 'namespace' => "", + 'model' => "User", + 'restful' => true, + 'repository' => true, + ]; + /* |------------------------------------------------------------ | Expectation |------------------------------------------------------------ */ + $command->shouldReceive('getClassName') + ->once()->with('Users') + ->andReturn('UsersController'); + + $command->shouldReceive('getNamespace') + ->once()->with('Users') + ->andReturn(''); + $config->shouldReceive('get') ->once()->with('auth.model') ->andReturn('User'); + $command->shouldReceive('option') + ->twice()->with('name') + ->andReturn('Users'); + + $command->shouldReceive('option') + ->once()->with('restful') + ->andReturn(true); + + $command->shouldReceive('option') + ->once()->with('repository') + ->andReturn(true); + + $command->shouldReceive('fire') + ->passthru(); + + $command->shouldReceive('line','info','comment','confirm') + ->andReturn(true); + + $command->shouldReceive('generateFile') + ->once()->with( + 'controllers/UsersController.php', + 'generators.controller', + $viewVars + ) + ->andReturn(true); + + $command->shouldReceive('generateFile') + ->once()->with( + 'models/UserRepository.php', + 'generators.repository', + $viewVars + ) + ->andReturn(true); + /* |------------------------------------------------------------ | Assertion |------------------------------------------------------------ */ - $this->assertEquals($options, $command->getOptions()); + $command->fire(); } } From a6be3652e8d99fb2cad79406f1e51f8152e22736 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 2 Feb 2014 12:43:24 -0200 Subject: [PATCH 033/115] Added getControllerName and getNamespace to ControllerCommand in order to find the correct name and place for the generated classes. --- src/commands/ControllerCommand.php | 48 ++++++++++++- tests/commands/ControllerCommandTest.php | 88 +++++++++++++++++++++++- 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index 2ad17a4..b7ccc10 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -71,7 +71,7 @@ protected function getOptions() public function fire() { // Prepare variables - $class = $this->getClassName($this->option('name')); + $class = $this->getControllerName($this->option('name')); $namespace = $this->getNamespace($this->option('name')); $model = $this->app['config']->get('auth.model'); $restful = $this->option('restful'); @@ -100,4 +100,50 @@ public function fire() } } } + + /** + * Returns the name of the controller class that will handle a + * resource with the given name. + * @param string $name Resource name + * @return string Controller class name + */ + protected function getControllerName($name) + { + if (strstr($name, '\\')) + { + $name = array_pop(explode('\\', $name)); + } + + $name = ( $name != '') ? ucfirst($name) : 'Users'; + + if( substr(strtolower($name),-10) == 'controller' ) + { + $name = substr($name, 0, -10).'Controller'; + } + else + { + $name .= 'Controller'; + } + + return $name; + } + + /** + * Returns the namespace of the given class name + * @param string $name Class name + * @return string Namespace + */ + protected function getNamespace($name) + { + if (strstr($name, '\\')) + { + $name = explode('\\', $name); + array_pop($name); + $name = implode('\\', $name); + } else { + $name = ''; + } + + return $name; + } } diff --git a/tests/commands/ControllerCommandTest.php b/tests/commands/ControllerCommandTest.php index 9ab1c46..8bbbb37 100644 --- a/tests/commands/ControllerCommandTest.php +++ b/tests/commands/ControllerCommandTest.php @@ -59,6 +59,7 @@ public function testSouldFire() $config = m::mock('Config'); $app = ['config'=>$config]; $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); + $command->shouldAllowMockingProtectedMethods(); $viewVars = [ 'class' => "UsersController", 'namespace' => "", @@ -72,7 +73,7 @@ public function testSouldFire() | Expectation |------------------------------------------------------------ */ - $command->shouldReceive('getClassName') + $command->shouldReceive('getControllerName') ->once()->with('Users') ->andReturn('UsersController'); @@ -125,4 +126,89 @@ public function testSouldFire() */ $command->fire(); } + + public function testSouldGetControlerName() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); + $command->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $command->shouldReceive('getControllerName') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + 'UsersController', + $command->getControllerName('Users') + ); + + $this->assertEquals( + 'UsersController', + $command->getControllerName('UsersController') + ); + + $this->assertEquals( + 'SomethingController', + $command->getControllerName('Some\Namespace\Something') + ); + + $this->assertEquals( + 'CamelCaseController', + $command->getControllerName('Some\Thing\CamelCase') + ); + } + + public function testSouldGetNamespace() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); + $command->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $command->shouldReceive('getNamespace') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + 'Some\Namespace', + $command->getNamespace('Some\Namespace\Something') + ); + + $this->assertEquals( + 'Some\Thing', + $command->getNamespace('Some\Thing\Resource') + ); + + $this->assertEquals( + '', + $command->getNamespace('Users') + ); + } } From 089c5871bea0f117c77c5d94b5f8577f3e45de26 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 2 Feb 2014 12:54:12 -0200 Subject: [PATCH 034/115] Fixed passed by reference problem in getControllerName. --- src/commands/ControllerCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index b7ccc10..94741f3 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -111,7 +111,8 @@ protected function getControllerName($name) { if (strstr($name, '\\')) { - $name = array_pop(explode('\\', $name)); + $name = explode('\\', $name); + $name = array_pop($name); } $name = ( $name != '') ? ucfirst($name) : 'Users'; From 641ca84d347597d4b7890df8f354c4b77d1d49de Mon Sep 17 00:00:00 2001 From: Zizaco Date: Mon, 3 Feb 2014 08:05:52 -0200 Subject: [PATCH 035/115] Added more verbosity to the ControllerCommand output. --- src/commands/ControllerCommand.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index 94741f3..8f6ea43 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -90,13 +90,16 @@ public function fire() if ( $this->confirm("Proceed with the controller creation? [Yes|no]") ) { + $this->info( "Creating $class..." ); // Generate $filename = 'controllers/'.($namespace ? $namespace.'/' : '').$class.'.php'; $this->generateFile($filename, 'generators.controller', $viewVars); + $this->info( "$class.php Successfully created!" ); if ($repository) { $filename = 'models/'.$model.'Repository.php'; $this->generateFile($filename, 'generators.repository', $viewVars); + $this->info( "$model.'Repository.php Successfully created!" ); } } } From e3d7c6aed1780ddb51a9ab3d834638634dffbd77 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:05:33 -0200 Subject: [PATCH 036/115] Added filter in phpunit.xml in order to only look for test coverage in the correct files. --- phpunit.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/phpunit.xml b/phpunit.xml index 8425e15..d1a5852 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -10,9 +10,15 @@ stopOnFailure="false" syntaxCheck="false" > + + + ./src/Zizaco + ./src/commands + + ./tests/ - \ No newline at end of file + From a73f0f4db829c4f10f5d4e14a0adda62ec25bddf Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:06:49 -0200 Subject: [PATCH 037/115] Added test coverage to the save method of the ConfideUser. --- src/Zizaco/Confide/ConfideUser.php | 2 +- tests/Zizaco/Confide/ConfideUserTest.php | 79 ++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index d893c82..3e5ab8f 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -72,7 +72,7 @@ public function isValid() public function save(array $options = array()) { if ($this->isValid()) { - parent::save(); + return parent::save($options); } else { return false; } diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 1f0a369..de10eda 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -103,6 +103,85 @@ public function testIsValid() $user->isValid(); } + public function testShouldValidateAndSave() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = m::mock('Zizaco\Confide\_ConfideUserStub[isValid,save,newQueryWithDeleted]'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $user->shouldReceive('save') + ->once() + ->passthru(); + + $user->shouldReceive('isValid') + ->once() + ->andReturn(true); + + // Throw an exception instead of actually saving the object + $user->shouldReceive('newQueryWithDeleted') + ->once() + ->andReturnUsing(function(){ + throw new \Exception('Saved in database'); + }); + + // Set the exception as expected ;) + $this->setExpectedException( + 'Exception', 'Saved in database' + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $user->save(); + } + + public function testShouldNotSaveInvalid() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = m::mock('Zizaco\Confide\_ConfideUserStub[isValid,save,newQueryWithDeleted]'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $user->shouldReceive('save') + ->once() + ->passthru(); + + $user->shouldReceive('isValid') + ->once() + ->andReturn(false); // If validation returns false + + // Throw an exception instead of actually saving the object + $user->shouldReceive('newQueryWithDeleted') + ->never() + ->andReturnUsing(function(){ + throw new \Exception('Saved in database'); + }); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertFalse($user->save()); + } + public function testShouldGetAuthIdentifier() { /* From 55fcd021cbebd1cc6100ad1f225f3ab95ce1125d Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:07:20 -0200 Subject: [PATCH 038/115] Added MigrationCommand in order to generate the default confide migration file. --- src/commands/MigrationCommand.php | 95 +++++++++++++++++++++++++ tests/commands/MigrationCommandTest.php | 94 ++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 src/commands/MigrationCommand.php create mode 100644 tests/commands/MigrationCommandTest.php diff --git a/src/commands/MigrationCommand.php b/src/commands/MigrationCommand.php new file mode 100644 index 0000000..3fe0663 --- /dev/null +++ b/src/commands/MigrationCommand.php @@ -0,0 +1,95 @@ +app = $app ?: app(); + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return array( + array('table', null, InputOption::VALUE_OPTIONAL, 'Table name.', 'users'), + ); + } + + /** + * Execute the console command. + * + * @return void + */ + public function fire() + { + // Prepare variables + $table = lcfirst($this->option('table')); + + $viewVars = compact( + 'table' + ); + + // Prompt + $this->line(''); + $this->info( "Table name: $table" ); + $this->comment("A migration that creates the $table table will". + " be created in app/database/migrations directory"); + $this->line(''); + + if ( $this->confirm("Proceed with the migration creation? [Yes|no]") ) + { + $this->info( "Creating migration..." ); + // Generate + $filename = 'database/migrations/'. + date('Y_m_d_His')."_confide_setup_$table.php"; + $this->generateFile($filename, 'generators.migration', $viewVars); + + $this->info( "Migration successfully created!" ); + } + } +} diff --git a/tests/commands/MigrationCommandTest.php b/tests/commands/MigrationCommandTest.php new file mode 100644 index 0000000..f392931 --- /dev/null +++ b/tests/commands/MigrationCommandTest.php @@ -0,0 +1,94 @@ +$config]; + $command = m::mock('Zizaco\Confide\MigrationCommand', [$app]); + $options = [ + ['table', null, InputOption::VALUE_OPTIONAL, 'Table name.', 'users'], + ]; + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($options, $command->getOptions()); + } + + public function testSouldFire() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $config = m::mock('Config'); + $app = ['config'=>$config]; + $command = m::mock('Zizaco\Confide\MigrationCommand', [$app]); + $command->shouldAllowMockingProtectedMethods(); + $viewVars = [ + 'table' => "users", + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $command->shouldReceive('option') + ->once()->with('table') + ->andReturn('users'); + + $command->shouldReceive('fire') + ->passthru(); + + $command->shouldReceive('line','info','comment','confirm') + ->andReturn(true); + + $command->shouldReceive('generateFile') + ->once()->with( + 'database/migrations/'.date('Y_m_d_His').'_confide_setup_users.php', + 'generators.migration', + $viewVars + ) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $command->fire(); + } +} From 4c04125e05febc14f8af536fd81948878e614445 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:35:28 -0200 Subject: [PATCH 039/115] Added RoutesCommand in order to be able to append the default controller routes to the route file. --- src/commands/RoutesCommand.php | 112 +++++++++++++++++++++++ tests/commands/RoutesCommandTest.php | 130 +++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 src/commands/RoutesCommand.php create mode 100644 tests/commands/RoutesCommandTest.php diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php new file mode 100644 index 0000000..0d51d69 --- /dev/null +++ b/src/commands/RoutesCommand.php @@ -0,0 +1,112 @@ +app = $app ?: app(); + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return array( + array('controller', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'UsersController'), + array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'), + ); + } + + /** + * Execute the console command. + * + * @return void + */ + public function fire() + { + // Prepare variables + $controllerName = $this->option('controller'); + $restful = $this->option('restful'); + + $viewVars = compact( + 'controllerName', + 'restful' + ); + + // Prompt + $this->line(''); + $this->info( "Routes file: app/routes.php" ); + + $message = $this->getFireMessage($restful); + + $this->comment($message); + $this->line(''); + + if ( $this->confirm("Proceed with the append? [Yes|no]") ) + { + $this->info( "Appending routes..." ); + // Generate + $filename = 'routes.php'; + $this->appendInFile($filename, 'generators.routes', $viewVars); + + $this->info("app/routes.php Patched successfully!"); + } + } + + protected function getFireMessage($restful = false) + { + if(! $restful) { + return "The default Confide routes (to use with the Controller template)". + " will be appended to your routes.php file."; + } else { + return "A single route to handle every action in a RESTful controller". + " will be appended to your routes.php file. This may be used with a confide". + " controller generated using [-r|--restful] option."; + } + } +} diff --git a/tests/commands/RoutesCommandTest.php b/tests/commands/RoutesCommandTest.php new file mode 100644 index 0000000..48bc876 --- /dev/null +++ b/tests/commands/RoutesCommandTest.php @@ -0,0 +1,130 @@ +assertEquals($options, $command->getOptions()); + } + + public function testSouldFire() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $command = m::mock('Zizaco\Confide\RoutesCommand', [$app]); + $command->shouldAllowMockingProtectedMethods(); + $viewVars = [ + 'controllerName' => 'UsersController', + 'restful' => true + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $command->shouldReceive('option') + ->once()->with('controller') + ->andReturn('UsersController'); + + $command->shouldReceive('option') + ->once()->with('restful') + ->andReturn(true); + + $command->shouldReceive('getFireMessage') + ->once() + ->andReturn("Some message about appending the routes..."); + + $command->shouldReceive('fire') + ->passthru(); + + $command->shouldReceive('line','info','comment','confirm') + ->andReturn(true); + + $command->shouldReceive('appendInFile') + ->once()->with( + 'routes.php', + 'generators.routes', + $viewVars + ) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $command->fire(); + } + + public function testShouldGetFireMessage() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $command = m::mock('Zizaco\Confide\RoutesCommand', [$app]); + $command->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $command->shouldReceive('getFireMessage') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue(is_string($command->getFireMessage(true))); + $this->assertTrue(is_string($command->getFireMessage(false))); + } +} From 5f16e0de9c8d0c79a4322b8ea8e2ec3c321f4626 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:35:57 -0200 Subject: [PATCH 040/115] Cleaned the MigrationCommandTest a little bit since the Config object was not being used. --- tests/commands/MigrationCommandTest.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/commands/MigrationCommandTest.php b/tests/commands/MigrationCommandTest.php index f392931..2e94635 100644 --- a/tests/commands/MigrationCommandTest.php +++ b/tests/commands/MigrationCommandTest.php @@ -31,8 +31,7 @@ public function testSouldGetOptions() | Set |------------------------------------------------------------ */ - $config = m::mock('Config'); - $app = ['config'=>$config]; + $app = []; $command = m::mock('Zizaco\Confide\MigrationCommand', [$app]); $options = [ ['table', null, InputOption::VALUE_OPTIONAL, 'Table name.', 'users'], @@ -53,8 +52,7 @@ public function testSouldFire() | Set |------------------------------------------------------------ */ - $config = m::mock('Config'); - $app = ['config'=>$config]; + $app = []; $command = m::mock('Zizaco\Confide\MigrationCommand', [$app]); $command->shouldAllowMockingProtectedMethods(); $viewVars = [ From ab427e81e05301330d1ed17b90724ab197480054 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:48:16 -0200 Subject: [PATCH 041/115] Improved how the PasswordService is tested. --- .../Confide/EloquentPasswordService.php | 28 +++++--- src/commands/RoutesCommand.php | 5 ++ .../Confide/EloquentPasswordServiceTest.php | 69 ++++++++++++++++++- 3 files changed, 93 insertions(+), 9 deletions(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index b5839fa..4f5e25b 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -69,14 +69,7 @@ public function getEmailByToken($token) ->select('email')->where('token','=',$token) ->first(); - if ($email && is_object($email)) - { - $email = $email->email; - } - elseif ($email && is_array($email)) - { - $email = $email['email']; - } + $email = $this->unwrapEmail($email); return $email; } @@ -90,4 +83,23 @@ protected function generateToken() { return md5(uniqid(mt_rand(), true)); } + + /** + * Extracts the email of the given object or array + * @param mixed $email An object, array or email string + * @return string The email address + */ + protected function unwrapEmail($email) + { + if ($email && is_object($email)) + { + $email = $email->email; + } + elseif ($email && is_array($email)) + { + $email = $email['email']; + } + + return $email; + } } diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php index 0d51d69..efd1f41 100644 --- a/src/commands/RoutesCommand.php +++ b/src/commands/RoutesCommand.php @@ -98,6 +98,11 @@ public function fire() } } + /** + * Returns a message that should explain what is about to be done. + * @param boolean $restful If the restful option is being used + * @return string The message + */ protected function getFireMessage($restful = false) { if(! $restful) { diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index 919a25f..bdf9d6a 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -102,7 +102,8 @@ public function testShouldGetEmailByToken() */ $userEmail = 'someone@somewhere.com'; $token = '123456789'; - $passService = new EloquentPasswordService; + $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); + $passService->shouldAllowMockingProtectedMethods(); $db = m::mock('connection'); $passService->app['db'] = $db; @@ -112,6 +113,13 @@ public function testShouldGetEmailByToken() | Expectation |------------------------------------------------------------ */ + $passService->shouldReceive('getEmailByToken') + ->passthru(); + + $passService->shouldReceive('unwrapEmail') + ->once()->with(['email'=>$userEmail]) + ->andReturn($userEmail); + // Mocks DB in order to check for the following query: // DB::table('password_reminders') // ->select('email') @@ -150,4 +158,63 @@ public function testShouldGetEmailByToken() $passService->getEmailByToken($token) ); } + + public function testShouldGenerateToken() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); + $passService->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $passService->shouldReceive('generateToken') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue(is_string($passService->generateToken())); + } + + public function testShouldUnwrapEmail() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); + $passService->shouldAllowMockingProtectedMethods(); + $email = 'someone@somewhere.com'; + $emailArray = ['email'=>$email]; + $emailObject = m::mock('UserWithEmail'); + + $emailObject->email = $email; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $passService->shouldReceive('unwrapEmail') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($email, $passService->unwrapEmail($email)); + $this->assertEquals($email, $passService->unwrapEmail($emailArray)); + $this->assertEquals($email, $passService->unwrapEmail($emailObject)); + } } From 768243377c0f68e76b7f6a3d50c5dd0441b32f3c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:52:32 -0200 Subject: [PATCH 042/115] Added test in order to cover the possibility of no model name being specified for the EloquentRepository. --- .../Zizaco/Confide/EloquentRepositoryTest.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index 793ff88..29060f5 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -50,6 +50,40 @@ public function testShouldGetModel() $this->assertEquals($user, $repo->model()); } + public function testShouldThrowExceptionIfCannotGetModel() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $repo = new EloquentRepository([]); + $repo->app['config'] = m::mock('Illuminate\Config\Repository'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + // Make sure to return the wanted value from config + $repo->app['config']->shouldReceive('get') + ->with('auth.model') + ->once() + ->andReturn(null); + + // Set the exception as expected ;) + $this->setExpectedException( + 'Exception', 'Wrong model specified in config/auth.php' + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $repo->model(); + } + public function testShouldGetUserByIdentity() { /* From f4054d7bde8093881b8fa6dabf00061223bf360a Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 22:55:33 -0200 Subject: [PATCH 043/115] Added an assertion for when trying to confirm an user with a wrong code. --- tests/Zizaco/Confide/EloquentRepositoryTest.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index 29060f5..8fbc98b 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -204,6 +204,7 @@ public function testShouldConfirmByCode() |------------------------------------------------------------ */ $confirmCode = 123123; + $wrongConfirmCode = 'IdontExist'; $user = m::mock('_mockedUser'); $repo = m::mock('Zizaco\Confide\EloquentRepository[getUserByIdentity,confirmUser]',[]); @@ -217,6 +218,11 @@ public function testShouldConfirmByCode() ->with(['confirmation_code' => $confirmCode]) ->andReturn($user); + // Return null if no user can be found + $repo->shouldReceive('getUserByIdentity') + ->with(['confirmation_code' => $wrongConfirmCode]) + ->andReturn(null); + // Should call the confirmUser method with the user // instance $repo->shouldReceive('confirmUser') @@ -229,6 +235,7 @@ public function testShouldConfirmByCode() | Assertion |------------------------------------------------------------ */ - $this->assertTrue($repo->confirmByCode($confirmCode)); + $this->assertTrue($repo->confirmByCode($confirmCode)); + $this->assertFalse($repo->confirmByCode($wrongConfirmCode)); } } From fa0ffc90f36a69d683b2474d9358e72b2e090916 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 23:05:38 -0200 Subject: [PATCH 044/115] Implementation and test coverage of ServiceProver::registerCommands method in order to make sure that the classes are being correctly registered in the IoC container. --- src/Zizaco/Confide/ServiceProvider.php | 19 ++++++++ tests/Zizaco/Confide/ServiceProviderTest.php | 51 ++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/Zizaco/Confide/ServiceProvider.php b/src/Zizaco/Confide/ServiceProvider.php index 3bf89eb..b2bbabf 100644 --- a/src/Zizaco/Confide/ServiceProvider.php +++ b/src/Zizaco/Confide/ServiceProvider.php @@ -111,6 +111,25 @@ protected function registerConfide() */ protected function registerCommands() { + $this->app->bind('command.confide.controller', function($app) + { + return new ControllerCommand($app); + }); + + $this->app->bind('command.confide.routes', function($app) + { + return new RoutesCommand($app); + }); + + $this->app->bind('command.confide.migration', function($app) + { + return new MigrationCommand($app); + }); + $this->commands( + 'command.confide.controller', + 'command.confide.routes', + 'command.confide.migration' + ); } } diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php index c266240..7065d7d 100644 --- a/tests/Zizaco/Confide/ServiceProviderTest.php +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -240,4 +240,55 @@ function($name, $closure) use ($test, $app) { */ $sp->registerConfide(); } + + public function testSHouldRegisterCommands() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $test = $this; + $app = m::mock('LaravelApp'); + $sp = m::mock('Zizaco\Confide\ServiceProvider', [$app]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app->shouldReceive('bind') + ->times(3)->andReturnUsing( + // Make sure that the commands are being registered + // with a closure that returns the correct + // object. + function($name, $closure) use ($test, $app) { + + $shouldBe = [ + 'command.confide.controller' => 'Zizaco\Confide\ControllerCommand', + 'command.confide.routes' => 'Zizaco\Confide\RoutesCommand', + 'command.confide.migration' => 'Zizaco\Confide\MigrationCommand', + ]; + + $test->assertInstanceOf( + $shouldBe[$name], + $closure($app) + ); + } + ); + + $sp->shouldReceive('commands') + ->with( + 'command.confide.controller', + 'command.confide.routes', + 'command.confide.migration' + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->registerCommands(); + } } From fa534c3fdcdefc078f96fa372c4cc42b8e69a66d Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 23:19:02 -0200 Subject: [PATCH 045/115] Refactored the commands in order to implement the constructor in the base abstract Support\GenerateCommand class. --- .../Confide/Support/GenerateCommand.php | 24 +++++++++++++++++++ src/commands/ControllerCommand.php | 21 ---------------- src/commands/MigrationCommand.php | 21 ---------------- src/commands/RoutesCommand.php | 21 ---------------- 4 files changed, 24 insertions(+), 63 deletions(-) diff --git a/src/Zizaco/Confide/Support/GenerateCommand.php b/src/Zizaco/Confide/Support/GenerateCommand.php index 0700fb0..1d0b007 100644 --- a/src/Zizaco/Confide/Support/GenerateCommand.php +++ b/src/Zizaco/Confide/Support/GenerateCommand.php @@ -11,5 +11,29 @@ */ abstract class GenerateCommand extends Command { + /** + * Laravel application + * + * @var \Illuminate\Foundation\Application + */ + public $app; + /** + * Create a new command instance. + * + * @param \Illuminate\Foundation\Application $app Laravel application object + * @return void + */ + public function __construct($app = null) + { + if (! is_array($app)) + parent::__construct(); + + $this->app = $app ?: app(); + } + + protected function generateFile($filename, $view, $viewVars) + { + + } } diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index 8f6ea43..c593500 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -14,13 +14,6 @@ */ class ControllerCommand extends GenerateCommand { - /** - * Laravel application - * - * @var \Illuminate\Foundation\Application - */ - public $app; - /** * The console command name. * @@ -35,20 +28,6 @@ class ControllerCommand extends GenerateCommand */ protected $description = 'Creates a controller template that uses Confide.'; - /** - * Create a new command instance. - * - * @param \Illuminate\Foundation\Application $app Laravel application object - * @return void - */ - public function __construct($app = null) - { - if (! is_array($app)) - parent::__construct(); - - $this->app = $app ?: app(); - } - /** * Get the console command options. * diff --git a/src/commands/MigrationCommand.php b/src/commands/MigrationCommand.php index 3fe0663..99723ee 100644 --- a/src/commands/MigrationCommand.php +++ b/src/commands/MigrationCommand.php @@ -13,13 +13,6 @@ */ class MigrationCommand extends GenerateCommand { - /** - * Laravel application - * - * @var \Illuminate\Foundation\Application - */ - public $app; - /** * The console command name. * @@ -34,20 +27,6 @@ class MigrationCommand extends GenerateCommand */ protected $description = 'Creates a migration following the Confide especifications.'; - /** - * Create a new command instance. - * - * @param \Illuminate\Foundation\Application $app Laravel application object - * @return void - */ - public function __construct($app = null) - { - if (! is_array($app)) - parent::__construct(); - - $this->app = $app ?: app(); - } - /** * Get the console command options. * diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php index efd1f41..73ed779 100644 --- a/src/commands/RoutesCommand.php +++ b/src/commands/RoutesCommand.php @@ -14,13 +14,6 @@ */ class RoutesCommand extends GenerateCommand { - /** - * Laravel application - * - * @var \Illuminate\Foundation\Application - */ - public $app; - /** * The console command name. * @@ -35,20 +28,6 @@ class RoutesCommand extends GenerateCommand */ protected $description = 'Append the default Confide controller routes to the routes.php'; - /** - * Create a new command instance. - * - * @param \Illuminate\Foundation\Application $app Laravel application object - * @return void - */ - public function __construct($app = null) - { - if (! is_array($app)) - parent::__construct(); - - $this->app = $app ?: app(); - } - /** * Get the console command options. * From 4edc08b6b1498279b9fabcb7c80016a2879832bf Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 12 Feb 2014 23:53:34 -0200 Subject: [PATCH 046/115] Added generateFile and appendInFile implementation in abstract class Zizaco\Confide\Support\GenerateCommand. --- .../Confide/Support/GenerateCommand.php | 62 ++++++++ .../Confide/Support/GenerateCommandTest.php | 140 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 tests/Zizaco/Confide/Support/GenerateCommandTest.php diff --git a/src/Zizaco/Confide/Support/GenerateCommand.php b/src/Zizaco/Confide/Support/GenerateCommand.php index 1d0b007..07a51e5 100644 --- a/src/Zizaco/Confide/Support/GenerateCommand.php +++ b/src/Zizaco/Confide/Support/GenerateCommand.php @@ -32,8 +32,70 @@ public function __construct($app = null) $this->app = $app ?: app(); } + /** + * Generates the given file with the rendered view + * @param string $filename Path to the file within the app directory + * @param string $view View file + * @param array $viewVars Variables that are going to be passed to the view + * @return bool Success + */ protected function generateFile($filename, $view, $viewVars) { + $output = $this->app['view']->make('confide::'.$view, $viewVars) + ->render(); + + $filename = $this->app['path'].'/'.trim($filename,'/'); + $directory = dirname($filename); + + $this->makeDir($directory, 0755, true); + $this->filePutContents($filename, $output); + + return true; + } + + /** + * Append the rendered view to the given file. Same as generateFile but + * the 'file_put_contents' is called with the FILE_APPEND flag. + * @param string $filename Path to the file within the app directory + * @param string $view View file + * @param array $viewVars Variables that are going to be passed to the view + * @return bool Success + */ + protected function appendInFile($filename, $view, $viewVars) + { + $output = $this->app['view']->make('confide::'.$view, $viewVars) + ->render(); + + $filename = $this->app['path'].'/'.trim($filename,'/'); + $directory = dirname($filename); + + $this->makeDir($directory, 0755, true); + $this->filePutContents($filename, $output, FILE_APPEND); + + return true; + } + + /** + * Encapsulates mkdir function + * @param string $directory + * @param int $mode + * @param bool $recursive + * @return void + */ + protected function makeDir($directory, $mode, $recursive) + { + @mkdir($directory, $mode, $recursive); + } + /** + * Encapsulates file_put_contents function + * @param string $filename + * @param string $data + * @param int $flags + * @return void + */ + protected function filePutContents($filename, $data, $flags = 0) + { + @file_put_contents($filename, $data, $flags); } } diff --git a/tests/Zizaco/Confide/Support/GenerateCommandTest.php b/tests/Zizaco/Confide/Support/GenerateCommandTest.php new file mode 100644 index 0000000..25aa6c8 --- /dev/null +++ b/tests/Zizaco/Confide/Support/GenerateCommandTest.php @@ -0,0 +1,140 @@ +$config, + 'view'=>$view, + 'path'=>'/where/the/app/is', + ]; + $command = m::mock('Zizaco\Confide\Support\_GenerateCommandStub', [$app]); + $command->shouldAllowMockingProtectedMethods(); + $filename = 'path/to/file.php'; + $viewName = 'generate.my_view'; + $viewVars = [ + 'someVar' => 'someValue' + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $view->shouldReceive('make') + ->once() + ->with('confide::'.$viewName, $viewVars) + ->andReturn($view); + + $view->shouldReceive('render') + ->once() + ->andReturn('The rendered content'); + + $command->shouldReceive('generateFile') + ->passthru(); + + $command->shouldReceive('makeDir') + ->with("/where/the/app/is/path/to", 493, true) + ->once() + ->passthru(); + + $command->shouldReceive('filePutContents') + ->with("/where/the/app/is/path/to/file.php", "The rendered content") + ->once() + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $command->generateFile($filename, $viewName, $viewVars); + } + + public function testShouldAppendInFile() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $config = m::mock('Config'); + $view = m::mock('View'); + $app = [ + 'config'=>$config, + 'view'=>$view, + 'path'=>'/where/the/app/is', + ]; + $command = m::mock('Zizaco\Confide\Support\_GenerateCommandStub', [$app]); + $command->shouldAllowMockingProtectedMethods(); + $filename = 'path/to/file.php'; + $viewName = 'generate.my_view'; + $viewVars = [ + 'someVar' => 'someValue' + ]; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $view->shouldReceive('make') + ->once() + ->with('confide::'.$viewName, $viewVars) + ->andReturn($view); + + $view->shouldReceive('render') + ->once() + ->andReturn('The rendered content'); + + $command->shouldReceive('appendInFile') + ->passthru(); + + $command->shouldReceive('makeDir') + ->with("/where/the/app/is/path/to", 493, true) + ->once() + ->passthru(); + + $command->shouldReceive('filePutContents') + ->with("/where/the/app/is/path/to/file.php", "The rendered content", 8) + ->once() + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $command->appendInFile($filename, $viewName, $viewVars); + } +} + +/** + * A stub class that extends GenerateCommand + * + * @see \Zizaco\Confide\Support\GenerateCommand + */ +class _GenerateCommandStub extends GenerateCommand {} From 0b0d742458ee13537b098dd860a42cb9718530da Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 13 Feb 2014 00:51:28 -0200 Subject: [PATCH 047/115] Tweaked MigrationCommand in order to match the file and the class name. --- src/commands/MigrationCommand.php | 2 +- tests/commands/MigrationCommandTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/MigrationCommand.php b/src/commands/MigrationCommand.php index 99723ee..da014a6 100644 --- a/src/commands/MigrationCommand.php +++ b/src/commands/MigrationCommand.php @@ -65,7 +65,7 @@ public function fire() $this->info( "Creating migration..." ); // Generate $filename = 'database/migrations/'. - date('Y_m_d_His')."_confide_setup_$table.php"; + date('Y_m_d_His')."_confide_setup_users_table.php"; $this->generateFile($filename, 'generators.migration', $viewVars); $this->info( "Migration successfully created!" ); diff --git a/tests/commands/MigrationCommandTest.php b/tests/commands/MigrationCommandTest.php index 2e94635..c343b1a 100644 --- a/tests/commands/MigrationCommandTest.php +++ b/tests/commands/MigrationCommandTest.php @@ -76,7 +76,7 @@ public function testSouldFire() $command->shouldReceive('generateFile') ->once()->with( - 'database/migrations/'.date('Y_m_d_His').'_confide_setup_users.php', + 'database/migrations/'.date('Y_m_d_His').'_confide_setup_users_table.php', 'generators.migration', $viewVars ) From 6bb0a836da94c9e283d72b1411d4f5ac9f89436e Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 13 Feb 2014 01:27:12 -0200 Subject: [PATCH 048/115] Tweaked ControllerCommand in order to actually create the namespace directories. --- src/commands/ControllerCommand.php | 2 +- tests/commands/ControllerCommandTest.php | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index c593500..e15c1e2 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -71,7 +71,7 @@ public function fire() { $this->info( "Creating $class..." ); // Generate - $filename = 'controllers/'.($namespace ? $namespace.'/' : '').$class.'.php'; + $filename = 'controllers/'.($namespace ? str_replace('\\', '/', $namespace).'/' : '').$class.'.php'; $this->generateFile($filename, 'generators.controller', $viewVars); $this->info( "$class.php Successfully created!" ); diff --git a/tests/commands/ControllerCommandTest.php b/tests/commands/ControllerCommandTest.php index 8bbbb37..288117c 100644 --- a/tests/commands/ControllerCommandTest.php +++ b/tests/commands/ControllerCommandTest.php @@ -62,7 +62,7 @@ public function testSouldFire() $command->shouldAllowMockingProtectedMethods(); $viewVars = [ 'class' => "UsersController", - 'namespace' => "", + 'namespace' => "The\\Namespace", 'model' => "User", 'restful' => true, 'repository' => true, @@ -74,12 +74,12 @@ public function testSouldFire() |------------------------------------------------------------ */ $command->shouldReceive('getControllerName') - ->once()->with('Users') + ->once()->with('The\\Namespace\\Users') ->andReturn('UsersController'); $command->shouldReceive('getNamespace') - ->once()->with('Users') - ->andReturn(''); + ->once()->with('The\\Namespace\\Users') + ->andReturn('The\\Namespace'); $config->shouldReceive('get') ->once()->with('auth.model') @@ -87,7 +87,7 @@ public function testSouldFire() $command->shouldReceive('option') ->twice()->with('name') - ->andReturn('Users'); + ->andReturn('The\\Namespace\\Users'); $command->shouldReceive('option') ->once()->with('restful') @@ -105,7 +105,7 @@ public function testSouldFire() $command->shouldReceive('generateFile') ->once()->with( - 'controllers/UsersController.php', + 'controllers/The/Namespace/UsersController.php', 'generators.controller', $viewVars ) From a3535ab1d0c4d7e84f79387d8b595ff1315e1b70 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 13 Feb 2014 01:37:41 -0200 Subject: [PATCH 049/115] Tweaked RoutesCommand in order to write an url that is relative to the controller name. --- src/commands/RoutesCommand.php | 5 +++++ tests/commands/RoutesCommandTest.php | 1 + 2 files changed, 6 insertions(+) diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php index 73ed779..557ff93 100644 --- a/src/commands/RoutesCommand.php +++ b/src/commands/RoutesCommand.php @@ -52,8 +52,13 @@ public function fire() $controllerName = $this->option('controller'); $restful = $this->option('restful'); + $url = explode('\\', $controllerName); + $url = array_pop($url); + $url = lcfirst(str_replace('Controller', '', $url)); + $viewVars = compact( 'controllerName', + 'url', 'restful' ); diff --git a/tests/commands/RoutesCommandTest.php b/tests/commands/RoutesCommandTest.php index 48bc876..2cbd759 100644 --- a/tests/commands/RoutesCommandTest.php +++ b/tests/commands/RoutesCommandTest.php @@ -58,6 +58,7 @@ public function testSouldFire() $command->shouldAllowMockingProtectedMethods(); $viewVars = [ 'controllerName' => 'UsersController', + 'url' => 'users', 'restful' => true ]; From cfdb4c9021f3561247d15a78695f260c5dec9ca3 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 13 Feb 2014 01:45:55 -0200 Subject: [PATCH 050/115] Initial implementation of the actual generator views. --- src/views/generators/controller.blade.php | 149 +++++------------- src/views/generators/routes.blade.php | 28 ++-- .../generators/user_repository.blade.php | 84 ++++++++++ 3 files changed, 140 insertions(+), 121 deletions(-) create mode 100644 src/views/generators/user_repository.blade.php diff --git a/src/views/generators/controller.blade.php b/src/views/generators/controller.blade.php index 8af8999..2bde909 100644 --- a/src/views/generators/controller.blade.php +++ b/src/views/generators/controller.blade.php @@ -1,20 +1,21 @@ -{{ 'username = Input::get( 'username' ); - ${{ lcfirst(Config::get('auth.model')) }}->email = Input::get( 'email' ); - ${{ lcfirst(Config::get('auth.model')) }}->password = Input::get( 'password' ); - - // The password confirmation will be removed from model - // before saving. This field will be used in Ardent's - // auto validation. - ${{ lcfirst(Config::get('auth.model')) }}->password_confirmation = Input::get( 'password_confirmation' ); - - // Save if valid. Password field will be hashed before save - ${{ lcfirst(Config::get('auth.model')) }}->save(); + $repo = App::make('UserRepository'); + $user = $repo->signup(Input::all()); - if ( ${{ lcfirst(Config::get('auth.model')) }}->id ) + if ($user->id) { - // Redirect with success message, You may replace "Lang::get(..." for your custom message. - @if (! $restful) - return Redirect::action('{{ $name }}@login') - @else - return Redirect::to('user/login') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->with( 'notice', Lang::get('confide::confide.alerts.account_created') ); } else { - // Get validation errors (see Ardent package) - $error = ${{ lcfirst(Config::get('auth.model')) }}->errors()->all(':message'); + $error = $user->errors()->all(':message'); - @if (! $restful) - return Redirect::action('{{ $name }}@create') - @else - return Redirect::to('user/create') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@create') ->withInput(Input::except('password')) ->with( 'error', $error ); } @@ -68,14 +48,12 @@ public function {{ (! $restful) ? 'store' : 'postIndex' }}() /** * Displays the login form - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'login' : 'getLogin' }}() { if( Confide::user() ) { - // If user is logged, redirect to internal - // page, change it to '/admin', '/dashboard' or something return Redirect::to('/'); } else @@ -86,39 +64,24 @@ public function {{ (! $restful) ? 'login' : 'getLogin' }}() /** * Attempt to do login - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'do_login' : 'postLogin' }}() { - $input = array( - 'email' => Input::get( 'email' ), // May be the username too - 'username' => Input::get( 'email' ), // so we have to pass both - 'password' => Input::get( 'password' ), - 'remember' => Input::get( 'remember' ), - ); + $repo = App::make('UserRepository'); + $input = Input::all(); - // If you wish to only allow login from confirmed users, call logAttempt - // with the second parameter as true. - // logAttempt will check if the 'email' perhaps is the username. - // Get the value from the config file instead of changing the controller - if ( Confide::logAttempt( $input, Config::get('confide::signup_confirm') ) ) + if ($repo->login($input)) { - // Redirect the user to the URL they were trying to access before - // caught by the authentication filter IE Redirect::guest('user/login'). - // Otherwise fallback to '/' - // Fix pull #145 - return Redirect::intended('/'); // change it to '/admin', '/dashboard' or something + return Redirect::intended('/'); } else { - ${{ lcfirst(Config::get('auth.model')) }} = new {{ Config::get('auth.model') }}; - - // Check if there was too many login attempts - if( Confide::isThrottled( $input ) ) + if ($repo->isThrottled($input)) { $err_msg = Lang::get('confide::confide.alerts.too_many_attempts'); } - elseif( ${{ lcfirst(Config::get('auth.model')) }}->checkUserExists( $input ) and ! ${{ lcfirst(Config::get('auth.model')) }}->isConfirmed( $input ) ) + elseif ($repo->existsButNotConfirmed($input)) { $err_msg = Lang::get('confide::confide.alerts.not_confirmed'); } @@ -127,11 +90,7 @@ public function {{ (! $restful) ? 'do_login' : 'postLogin' }}() $err_msg = Lang::get('confide::confide.alerts.wrong_credentials'); } - @if (! $restful) - return Redirect::action('{{ $name }}@login') - @else - return Redirect::to('user/login') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->withInput(Input::except('password')) ->with( 'error', $err_msg ); } @@ -139,36 +98,28 @@ public function {{ (! $restful) ? 'do_login' : 'postLogin' }}() /** * Attempt to confirm account with code - * * @param string $code + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'confirm' : 'getConfirm' }}( $code ) { if ( Confide::confirm( $code ) ) { $notice_msg = Lang::get('confide::confide.alerts.confirmation'); - @if (! $restful) - return Redirect::action('{{ $name }}@login') - @else - return Redirect::to('user/login') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->with( 'notice', $notice_msg ); } else { $error_msg = Lang::get('confide::confide.alerts.wrong_confirmation'); - @if (! $restful) - return Redirect::action('{{ $name }}@login') - @else - return Redirect::to('user/login') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->with( 'error', $error_msg ); } } /** * Displays the forgot password form - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'forgot_password' : 'getForgot' }}() { @@ -177,28 +128,20 @@ public function {{ (! $restful) ? 'forgot_password' : 'getForgot' }}() /** * Attempt to send change password link to the given email - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'do_forgot_password' : 'postForgot' }}() { if( Confide::forgotPassword( Input::get( 'email' ) ) ) { $notice_msg = Lang::get('confide::confide.alerts.password_forgot'); - @if (! $restful) - return Redirect::action('{{ $name }}@login') - @else - return Redirect::to('user/login') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->with( 'notice', $notice_msg ); } else { $error_msg = Lang::get('confide::confide.alerts.wrong_password_forgot'); - @if (! $restful) - return Redirect::action('{{ $name }}@forgot_password') - @else - return Redirect::to('user/forgot') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@forgot_password') ->withInput() ->with( 'error', $error_msg ); } @@ -206,7 +149,7 @@ public function {{ (! $restful) ? 'do_forgot_password' : 'postForgot' }}() /** * Shows the change password form with the given token - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'reset_password' : 'getReset' }}( $token ) { @@ -216,7 +159,7 @@ public function {{ (! $restful) ? 'reset_password' : 'getReset' }}( $token ) /** * Attempt change password of the user - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'do_reset_password' : 'postReset' }}() { @@ -230,21 +173,13 @@ public function {{ (! $restful) ? 'do_reset_password' : 'postReset' }}() if( Confide::resetPassword( $input ) ) { $notice_msg = Lang::get('confide::confide.alerts.password_reset'); - @if (! $restful) - return Redirect::action('{{ $name }}@login') - @else - return Redirect::to('user/login') - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->with( 'notice', $notice_msg ); } else { $error_msg = Lang::get('confide::confide.alerts.wrong_password_reset'); - @if (! $restful) - return Redirect::action('{{ $name }}@reset_password', array('token'=>$input['token'])) - @else - return Redirect::to('user/reset/'.$input['token']) - @endif + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@reset_password', array('token'=>$input['token'])) ->withInput() ->with( 'error', $error_msg ); } @@ -252,12 +187,12 @@ public function {{ (! $restful) ? 'do_reset_password' : 'postReset' }}() /** * Log the user out of the application. - * + * @return Illuminate\Http\Response */ public function {{ (! $restful) ? 'logout' : 'getLogout' }}() { Confide::logout(); - + return Redirect::to('/'); } diff --git a/src/views/generators/routes.blade.php b/src/views/generators/routes.blade.php index 7d76b3d..4a0a43c 100644 --- a/src/views/generators/routes.blade.php +++ b/src/views/generators/routes.blade.php @@ -1,21 +1,21 @@ -{{ "\n\n" }} +{{ "\n\n\n\n" }} @if (! $restful) // Confide routes -Route::get( '{{ lcfirst(substr($name,0,-10)) }}/create', '{{ $name }}@create'); -Route::post('{{ lcfirst(substr($name,0,-10)) }}', '{{ $name }}@store'); -Route::get( '{{ lcfirst(substr($name,0,-10)) }}/login', '{{ $name }}@login'); -Route::post('{{ lcfirst(substr($name,0,-10)) }}/login', '{{ $name }}@do_login'); -Route::get( '{{ lcfirst(substr($name,0,-10)) }}/confirm/{code}', '{{ $name }}@confirm'); -Route::get( '{{ lcfirst(substr($name,0,-10)) }}/forgot_password', '{{ $name }}@forgot_password'); -Route::post('{{ lcfirst(substr($name,0,-10)) }}/forgot_password', '{{ $name }}@do_forgot_password'); -Route::get( '{{ lcfirst(substr($name,0,-10)) }}/reset_password/{token}', '{{ $name }}@reset_password'); -Route::post('{{ lcfirst(substr($name,0,-10)) }}/reset_password', '{{ $name }}@do_reset_password'); -Route::get( '{{ lcfirst(substr($name,0,-10)) }}/logout', '{{ $name }}@logout'); +Route::get( '{{ $url }}/create', '{{ $controllerName }}@create'); +Route::post('{{ $url }}', '{{ $controllerName }}@store'); +Route::get( '{{ $url }}/login', '{{ $controllerName }}@login'); +Route::post('{{ $url }}/login', '{{ $controllerName }}@do_login'); +Route::get( '{{ $url }}/confirm/{code}', '{{ $controllerName }}@confirm'); +Route::get( '{{ $url }}/forgot_password', '{{ $controllerName }}@forgot_password'); +Route::post('{{ $url }}/forgot_password', '{{ $controllerName }}@do_forgot_password'); +Route::get( '{{ $url }}/reset_password/{token}', '{{ $controllerName }}@reset_password'); +Route::post('{{ $url }}/reset_password', '{{ $controllerName }}@do_reset_password'); +Route::get( '{{ $url }}/logout', '{{ $controllerName }}@logout'); @else // Confide RESTful route -Route::get('user/confirm/{code}', '{{ $name }}@getConfirm'); -Route::get('user/reset/{token}', '{{ $name }}@getReset'); -Route::controller( 'user', '{{ $name }}'); +Route::get('{{ $url }}/confirm/{code}', '{{ $controllerName }}@getConfirm'); +Route::get('{{ $url }}/reset/{token}', '{{ $controllerName }}@getReset'); +Route::controller( '{{ $url }}', '{{ $controllerName }}'); @endif diff --git a/src/views/generators/user_repository.blade.php b/src/views/generators/user_repository.blade.php new file mode 100644 index 0000000..5755b22 --- /dev/null +++ b/src/views/generators/user_repository.blade.php @@ -0,0 +1,84 @@ +{{ 'username = array_get($input, 'username'); + $user->email = array_get($input, 'email'); + $user->password = array_get($input, 'password'); + + // The password confirmation will be removed from model + // before saving. This field will be used in Ardent's + // auto validation. + $user->password_confirmation = array_get($input, 'password_confirmation' ); + + // Save if valid. Password field will be hashed before save + $this->save($user); + + return $user; + } + + /** + * Attempts to login with the given credentials. + * @param array $input Array containing the credentials (email/username and password) + * @return boolean Success? + */ + public function login($input) + { + if(! isset($input['password'])) + $input['password'] = null; + + $identityColumns = ['email', 'username']; + + return Confide::logAttempt($input, Config::get('confide::signup_confirm'), $identityColumns); + } + + /** + * Checks if the credentials has been throttled by too + * much failed login attempts + * + * @param array $credentials Array containing the credentials (email/username and password) + * @return boolean Is throttled + */ + public function isThrottled($input) + { + return Confide::isThrottled($input); + } + + /** + * Checks if the given credentials correponds to a user that exists but + * is not confirmed + * @param array $credentials Array containing the credentials (email/username and password) + * @return boolean Exists and is not confirmed? + */ + public function existsButNotConfirmed($input) + { + $user = App::make('{{ $model }}'); + + return $user->checkUserExists($input) and !$user->isConfirmed($input); + } + + /** + * Simply saves the given instance + * @param {{ $model }} $instance + * @return boolean Success + */ + public function save({{ $model }} $instance) + { + return $instance->save(); + } +} From 39b87a31af5056e2c68c3c9c4042692a0802f876 Mon Sep 17 00:00:00 2001 From: Skyler Lewis Date: Sun, 23 Feb 2014 18:43:45 -0700 Subject: [PATCH 051/115] Update 2013_01_13_172956_confide_setup_users_table.php --- .../2013_01_13_172956_confide_setup_users_table.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/migrations/2013_01_13_172956_confide_setup_users_table.php b/src/migrations/2013_01_13_172956_confide_setup_users_table.php index 34123a4..bb2c62b 100644 --- a/src/migrations/2013_01_13_172956_confide_setup_users_table.php +++ b/src/migrations/2013_01_13_172956_confide_setup_users_table.php @@ -15,8 +15,8 @@ public function up() Schema::create('users', function($table) { $table->increments('id'); - $table->string('username'); - $table->string('email'); + $table->string('username')->unique(); + $table->string('email')->unique(); $table->string('password'); $table->string('confirmation_code'); $table->boolean('confirmed')->default(false); From ba0c1900b89b9d17abc7844fb9422af3933641e0 Mon Sep 17 00:00:00 2001 From: Skyler Lewis Date: Sun, 23 Feb 2014 18:44:19 -0700 Subject: [PATCH 052/115] Update migration.blade.php --- src/views/generators/migration.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/generators/migration.blade.php b/src/views/generators/migration.blade.php index cb28544..61f1790 100644 --- a/src/views/generators/migration.blade.php +++ b/src/views/generators/migration.blade.php @@ -15,8 +15,8 @@ public function up() Schema::create('{{ $table }}', function($table) { $table->increments('id'); - $table->string('username'); - $table->string('email'); + $table->string('username')->unique(); + $table->string('email')->unique(); $table->string('password'); $table->string('confirmation_code'); $table->boolean('confirmed')->default(false); From cf5d3f84149dda4a2402df6081cbb08884fbff57 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 05:26:51 -0300 Subject: [PATCH 053/115] Renamed generators.user_repository view to simply repository --- .../{user_repository.blade.php => repository.blade.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/views/generators/{user_repository.blade.php => repository.blade.php} (100%) diff --git a/src/views/generators/user_repository.blade.php b/src/views/generators/repository.blade.php similarity index 100% rename from src/views/generators/user_repository.blade.php rename to src/views/generators/repository.blade.php From 0e0dfba3fad8a100e7ceea666819d37894261e0b Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 05:28:37 -0300 Subject: [PATCH 054/115] Temporary fix for action urls in default confide views --- src/views/forgot_password.blade.php | 2 +- src/views/login.blade.php | 2 +- src/views/reset_password.blade.php | 2 +- src/views/signup.blade.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/forgot_password.blade.php b/src/views/forgot_password.blade.php index 06d20f6..4b75357 100644 --- a/src/views/forgot_password.blade.php +++ b/src/views/forgot_password.blade.php @@ -1,4 +1,4 @@ -
+
diff --git a/src/views/login.blade.php b/src/views/login.blade.php index 4d989b7..468a0fc 100644 --- a/src/views/login.blade.php +++ b/src/views/login.blade.php @@ -1,4 +1,4 @@ - +
diff --git a/src/views/reset_password.blade.php b/src/views/reset_password.blade.php index 7198159..587cf87 100644 --- a/src/views/reset_password.blade.php +++ b/src/views/reset_password.blade.php @@ -1,4 +1,4 @@ - + diff --git a/src/views/signup.blade.php b/src/views/signup.blade.php index afe024c..c273184 100644 --- a/src/views/signup.blade.php +++ b/src/views/signup.blade.php @@ -1,4 +1,4 @@ - +
From c5bb39ae23d961b0e03695a93040785fab3e4081 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 05:31:12 -0300 Subject: [PATCH 055/115] Added new UserInterface methods (that were introduced in Laravel 4.1.26) to ConfideUser --- src/Zizaco/Confide/ConfideUser.php | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index 3e5ab8f..c70f6f1 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -114,4 +114,38 @@ public function getAuthPassword() { return $this->password; } + + /** + * Get the token value for the "remember me" session. + * + * @see \Illuminate\Auth\UserInterface + * @return string + */ + public function getRememberToken() + { + return $this->remember_token; + } + + /** + * Set the token value for the "remember me" session. + * + * @see \Illuminate\Auth\UserInterface + * @param string $value + * @return void + */ + public function setRememberToken($value) + { + $this->remember_token = $value; + } + + /** + * Get the column name for the "remember me" token. + * + * @see \Illuminate\Auth\UserInterface + * @return string + */ + public function getRememberTokenName() + { + return 'remember_token'; + } } From 4d479423818e60c78a3e3d43f795ae4e646480eb Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 05:56:15 -0300 Subject: [PATCH 056/115] Added initial implementation of UserValidator --- src/Zizaco/Confide/UserValidator.php | 38 +++++++++++++++++++ src/Zizaco/Confide/UserValidatorInterface.php | 21 ++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/Zizaco/Confide/UserValidator.php create mode 100644 src/Zizaco/Confide/UserValidatorInterface.php diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php new file mode 100644 index 0000000..7bdbedc --- /dev/null +++ b/src/Zizaco/Confide/UserValidator.php @@ -0,0 +1,38 @@ + Date: Wed, 16 Apr 2014 05:58:03 -0300 Subject: [PATCH 057/115] Updated ConfideUser in order to use UserValidator inside the isValid method --- src/Zizaco/Confide/ConfideUser.php | 4 ++-- tests/Zizaco/Confide/ConfideUserTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index c70f6f1..4b0fc6f 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -54,10 +54,10 @@ public function forgotPassword() */ public function isValid() { - // Instantiate the ConfideUserValidator and calls the + // Instantiate the Zizaco\Confide\UserValidator and calls the // validate method. Feel free to use your own validation // class. - $validator = App::make('ConfideUserValidator'); + $validator = App::make('confide.user_validator'); $validator->validate($this); } diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index de10eda..c5e096b 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -88,7 +88,7 @@ public function testIsValid() |------------------------------------------------------------ */ App::shouldReceive('make') - ->once()->with('ConfideUserValidator') + ->once()->with('confide.user_validator') ->andReturn($validator); $validator->shouldReceive('validate') From 56c0a98bca56d2a4bf0676088cc5d0edcc1098dc Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 05:58:28 -0300 Subject: [PATCH 058/115] Updated Confide\ServiceProvider in order to register the default UserValidator properly --- src/Zizaco/Confide/ServiceProvider.php | 16 +++++++ tests/Zizaco/Confide/ServiceProviderTest.php | 44 +++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/Zizaco/Confide/ServiceProvider.php b/src/Zizaco/Confide/ServiceProvider.php index b2bbabf..6612413 100644 --- a/src/Zizaco/Confide/ServiceProvider.php +++ b/src/Zizaco/Confide/ServiceProvider.php @@ -38,6 +38,8 @@ public function register() $this->registerLoginThrottleService(); + $this->registerUserValidator(); + $this->registerConfide(); $this->registerCommands(); @@ -86,6 +88,20 @@ protected function registerLoginThrottleService() }); } + /** + * Register the UserValidator class. The default class that + * used for user validation + * + * @return void + */ + protected function registerUserValidator() + { + $this->app->bind('confide.user_validator', function($app) + { + return new UserValidator(); + }); + } + /** * Register the application bindings. * diff --git a/tests/Zizaco/Confide/ServiceProviderTest.php b/tests/Zizaco/Confide/ServiceProviderTest.php index 7065d7d..2e73eb9 100644 --- a/tests/Zizaco/Confide/ServiceProviderTest.php +++ b/tests/Zizaco/Confide/ServiceProviderTest.php @@ -52,7 +52,8 @@ public function testShouldRegister() 'Zizaco\Confide\ServiceProvider'. '[registerRepository,registerPasswordService,'. 'registerConfide,registerCommands,'. - 'registerLoginThrottleService]', + 'registerLoginThrottleService,'. + 'registerUserValidator]', ['something'] ); $sp->shouldAllowMockingProtectedMethods(); @@ -65,7 +66,8 @@ public function testShouldRegister() $sp->shouldReceive( 'registerRepository','registerConfide', 'registerCommands','registerPasswordService', - 'registerLoginThrottleService' + 'registerLoginThrottleService', + 'registerUserValidator' ) ->once(); @@ -191,6 +193,44 @@ function($name, $closure) use ($test, $app) { $sp->registerLoginThrottleService(); } + public function testShouldRegisterUserValidator() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $test = $this; + $app = m::mock('LaravelApp'); + $sp = m::mock('Zizaco\Confide\ServiceProvider', [$app]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $app->shouldReceive('bind') + ->once()->andReturnUsing( + // Make sure that the name is 'confide.user_validator' + // and that the closure passed returns the correct + // kind of object. + function($name, $closure) use ($test, $app) { + $test->assertEquals('confide.user_validator', $name); + $test->assertInstanceOf( + 'Zizaco\Confide\UserValidator', + $closure($app) + ); + } + ); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $sp->registerUserValidator(); + } + public function testShouldRegisterConfide() { /* From 1a5f86e060ca620d7d42e1589b446600bfa43aac Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 06:04:41 -0300 Subject: [PATCH 059/115] Updated ConfideUser in order to fix isValid method. isValid should return the validate result --- src/Zizaco/Confide/ConfideUser.php | 2 +- tests/Zizaco/Confide/ConfideUserTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index 4b0fc6f..05919ec 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -59,7 +59,7 @@ public function isValid() // class. $validator = App::make('confide.user_validator'); - $validator->validate($this); + return $validator->validate($this); } /** diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index c5e096b..6610771 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -100,7 +100,7 @@ public function testIsValid() | Assertion |------------------------------------------------------------ */ - $user->isValid(); + $this->assertTrue($user->isValid()); } public function testShouldValidateAndSave() From 81f19637b346cc5cb37821ec73527d4a0234dc2f Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 06:08:19 -0300 Subject: [PATCH 060/115] Tweaked UserValidator in order clean password_confirmation attribute --- src/Zizaco/Confide/UserValidator.php | 2 ++ src/views/login.blade.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 7bdbedc..3fed492 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -32,6 +32,8 @@ class UserValidator implements UserValidatorInterface { */ public function validate(ConfideUserInterface $user) { + unset($user->password_confirmation); + return true; } diff --git a/src/views/login.blade.php b/src/views/login.blade.php index 468a0fc..78d9a5e 100644 --- a/src/views/login.blade.php +++ b/src/views/login.blade.php @@ -9,7 +9,7 @@ From be14061e54ceef75770cab027ac7bc177a03a7b1 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 06:35:40 -0300 Subject: [PATCH 061/115] Fixed login attempt with uppercase usernames and tweaked throttling delay --- src/Zizaco/Confide/Confide.php | 2 +- src/Zizaco/Confide/EloquentRepository.php | 2 +- tests/Zizaco/Confide/EloquentRepositoryTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index e1d96f4..647a35e 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -179,7 +179,7 @@ protected function loginThrottling($identity) // Throttling delay! // See: http://www.codinghorror.com/blog/2009/01/dictionary-attacks-101.html if($count > 2) - sleep(($count-1) * 400000); + usleep(($count-1) * 400000); return true; } diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index 0525c76..886fb37 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -103,7 +103,7 @@ public function getUserByEmailOrUsername($emailOrUsername) { $identity = [ 'email' => $emailOrUsername, - 'username' => $emailOrUsername + 'username' => strtolower($emailOrUsername) ]; return $this->getUserByIdentity($identity); diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index 8fbc98b..71b8991 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -184,7 +184,7 @@ public function testShouldGetUserByEmailOrUsername() */ // Repo model method should return the model instance $repo->shouldReceive('getUserByIdentity') - ->with(['email'=>$username, 'username'=>$username]) + ->with(['email'=>$username, 'username'=>strtolower($username)]) ->andReturn($user); /* From 367972519cfe67717a022c721e0b67f3c6e19e3c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Apr 2014 06:38:05 -0300 Subject: [PATCH 062/115] Fixed UserValidator password hashing with temporary implementation. Still need a real implementation --- src/Zizaco/Confide/UserValidator.php | 1 + tests/Zizaco/Confide/UserValidatorTest.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/Zizaco/Confide/UserValidatorTest.php diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 3fed492..74b84d9 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -33,6 +33,7 @@ class UserValidator implements UserValidatorInterface { public function validate(ConfideUserInterface $user) { unset($user->password_confirmation); + $user->password = \Hash::make($user->password); return true; } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php new file mode 100644 index 0000000..1bf41ed --- /dev/null +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -0,0 +1,17 @@ + Date: Fri, 18 Apr 2014 21:14:48 -0300 Subject: [PATCH 063/115] Added actual implementation of UserValidator::validatePassword method in order to to allow password creation and password update --- src/Zizaco/Confide/UserValidator.php | 64 ++++++++++++- tests/Zizaco/Confide/UserValidatorTest.php | 106 +++++++++++++++++++++ 2 files changed, 167 insertions(+), 3 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 74b84d9..13c5fa4 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -1,5 +1,7 @@ [ + 'username' => 'required|alpha_dash', + 'email' => 'required|email', + 'password' => 'required|min:4', + ], + 'update' => [ + 'username' => 'required|alpha_dash', + 'email' => 'required|email', + 'password' => 'required|min:4', + ] + ]; + /** * Validates the given user. Should check if all the fields are correctly * @param ConfideUserInterface $user Instance to be tested * @return boolean True if the $user is valid */ - public function validate(ConfideUserInterface $user) + public function validate(ConfideUserInterface $user, $ruleset = 'create') { - unset($user->password_confirmation); - $user->password = \Hash::make($user->password); + // Set the $repo as a ConfideRepository object + $this->repo = App::make('confide.repository'); + + // Validate object + $result = $this->validatePassword($user) && + $this->isUnique($user) && + $this->validateFields($user); + + return $result; + } + + /** + * Validates the password and password_confirmation of the given + * user + * @param ConfideUserInterface $user + * @return boolean True if password is valid + */ + public function validatePassword(ConfideUserInterface $user) + { + $hash = App::make('hash'); + + if($user->getOriginal('password') != $user->password) { + if ($user->password == $user->password_confirmation) { + + // Hashes password and unset password_confirmation field + $user->password = $hash->make($user->password); + unset($user->password_confirmation); + + return true; + } else { + return false; + } + } return true; } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 1bf41ed..7d8e7d2 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -2,6 +2,7 @@ use Mockery as m; use PHPUnit_Framework_TestCase; +use Illuminate\Support\Facades\App as App; class UserValidatorTest extends PHPUnit_Framework_TestCase { @@ -14,4 +15,109 @@ public function tearDown() { m::close(); } + + public function testShouldValidate() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $repo = m::mock('Zizaco\Confide\EloquentRepository'); + + App::shouldReceive('make') + ->with('confide.repository') + ->andReturn($repo); + + $validator = m::mock( + 'Zizaco\Confide\UserValidator'. + '[validatePassword,isUnique,validateFields]' + ); + $validator->shouldAllowMockingProtectedMethods(); + + $user = m::mock('Zizaco\Confide\ConfideUserInterface'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $validator->shouldReceive('validatePassword') + ->once()->andReturn(true); + + $validator->shouldReceive('isUnique') + ->once()->andReturn(true); + + $validator->shouldReceive('validateFields') + ->once()->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($validator->validate($user)); + } + + public function testShouldValidatePassword() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $repo = m::mock('Zizaco\Confide\EloquentRepository'); + $hash = m::mock('Hash'); + + App::shouldReceive('make') + ->with('confide.repository') + ->andReturn($repo); + + App::shouldReceive('make') + ->with('hash') + ->andReturn($hash); + + $validator = new UserValidator; + + $userA = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userA->password = 'foo123'; + $userA->password_confirmation = 'foo123'; + + $userB = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userB->password = 'foo123'; + $userB->password_confirmation = 'foo456'; + + $userC = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userC->password = '$2y$10$8PqTle4VGODMbjFbpIe.vOISth8qAaXlO7CAi4HNneqe37Jy1gGRO'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $userA->shouldReceive('getOriginal') + ->once()->with('password') + ->andReturn(''); + + $userB->shouldReceive('getOriginal') + ->once()->with('password') + ->andReturn('old_pass'); + + $userC->shouldReceive('getOriginal') + ->once()->with('password') + ->andReturn('$2y$10$8PqTle4VGODMbjFbpIe.vOISth8qAaXlO7CAi4HNneqe37Jy1gGRO'); + + $hash->shouldReceive('make') + ->once()->with('foo123') + ->andReturn('hashedPassword'); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($validator->validatePassword($userA)); + $this->assertFalse($validator->validatePassword($userB)); + $this->assertTrue($validator->validatePassword($userC)); + } } From 460444d84dd14b9020b1b0c7ef9329f00cceb06e Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 18 Apr 2014 17:36:00 -0700 Subject: [PATCH 064/115] Update service provider location --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 073276e..8980348 100644 --- a/README.md +++ b/README.md @@ -46,20 +46,20 @@ to be confirmed to be able to login to the website. In the `require` key of `composer.json` file add the following - "zizaco/confide": "3.2.x" + "zizaco/confide": "dev-huge-update" Run the Composer update comand $ composer update -In your `config/app.php` add `'Zizaco\Confide\ConfideServiceProvider'` to the end of the `$providers` array +In your `config/app.php` add `'Zizaco\Confide\ServiceProvider'` to the end of the `$providers` array 'providers' => array( 'Illuminate\Foundation\Providers\ArtisanServiceProvider', 'Illuminate\Auth\AuthServiceProvider', ... - 'Zizaco\Confide\ConfideServiceProvider', + 'Zizaco\Confide\ServiceProvider', ), From 220d8cba81fd79f286fed200aea7731e23323e5d Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 18:44:09 -0300 Subject: [PATCH 065/115] Added implementation of UserValidator::validateIsUnique in order to check if an email or username has been used before --- src/Zizaco/Confide/UserValidator.php | 17 +++++- tests/Zizaco/Confide/UserValidatorTest.php | 70 +++++++++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 13c5fa4..68ae36c 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -64,7 +64,7 @@ public function validate(ConfideUserInterface $user, $ruleset = 'create') // Validate object $result = $this->validatePassword($user) && - $this->isUnique($user) && + $this->validateIsUnique($user) && $this->validateFields($user); return $result; @@ -96,4 +96,19 @@ public function validatePassword(ConfideUserInterface $user) return true; } + public function validateIsUnique(ConfideUserInterface $user) + { + $identity = [ + 'username' => $user->username, + 'email' => $user->email, + ]; + + $similar = $this->repo->getUserByIdentity($identity); + + if (!$similar || $similar->getKey() == $user->getKey()) { + return true; + } + + return false; + } } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 7d8e7d2..7b964bc 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -31,7 +31,7 @@ public function testShouldValidate() $validator = m::mock( 'Zizaco\Confide\UserValidator'. - '[validatePassword,isUnique,validateFields]' + '[validatePassword,validateIsUnique,validateFields]' ); $validator->shouldAllowMockingProtectedMethods(); @@ -45,7 +45,7 @@ public function testShouldValidate() $validator->shouldReceive('validatePassword') ->once()->andReturn(true); - $validator->shouldReceive('isUnique') + $validator->shouldReceive('validateIsUnique') ->once()->andReturn(true); $validator->shouldReceive('validateFields') @@ -120,4 +120,70 @@ public function testShouldValidatePassword() $this->assertFalse($validator->validatePassword($userB)); $this->assertTrue($validator->validatePassword($userC)); } + + public function testShouldValidateIsUnique() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $repo = m::mock('Zizaco\Confide\EloquentRepository'); + + $validator = new UserValidator; + $validator->repo = $repo; + + $userA = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userA->id = 1; + $userA->email = 'zizaco@gmail.com'; + $userA->username = 'zizaco'; + + $userB = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userB->id = '2'; + $userB->email = 'foo@bar.com'; + $userB->username = 'foo'; + + $userC = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userC->id = '3'; + $userC->email = 'something@somewhere.com'; + $userC->username = 'something'; + + $userD = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userD->id = ''; // No id + $userD->email = 'something@somewhere.com'; // Duplicated email + $userD->username = 'something'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $userA->shouldReceive('getKey') + ->andReturn($userA->id); + + $userB->shouldReceive('getKey') + ->andReturn($userB->id); + + $userC->shouldReceive('getKey') + ->andReturn($userC->id); + + $userD->shouldReceive('getKey') + ->andReturn($userD->id); + + $repo->shouldReceive('getUserByIdentity') + ->andReturnUsing(function($user) use ($userB, $userC) { + if ($user['email'] == $userB->email) return $userB; + if ($user['email'] == $userC->email) return $userC; + }); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($validator->validateIsUnique($userA)); + $this->assertTrue($validator->validateIsUnique($userB)); + $this->assertTrue($validator->validateIsUnique($userC)); + $this->assertFalse($validator->validateIsUnique($userD)); + } } From 77ece2f0a683a2995345e19d7675cc18122cdb44 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 19:04:19 -0300 Subject: [PATCH 066/115] Added implementation of UserValidator::validateAttributes in order to check if user attributes are valid. --- src/Zizaco/Confide/UserValidator.php | 28 +++++++++- tests/Zizaco/Confide/UserValidatorTest.php | 63 +++++++++++++++++++--- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 68ae36c..5552bdc 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -39,7 +39,7 @@ class UserValidator implements UserValidatorInterface { * * @var array */ - protected $rules = [ + public $rules = [ 'create' => [ 'username' => 'required|alpha_dash', 'email' => 'required|email', @@ -65,7 +65,7 @@ public function validate(ConfideUserInterface $user, $ruleset = 'create') // Validate object $result = $this->validatePassword($user) && $this->validateIsUnique($user) && - $this->validateFields($user); + $this->validateAttributes($user, $ruleset); return $result; } @@ -96,6 +96,13 @@ public function validatePassword(ConfideUserInterface $user) return true; } + /** + * Validates if the given user is unique. If there is another + * user with the same credentials but a different id, this + * method will return false. + * @param ConfideUserInterface $user + * @return boolean True if user is unique + */ public function validateIsUnique(ConfideUserInterface $user) { $identity = [ @@ -111,4 +118,21 @@ public function validateIsUnique(ConfideUserInterface $user) return false; } + + public function validateAttributes(ConfideUserInterface $user, $ruleset = 'create') + { + $attributes = $user->toArray(); + $rules = $this->rules[$ruleset]; + + $validator = App::make('validator') + ->make( $attributes, $rules ); + + // Validate and attach errors + if ($validator->fails()) { + $user->errors = $validator->errors(); + return false; + } else { + return true; + } + } } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 7b964bc..5110fdc 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -31,7 +31,7 @@ public function testShouldValidate() $validator = m::mock( 'Zizaco\Confide\UserValidator'. - '[validatePassword,validateIsUnique,validateFields]' + '[validatePassword,validateIsUnique,validateAttributes]' ); $validator->shouldAllowMockingProtectedMethods(); @@ -48,7 +48,7 @@ public function testShouldValidate() $validator->shouldReceive('validateIsUnique') ->once()->andReturn(true); - $validator->shouldReceive('validateFields') + $validator->shouldReceive('validateAttributes') ->once()->andReturn(true); /* @@ -66,13 +66,8 @@ public function testShouldValidatePassword() | Set |------------------------------------------------------------ */ - $repo = m::mock('Zizaco\Confide\EloquentRepository'); $hash = m::mock('Hash'); - App::shouldReceive('make') - ->with('confide.repository') - ->andReturn($repo); - App::shouldReceive('make') ->with('hash') ->andReturn($hash); @@ -186,4 +181,58 @@ public function testShouldValidateIsUnique() $this->assertTrue($validator->validateIsUnique($userC)); $this->assertFalse($validator->validateIsUnique($userD)); } + + public function testShouldValidateAttributes() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $laravelValidator = m::mock('Validator'); + $errorBag = m::mock('ErrorBag'); + + App::shouldReceive('make') + ->with('validator') + ->andReturn($laravelValidator); + + $validator = new UserValidator; + + $userA = m::mock('Zizaco\Confide\ConfideUserInterface'); + $userB = m::mock('Zizaco\Confide\ConfideUserInterface'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $userA->shouldReceive('toArray') + ->andReturn(['username'=>'foo']); + + $userB->shouldReceive('toArray') + ->andReturn(['username'=>'bar']); + + $laravelValidator->shouldReceive('make') + ->with(['username'=>'foo'], $validator->rules['create']) + ->once()->andReturn($laravelValidator); + + $laravelValidator->shouldReceive('make') + ->with(['username'=>'bar'], $validator->rules['create']) + ->once()->andReturn($laravelValidator); + + $laravelValidator->shouldReceive('fails') + ->twice()->andReturn(false, true); + + $laravelValidator->shouldReceive('errors') + ->once()->andReturn($errorBag); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($validator->validateAttributes($userA)); + $this->assertFalse($validator->validateAttributes($userB)); + $this->assertEquals($errorBag, $userB->errors); + } } From cfb74ef3e6a92caf75ca9cd7ac40b2c2fc76bf35 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 19:06:19 -0300 Subject: [PATCH 067/115] Added docblock in UserValidator::validateAttributes in order to explain the method purpose --- src/Zizaco/Confide/UserValidator.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 5552bdc..6b18072 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -119,6 +119,13 @@ public function validateIsUnique(ConfideUserInterface $user) return false; } + /** + * Uses Laravel Validator in order to check if the attributes of the + * $user object are valid for the given $ruleset + * @param ConfideUserInterface $user + * @param string $ruleset The name of the key in the UserValidator->$rules array + * @return boolean True if the attributes are valid + */ public function validateAttributes(ConfideUserInterface $user, $ruleset = 'create') { $attributes = $user->toArray(); From f89c3aa26c481fc8d9640b59fedff43cfe78ffb6 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 19:19:22 -0300 Subject: [PATCH 068/115] Added attachErrorMsg method to UserValidator in order to attach a message bag object with the error messages found. --- src/Zizaco/Confide/UserValidator.php | 14 ++++++++++ tests/Zizaco/Confide/UserValidatorTest.php | 32 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 6b18072..4c32b98 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -142,4 +142,18 @@ public function validateAttributes(ConfideUserInterface $user, $ruleset = 'creat return true; } } + + /** + * Creates a \Illuminate\Support\MessageBag object, add the error message + * to it and then set the errors attribute of the user with that bag + * @param ConfideUserInterface $user + * @param string $errorMsg The error messgae + * @return void + */ + public function attachErrorMsg(ConfideUserInterface $user, $errorMsg) + { + $messageBag = App::make('Illuminate\Support\MessageBag'); + $messageBag->add('confide', $errorMsg); + $user->errors = $messageBag; + } } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 5110fdc..27febb0 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -235,4 +235,36 @@ public function testShouldValidateAttributes() $this->assertFalse($validator->validateAttributes($userB)); $this->assertEquals($errorBag, $userB->errors); } + + public function testShouldAttachErrorMsg() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $errorBag = m::mock('ErrorBag'); + + App::shouldReceive('make') + ->with('Illuminate\Support\MessageBag') + ->andReturn($errorBag); + + $validator = new UserValidator; + $user = m::mock('Zizaco\Confide\ConfideUserInterface'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $errorBag->shouldReceive('add') + ->with('confide', 'foobar'); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $validator->attachErrorMsg($user, 'foobar'); + } } From 6f3aaa591c93dd36b739fb8083dc583446cbc594 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 19:36:18 -0300 Subject: [PATCH 069/115] Added error MessageBag object to validatePassword and validateIsUnique method of UserValidator in order to explain the error. --- src/Zizaco/Confide/UserValidator.php | 5 ++++- tests/Zizaco/Confide/UserValidatorTest.php | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 4c32b98..7a99ee0 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -1,6 +1,7 @@ attachErrorMsg($user, 'validation.confirmed::confide.alerts.wrong_password_reset'); return false; } } @@ -116,6 +118,7 @@ public function validateIsUnique(ConfideUserInterface $user) return true; } + $this->attachErrorMsg($user, 'confide::confide.alerts.duplicated_credentials'); return false; } @@ -153,7 +156,7 @@ public function validateAttributes(ConfideUserInterface $user, $ruleset = 'creat public function attachErrorMsg(ConfideUserInterface $user, $errorMsg) { $messageBag = App::make('Illuminate\Support\MessageBag'); - $messageBag->add('confide', $errorMsg); + $messageBag->add('confide', Lang::get($errorMsg)); $user->errors = $messageBag; } } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 27febb0..ca07d75 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -3,6 +3,7 @@ use Mockery as m; use PHPUnit_Framework_TestCase; use Illuminate\Support\Facades\App as App; +use Illuminate\Support\Facades\Lang as Lang; class UserValidatorTest extends PHPUnit_Framework_TestCase { @@ -72,7 +73,7 @@ public function testShouldValidatePassword() ->with('hash') ->andReturn($hash); - $validator = new UserValidator; + $validator = m::mock('Zizaco\Confide\UserValidator[attachErrorMsg]'); $userA = m::mock('Zizaco\Confide\ConfideUserInterface'); $userA->password = 'foo123'; @@ -106,6 +107,10 @@ public function testShouldValidatePassword() ->once()->with('foo123') ->andReturn('hashedPassword'); + $validator->shouldReceive('attachErrorMsg') + ->atLeast(1) + ->with(m::any(), 'validation.confirmed::confide.alerts.wrong_password_reset'); + /* |------------------------------------------------------------ | Assertion @@ -125,7 +130,7 @@ public function testShouldValidateIsUnique() */ $repo = m::mock('Zizaco\Confide\EloquentRepository'); - $validator = new UserValidator; + $validator = m::mock('Zizaco\Confide\UserValidator[attachErrorMsg]'); $validator->repo = $repo; $userA = m::mock('Zizaco\Confide\ConfideUserInterface'); @@ -171,6 +176,10 @@ public function testShouldValidateIsUnique() if ($user['email'] == $userC->email) return $userC; }); + $validator->shouldReceive('attachErrorMsg') + ->atLeast(1) + ->with(m::any(), 'confide::confide.alerts.duplicated_credentials'); + /* |------------------------------------------------------------ | Assertion @@ -257,8 +266,12 @@ public function testShouldAttachErrorMsg() | Expectation |------------------------------------------------------------ */ + Lang::shouldReceive('get') + ->once()->with('foobar') + ->andReturn('translated_foobar'); + $errorBag->shouldReceive('add') - ->with('confide', 'foobar'); + ->with('confide', 'translated_foobar'); /* |------------------------------------------------------------ From b9f06297ce5cfcfda2f6df4b5ac6d3b0675982f5 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 20:18:14 -0300 Subject: [PATCH 070/115] Removed 'repository' option from ControllerCommand. There will be always a repository now --- src/commands/ControllerCommand.php | 15 ++++++--------- tests/commands/ControllerCommandTest.php | 10 ++-------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index e15c1e2..79596e2 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -37,8 +37,7 @@ protected function getOptions() { return array( array('name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'Users'), - array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'), - array('--repository', '-R', InputOption::VALUE_NONE, 'Generate a User Repository class.'), + array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.') ); } @@ -54,10 +53,9 @@ public function fire() $namespace = $this->getNamespace($this->option('name')); $model = $this->app['config']->get('auth.model'); $restful = $this->option('restful'); - $repository = $this->option('repository'); $viewVars = compact( - 'class','namespace','model','restful','repository' + 'class','namespace','model','restful' ); // Prompt @@ -75,11 +73,10 @@ public function fire() $this->generateFile($filename, 'generators.controller', $viewVars); $this->info( "$class.php Successfully created!" ); - if ($repository) { - $filename = 'models/'.$model.'Repository.php'; - $this->generateFile($filename, 'generators.repository', $viewVars); - $this->info( "$model.'Repository.php Successfully created!" ); - } + // Generate repository + $filename = 'models/'.$model.'Repository.php'; + $this->generateFile($filename, 'generators.repository', $viewVars); + $this->info( "$model.'Repository.php Successfully created!" ); } } diff --git a/tests/commands/ControllerCommandTest.php b/tests/commands/ControllerCommandTest.php index 288117c..25e5699 100644 --- a/tests/commands/ControllerCommandTest.php +++ b/tests/commands/ControllerCommandTest.php @@ -37,8 +37,7 @@ public function testSouldGetOptions() $command = m::mock('Zizaco\Confide\ControllerCommand', [$app]); $options = [ ['name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', 'Users'], - ['--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'], - ['--repository', '-R', InputOption::VALUE_NONE, 'Generate a User Repository class.'], + ['--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'] ]; /* @@ -64,8 +63,7 @@ public function testSouldFire() 'class' => "UsersController", 'namespace' => "The\\Namespace", 'model' => "User", - 'restful' => true, - 'repository' => true, + 'restful' => true ]; /* @@ -93,10 +91,6 @@ public function testSouldFire() ->once()->with('restful') ->andReturn(true); - $command->shouldReceive('option') - ->once()->with('repository') - ->andReturn(true); - $command->shouldReceive('fire') ->passthru(); From 69d10651d654da79c816931811d47ebb825df695 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 20:58:19 -0300 Subject: [PATCH 071/115] Tweaked UserRepository name --- src/commands/ControllerCommand.php | 2 +- src/views/generators/repository.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index 79596e2..00bf160 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -76,7 +76,7 @@ public function fire() // Generate repository $filename = 'models/'.$model.'Repository.php'; $this->generateFile($filename, 'generators.repository', $viewVars); - $this->info( "$model.'Repository.php Successfully created!" ); + $this->info( $model.'Repository.php Successfully created!'); } } diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index 5755b22..fa63814 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -6,7 +6,7 @@ * This service abstracts some interactions that occurs within Confide and * the Database. */ -class Repository +class UserRepository { /** * Signup a new account with the given parameters From df2561dd6f64832514a5d35088c064f59638e07c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 20:59:18 -0300 Subject: [PATCH 072/115] Added isThrottled method to the throttleService in order to get the trhottle count for the given identity --- .../Confide/CacheLoginThrottleService.php | 32 +++++++-- .../Confide/LoginThrottleServiceInterface.php | 7 ++ .../Confide/CacheLoginThrottleServiceTest.php | 69 ++++++++++++++++++- 3 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php index e48754f..50678ab 100644 --- a/src/Zizaco/Confide/CacheLoginThrottleService.php +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -36,6 +36,30 @@ public function __construct($app = null) * @return integer How many times that same identity was used */ public function throttleIdentity($identity) + { + $identity = $this->parseIdentity($identity); + + // Increments and also retuns the current count + return $this->countThrottle($identity); + } + + public function isThrottled($identity) + { + $identity = $this->parseIdentity($identity); + + // Retuns the current count + return $this->countThrottle($identity, 0); + } + + /** + * Parse the given identity in order to return a string with + * the relevant fields. I.E: if the attacker tries to use a + * bunch of different passwords, the identity will still be the + * same. + * @param $mixed $identity + * @return string $identityString + */ + protected function parseIdentity($identity) { // If is an array, remove password, remember and then // transforms it into a string. @@ -45,9 +69,6 @@ public function throttleIdentity($identity) unset($identity['remember']); $identity = serialize($identity); } - - // Increments and also retuns the current count - return $this->countThrottle($identity); } /** @@ -56,14 +77,15 @@ public function throttleIdentity($identity) * identity. * * @param string $identityString + * @param integer $increments Amount that is going to be added to the throttling attemps for the given identity * @return integer How many times that same string was used */ - protected function countThrottle($identityString) + protected function countThrottle($identityString, $increments = 1) { $count = $this->app['cache'] ->get('login_throttling:'.md5($identityString), 0); - $count++; + $count = $count + $increments; $ttl = $this->app['config']->get('confide::throttle_time_period'); diff --git a/src/Zizaco/Confide/LoginThrottleServiceInterface.php b/src/Zizaco/Confide/LoginThrottleServiceInterface.php index 5c63dad..de66def 100644 --- a/src/Zizaco/Confide/LoginThrottleServiceInterface.php +++ b/src/Zizaco/Confide/LoginThrottleServiceInterface.php @@ -18,4 +18,11 @@ interface LoginThrottleServiceInterface * @return integer How many times that same identity was used */ public function throttleIdentity($identity); + + /** + * Tells if the given identity has reached the throttle_limit + * @param mixed $identity The login identity + * @return boolean True if the identity has reached the throttle_limit + */ + public function isThrottled($identity); } diff --git a/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php b/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php index 1d08147..782445c 100644 --- a/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php +++ b/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php @@ -24,7 +24,7 @@ public function testShouldThrottleIdentity() */ $identity = ['email'=>'someone@somewhere.com','password'=>'123']; - $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle]',[]); + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle, parseIdentity]',[]); $throttleService->shouldAllowMockingProtectedMethods(); /* @@ -32,6 +32,10 @@ public function testShouldThrottleIdentity() | Expectation |------------------------------------------------------------ */ + $throttleService->shouldReceive('parseIdentity') + ->once()->with($identity) + ->andReturn(serialize(['email'=>'someone@somewhere.com'])); + $throttleService->shouldReceive('countThrottle') ->once()->with(serialize(['email'=>'someone@somewhere.com'])) ->andReturn(5); @@ -44,6 +48,69 @@ public function testShouldThrottleIdentity() $this->assertEquals(5, $throttleService->throttleIdentity($identity)); } + public function testShouldCheckIsThrottled() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $identity = ['email'=>'someone@somewhere.com','password'=>'123']; + + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle, parseIdentity]',[]); + $throttleService->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $throttleService->shouldReceive('parseIdentity') + ->once()->with($identity) + ->andReturn(serialize(['email'=>'someone@somewhere.com'])); + + $throttleService->shouldReceive('countThrottle') + ->once()->with(serialize(['email'=>'someone@somewhere.com']), 0) + ->andReturn(5); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals(5, $throttleService->isThrottled($identity)); + } + + public function parseIdentity() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[parseIdentity]',[]); + $throttleService->shouldAllowMockingProtectedMethods(); + $identity = ['email'=>'someone@somewhere.com','password'=>'123']; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $throttleService->shouldReceive('parseIdentity') + ->passthru(); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + serialize(['email'=>'someone@somewhere.com']), + $throttleService->parseIdentity($identity) + ); + } + public function testShouldCountThrottle() { /* From 43cf118cf94e024ad3c7653c9e4d295b7e2358c6 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 21:14:05 -0300 Subject: [PATCH 073/115] Added docblock to CacheLoginThrottleService::isThrottled method --- src/Zizaco/Confide/CacheLoginThrottleService.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php index 50678ab..37d5b91 100644 --- a/src/Zizaco/Confide/CacheLoginThrottleService.php +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -43,6 +43,11 @@ public function throttleIdentity($identity) return $this->countThrottle($identity); } + /** + * Tells if the given identity has reached the throttle_limit + * @param mixed $identity The login identity + * @return boolean True if the identity has reached the throttle_limit + */ public function isThrottled($identity) { $identity = $this->parseIdentity($identity); From 6b88d2c74c3a0aae04db8a1eec08a84cf0531fc5 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 19 Apr 2014 21:21:58 -0300 Subject: [PATCH 074/115] Added the isThrottled method to the main Confide class in order to call the relative method in LoginThrottleServiceInterface --- src/Zizaco/Confide/Confide.php | 11 ++++++++ tests/Zizaco/Confide/ConfideTest.php | 39 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 647a35e..e5eec80 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -184,6 +184,17 @@ protected function loginThrottling($identity) return true; } + /** + * Asks the loginThrottler service if the given identity has reached the + * throttle_limit + * @param mixed $identity The login identity + * @return boolean True if the identity has reached the throttle_limit + */ + public function isThrottled($identity) + { + return $this->loginThrottler->isThrottled($identity); + } + /** * If an user with the given email exists then generate * a token for password change and saves it in the diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index f80506f..418946f 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -636,6 +636,45 @@ public function testShouldDoLoginThrottling() $this->assertFalse($confide->loginThrottling($throttledUserEmail)); } + public function testIsThrottled() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide[isThrottled]', + [$repo, $passService, $loginThrottler, $app] + ); + + $userEmail = 'someone@somewhere.com'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('isThrottled') + ->passthru(); + + $loginThrottler->shouldReceive('isThrottled') + ->once()->with($userEmail) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->isThrottled($userEmail)); + } + public function testShouldForgotPassword() { /* From 38f9b705286dcbb8ffd971533e4dded23b6bb5ed Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 12:04:55 -0300 Subject: [PATCH 075/115] Tweaked GenerateCommandTest in order not to actually call PHP's mkdir and file_put_contents --- src/Zizaco/Confide/Support/GenerateCommand.php | 2 ++ tests/Zizaco/Confide/Support/GenerateCommandTest.php | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Zizaco/Confide/Support/GenerateCommand.php b/src/Zizaco/Confide/Support/GenerateCommand.php index 07a51e5..42935aa 100644 --- a/src/Zizaco/Confide/Support/GenerateCommand.php +++ b/src/Zizaco/Confide/Support/GenerateCommand.php @@ -77,6 +77,7 @@ protected function appendInFile($filename, $view, $viewVars) /** * Encapsulates mkdir function + * @codeCoverageIgnore * @param string $directory * @param int $mode * @param bool $recursive @@ -89,6 +90,7 @@ protected function makeDir($directory, $mode, $recursive) /** * Encapsulates file_put_contents function + * @codeCoverageIgnore * @param string $filename * @param string $data * @param int $flags diff --git a/tests/Zizaco/Confide/Support/GenerateCommandTest.php b/tests/Zizaco/Confide/Support/GenerateCommandTest.php index 25aa6c8..fc40d59 100644 --- a/tests/Zizaco/Confide/Support/GenerateCommandTest.php +++ b/tests/Zizaco/Confide/Support/GenerateCommandTest.php @@ -31,7 +31,7 @@ public function testShouldGenerateFile() 'view'=>$view, 'path'=>'/where/the/app/is', ]; - $command = m::mock('Zizaco\Confide\Support\_GenerateCommandStub', [$app]); + $command = m::mock('Zizaco\Confide\Support\_GenerateCommandStub[makeDir,filePutContents]', [$app]); $command->shouldAllowMockingProtectedMethods(); $filename = 'path/to/file.php'; $viewName = 'generate.my_view'; @@ -59,12 +59,12 @@ public function testShouldGenerateFile() $command->shouldReceive('makeDir') ->with("/where/the/app/is/path/to", 493, true) ->once() - ->passthru(); + ->andReturn(true); $command->shouldReceive('filePutContents') ->with("/where/the/app/is/path/to/file.php", "The rendered content") ->once() - ->passthru(); + ->andReturn(true); /* |------------------------------------------------------------ @@ -88,7 +88,7 @@ public function testShouldAppendInFile() 'view'=>$view, 'path'=>'/where/the/app/is', ]; - $command = m::mock('Zizaco\Confide\Support\_GenerateCommandStub', [$app]); + $command = m::mock('Zizaco\Confide\Support\_GenerateCommandStub[makeDir,filePutContents]', [$app]); $command->shouldAllowMockingProtectedMethods(); $filename = 'path/to/file.php'; $viewName = 'generate.my_view'; @@ -116,12 +116,12 @@ public function testShouldAppendInFile() $command->shouldReceive('makeDir') ->with("/where/the/app/is/path/to", 493, true) ->once() - ->passthru(); + ->andReturn(true); $command->shouldReceive('filePutContents') ->with("/where/the/app/is/path/to/file.php", "The rendered content", 8) ->once() - ->passthru(); + ->andReturn(true); /* |------------------------------------------------------------ From 56112d362649b513b33147f26ed1a3a1fed79711 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 13:11:59 -0300 Subject: [PATCH 076/115] Updated generators.repository view in order to correctly use the user model namespace --- src/views/generators/repository.blade.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index fa63814..4d23dda 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -1,9 +1,15 @@ -{{ ' +@if (strstr($model, '\\')) + +use App, Config, Confide; +@endif /** * Class UserRepository * - * This service abstracts some interactions that occurs within Confide and + * This service abstracts some interactions that occurs between Confide and * the Database. */ class UserRepository @@ -11,11 +17,11 @@ class UserRepository /** * Signup a new account with the given parameters * @param array $input Array containing 'username', 'email' and 'password'. - * @return {{ $model }} {{ $model }} object that may or may not be saved successfully. Check the id to make sure. + * @return {{ $nonNamespacedName }} {{ $nonNamespacedName }} object that may or may not be saved successfully. Check the id to make sure. */ public function signup($input) { - $user = new {{ $model }}; + $user = new {{ $nonNamespacedName }}; $user->username = array_get($input, 'username'); $user->email = array_get($input, 'email'); @@ -74,10 +80,10 @@ public function existsButNotConfirmed($input) /** * Simply saves the given instance - * @param {{ $model }} $instance + * @param {{ $nonNamespacedName }} $instance * @return boolean Success */ - public function save({{ $model }} $instance) + public function save({{ $nonNamespacedName }} $instance) { return $instance->save(); } From a1dbca46e6c8890a86762488c711acc532331861 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 13:13:17 -0300 Subject: [PATCH 077/115] Updated ControllerCommand and Support\GenerateCommand to respect the directories of namespaced user models --- src/Zizaco/Confide/Support/GenerateCommand.php | 3 ++- src/commands/ControllerCommand.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Zizaco/Confide/Support/GenerateCommand.php b/src/Zizaco/Confide/Support/GenerateCommand.php index 42935aa..2d70b77 100644 --- a/src/Zizaco/Confide/Support/GenerateCommand.php +++ b/src/Zizaco/Confide/Support/GenerateCommand.php @@ -85,7 +85,8 @@ protected function appendInFile($filename, $view, $viewVars) */ protected function makeDir($directory, $mode, $recursive) { - @mkdir($directory, $mode, $recursive); + if (! is_dir($directory)) + @mkdir($directory, $mode, $recursive); } /** diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index 00bf160..93f2d15 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -74,7 +74,7 @@ public function fire() $this->info( "$class.php Successfully created!" ); // Generate repository - $filename = 'models/'.$model.'Repository.php'; + $filename = 'models/'.str_replace('\\', '/', $model).'Repository.php'; $this->generateFile($filename, 'generators.repository', $viewVars); $this->info( $model.'Repository.php Successfully created!'); } From 970310233da5aa4e655725dad297acfa3c0b176b Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 13:25:59 -0300 Subject: [PATCH 078/115] Tweaked RoutesCommand in order to use a more friendly Url --- src/commands/RoutesCommand.php | 4 +--- src/views/generators/routes.blade.php | 4 ++-- tests/commands/RoutesCommandTest.php | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php index 557ff93..3c46d2a 100644 --- a/src/commands/RoutesCommand.php +++ b/src/commands/RoutesCommand.php @@ -52,9 +52,7 @@ public function fire() $controllerName = $this->option('controller'); $restful = $this->option('restful'); - $url = explode('\\', $controllerName); - $url = array_pop($url); - $url = lcfirst(str_replace('Controller', '', $url)); + $url = 'user'; $viewVars = compact( 'controllerName', diff --git a/src/views/generators/routes.blade.php b/src/views/generators/routes.blade.php index 4a0a43c..72c2501 100644 --- a/src/views/generators/routes.blade.php +++ b/src/views/generators/routes.blade.php @@ -1,4 +1,4 @@ -{{ "\n\n\n\n" }} +// @if (! $restful) // Confide routes @@ -16,6 +16,6 @@ // Confide RESTful route Route::get('{{ $url }}/confirm/{code}', '{{ $controllerName }}@getConfirm'); -Route::get('{{ $url }}/reset/{token}', '{{ $controllerName }}@getReset'); +Route::get('{{ $url }}/reset/{token}', '{{ $controllerName }}@getReset'); Route::controller( '{{ $url }}', '{{ $controllerName }}'); @endif diff --git a/tests/commands/RoutesCommandTest.php b/tests/commands/RoutesCommandTest.php index 2cbd759..b6ab820 100644 --- a/tests/commands/RoutesCommandTest.php +++ b/tests/commands/RoutesCommandTest.php @@ -58,7 +58,7 @@ public function testSouldFire() $command->shouldAllowMockingProtectedMethods(); $viewVars = [ 'controllerName' => 'UsersController', - 'url' => 'users', + 'url' => 'user', 'restful' => true ]; From aff517252df1aa6b3ff8c9e378105ababb1d3a76 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 14:12:08 -0300 Subject: [PATCH 079/115] Fixed implementation of how to check if the given credentials are throttled --- .../Confide/CacheLoginThrottleService.php | 4 +- .../Confide/CacheLoginThrottleServiceTest.php | 51 +++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php index 37d5b91..4db0f03 100644 --- a/src/Zizaco/Confide/CacheLoginThrottleService.php +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -53,7 +53,9 @@ public function isThrottled($identity) $identity = $this->parseIdentity($identity); // Retuns the current count - return $this->countThrottle($identity, 0); + $count = $this->countThrottle($identity, 0); + + return $count >= $this->app['config']->get('confide::throttle_limit'); } /** diff --git a/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php b/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php index 782445c..46f6b5e 100644 --- a/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php +++ b/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php @@ -56,8 +56,10 @@ public function testShouldCheckIsThrottled() |------------------------------------------------------------ */ $identity = ['email'=>'someone@somewhere.com','password'=>'123']; + $config = m::mock('Config'); + $app = ['config'=>$config]; - $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle, parseIdentity]',[]); + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle,parseIdentity]',[$app]); $throttleService->shouldAllowMockingProtectedMethods(); /* @@ -71,14 +73,57 @@ public function testShouldCheckIsThrottled() $throttleService->shouldReceive('countThrottle') ->once()->with(serialize(['email'=>'someone@somewhere.com']), 0) - ->andReturn(5); + ->andReturn(10); // More than the limit specified bellow + + $config->shouldReceive('get') + ->once()->with('confide::throttle_limit') + ->andReturn(9); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($throttleService->isThrottled($identity)); + } + + public function testShouldCheckIsThrottledOnNonThrottled() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $identity = ['email'=>'someone@somewhere.com','password'=>'123']; + $config = m::mock('Config'); + $app = ['config'=>$config]; + + $throttleService = m::mock('Zizaco\Confide\CacheLoginThrottleService[countThrottle,parseIdentity]',[$app]); + $throttleService->shouldAllowMockingProtectedMethods(); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $throttleService->shouldReceive('parseIdentity') + ->once()->with($identity) + ->andReturn(serialize(['email'=>'someone@somewhere.com'])); + + $throttleService->shouldReceive('countThrottle') + ->once()->with(serialize(['email'=>'someone@somewhere.com']), 0) + ->andReturn(5); // Less than the limit specified bellow + + $config->shouldReceive('get') + ->once()->with('confide::throttle_limit') + ->andReturn(9); /* |------------------------------------------------------------ | Assertion |------------------------------------------------------------ */ - $this->assertEquals(5, $throttleService->isThrottled($identity)); + $this->assertFalse($throttleService->isThrottled($identity)); } public function parseIdentity() From a74fc4e19a41c370fb9acc8956690d49a9e4a459 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 14:13:31 -0300 Subject: [PATCH 080/115] Fixed routes command in order to match view urls --- src/commands/RoutesCommand.php | 2 +- tests/commands/RoutesCommandTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php index 3c46d2a..f0a1fed 100644 --- a/src/commands/RoutesCommand.php +++ b/src/commands/RoutesCommand.php @@ -52,7 +52,7 @@ public function fire() $controllerName = $this->option('controller'); $restful = $this->option('restful'); - $url = 'user'; + $url = 'users'; $viewVars = compact( 'controllerName', diff --git a/tests/commands/RoutesCommandTest.php b/tests/commands/RoutesCommandTest.php index b6ab820..2cbd759 100644 --- a/tests/commands/RoutesCommandTest.php +++ b/tests/commands/RoutesCommandTest.php @@ -58,7 +58,7 @@ public function testSouldFire() $command->shouldAllowMockingProtectedMethods(); $viewVars = [ 'controllerName' => 'UsersController', - 'url' => 'user', + 'url' => 'users', 'restful' => true ]; From 905686d9af87ad44ff62ab1775722f3f4f81b06f Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 19:22:37 -0300 Subject: [PATCH 081/115] Added remember_token to users table migration and also extension of Illuminate\Auth\Reminders\RemindableInterface in ConfideUserInterface --- src/Zizaco/Confide/ConfideUser.php | 13 +++++++- src/Zizaco/Confide/ConfideUserInterface.php | 3 +- ...01_13_172956_confide_setup_users_table.php | 30 ++++++++++++------- src/views/generators/migration.blade.php | 1 + 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/Zizaco/Confide/ConfideUser.php b/src/Zizaco/Confide/ConfideUser.php index 05919ec..d16afa3 100644 --- a/src/Zizaco/Confide/ConfideUser.php +++ b/src/Zizaco/Confide/ConfideUser.php @@ -30,7 +30,7 @@ trait ConfideUser { */ public function confirm() { - $this->confirmed = 1; + $this->confirmed = true; return ConfideFacade::confirm($this->confirmation_code); } @@ -148,4 +148,15 @@ public function getRememberTokenName() { return 'remember_token'; } + + /** + * Get the e-mail address where password reminders are sent. + * + * @see \Illuminate\Auth\Reminders\RemindableInterface + * @return string + */ + public function getReminderEmail() + { + return $this->email; + } } diff --git a/src/Zizaco/Confide/ConfideUserInterface.php b/src/Zizaco/Confide/ConfideUserInterface.php index a0b53fb..d049eb6 100644 --- a/src/Zizaco/Confide/ConfideUserInterface.php +++ b/src/Zizaco/Confide/ConfideUserInterface.php @@ -1,6 +1,7 @@ increments('id'); - $table->string('username')->unique(); - $table->string('email')->unique(); - $table->string('password'); - $table->string('confirmation_code'); - $table->boolean('confirmed')->default(false); - $table->timestamps(); - }); + Schema::create('users', function($table) + { + $table->increments('id'); + $table->string('username')->unique(); + $table->string('email')->unique(); + $table->string('password'); + $table->string('confirmation_code'); + $table->string('remember_token'); + $table->boolean('confirmed')->default(false); + $table->timestamps(); + }); + + // Creates password reminders table + Schema::create('password_reminders', function($t) + { + $t->string('email'); + $t->string('token'); + $t->timestamp('created_at'); + }); } /** @@ -31,6 +40,7 @@ public function up() */ public function down() { + Schema::drop('password_reminders'); Schema::drop('users'); } diff --git a/src/views/generators/migration.blade.php b/src/views/generators/migration.blade.php index 61f1790..6489e6e 100644 --- a/src/views/generators/migration.blade.php +++ b/src/views/generators/migration.blade.php @@ -19,6 +19,7 @@ public function up() $table->string('email')->unique(); $table->string('password'); $table->string('confirmation_code'); + $table->string('remember_token'); $table->boolean('confirmed')->default(false); $table->timestamps(); }); From 072476f26f8a9ae95300dd317d390deb580cd183 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 19:24:14 -0300 Subject: [PATCH 082/115] Tweaked how the user password reset will be handled --- src/Zizaco/Confide/Confide.php | 15 ++++++++++++ src/Zizaco/Confide/EloquentRepository.php | 12 ++++++++++ src/views/generators/controller.blade.php | 14 ++++++----- src/views/generators/repository.blade.php | 24 +++++++++++++++++-- .../Zizaco/Confide/EloquentRepositoryTest.php | 1 + 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index e5eec80..8214c6e 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -92,6 +92,21 @@ public function confirm($code) return $this->repo->confirmByCode($code); } + /** + * Checks if a user with the given identity (email or username) already + * exists and retrieve it + * + * @param array $identity Array containing at least 'username' or 'email'. + * @return \Zizaco\Confide\ConfideUserInterface|null + */ + public function getUserByEmailOrUsername($identity) + { + if (is_array($identity)) + $identity = $this->extractIdentityFromArray($identity); + + return $this->repo->getUserByEmailOrUsername($identity); + } + /** * Attempt to log a user into the application with * password and identity field(s), usually email or username. diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index 886fb37..e5c4766 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -128,4 +128,16 @@ public function confirmByCode($code) return false; } } + + /** + * Updated the given user in the database. Set the 'confirmed' attribute to + * true. + * @param ConfideUser User object + * @return bool Success + */ + protected function confirmUser($user) + { + $user->confirmed = true; + return $user->save(); + } } diff --git a/src/views/generators/controller.blade.php b/src/views/generators/controller.blade.php index 2bde909..c7208ff 100644 --- a/src/views/generators/controller.blade.php +++ b/src/views/generators/controller.blade.php @@ -1,5 +1,6 @@ {{ ' @if ($namespace) use App, View, Input, Config, Redirect, Lang, Confide; @@ -28,7 +29,7 @@ public function {{ (! $restful) ? 'create' : 'getCreate' }}() */ public function {{ (! $restful) ? 'store' : 'postIndex' }}() { - $repo = App::make('UserRepository'); + $repo = App::make('{{ $repositoryClass }}'); $user = $repo->signup(Input::all()); if ($user->id) @@ -68,7 +69,7 @@ public function {{ (! $restful) ? 'login' : 'getLogin' }}() */ public function {{ (! $restful) ? 'do_login' : 'postLogin' }}() { - $repo = App::make('UserRepository'); + $repo = App::make('{{ $repositoryClass }}'); $input = Input::all(); if ($repo->login($input)) @@ -163,14 +164,15 @@ public function {{ (! $restful) ? 'reset_password' : 'getReset' }}( $token ) */ public function {{ (! $restful) ? 'do_reset_password' : 'postReset' }}() { + $repo = App::make('{{ $repositoryClass }}'); $input = array( - 'token'=>Input::get( 'token' ), - 'password'=>Input::get( 'password' ), - 'password_confirmation'=>Input::get( 'password_confirmation' ), + 'token' =>Input::get( 'token' ), + 'password' =>Input::get( 'password' ), + 'password_confirmation' =>Input::get( 'password_confirmation' ), ); // By passing an array with the token, password and confirmation - if( Confide::resetPassword( $input ) ) + if( $repo->resetPassword( $input ) ) { $notice_msg = Lang::get('confide::confide.alerts.password_reset'); return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index 4d23dda..44bbdfe 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -73,9 +73,29 @@ public function isThrottled($input) */ public function existsButNotConfirmed($input) { - $user = App::make('{{ $model }}'); + $user = Confide::getUserByEmailOrUsername($input); - return $user->checkUserExists($input) and !$user->isConfirmed($input); + if ($user) + return ! $user->confirmed; + } + + /** + * Resets a password of a user. The $input['token'] will tell which user. + * @param array $input Array containing 'token', 'password' and 'password_confirmation' keys. + * @return boolean Success + */ + public function resetPassword($input) + { + $result = false; + $user = Confide::userByResetPasswordToken($input['token']); + + if ($user) { + $user->password = $input['password']; + $user->password_confirmation = $input['password_confirmation']; + $result = $this->save($user); + } + + return $result; } /** diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index 71b8991..125e7d4 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -207,6 +207,7 @@ public function testShouldConfirmByCode() $wrongConfirmCode = 'IdontExist'; $user = m::mock('_mockedUser'); $repo = m::mock('Zizaco\Confide\EloquentRepository[getUserByIdentity,confirmUser]',[]); + $repo->shouldAllowMockingProtectedMethods(); /* |------------------------------------------------------------ From ddd51bfd44ff9c49801f6ed84e41567ef2e8d424 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 22:23:53 -0300 Subject: [PATCH 083/115] Updated README.md file in order to match 4.0.0 Beta 1 changes --- README.md | 203 ++++++++++++++++++++---------------------------------- 1 file changed, 73 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index 8980348..59f8a72 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Confide (Laravel4 Package) +# Confide _(A Laravel4 Package)_ ![Confide Poster](https://dl.dropbox.com/u/12506137/libs_bundles/confide.png) @@ -17,11 +17,11 @@ Confide aims to be simple to use, quick to configure and flexible. - Account confirmation (through confirmation link). - Password reset (sending email with a change password link). - Easily render forms for login, signup and password reset. -- Generate customizable routes for login, signup, password reset, confirmation, etc. +- Generate routes for login, signup, password reset, confirmation, etc. - Generate a customizable controller that handles the basic user account actions. -- Contains a set of methods to help basic user features. -- Integrated with the Laravel Auth component/configs. -- Field/model validation (Powered by [Ardent](http://laravelbook.github.com/ardent "Ardent")). +- Contains a set of methods to help with basic user features. +- Integrated with the Laravel _Auth_ and _Reminders_ component/configs. +- User validation. - Login throttling. - Redirecting to previous route after authentication. - Checks for unique email and username in signup @@ -30,15 +30,10 @@ If you are looking for user roles and permissions see [Entrust](https://github.c For MongoDB support see [Confide Mongo](https://github.com/Zizaco/confide-mongo) -**Planned:** -- Captcha in user signup and password reset. - -**Warning:** - -By default a confirmation email is sent and users are required to confirm the email address. +**Warning:** _By default a confirmation email is sent and users are required to confirm the email address. It is easy to change this in the confide config file. -Change signup_email and signup_confirm to false if you do not want to send them an email and they do not need -to be confirmed to be able to login to the website. +Change `signup_email` and `signup_confirm` to false if you do not want to send them an email and they do not need +to be confirmed to be able to login to the website._ ## Quick start @@ -46,13 +41,13 @@ to be confirmed to be able to login to the website. In the `require` key of `composer.json` file add the following - "zizaco/confide": "dev-huge-update" + "zizaco/confide": "~4.0" Run the Composer update comand $ composer update -In your `config/app.php` add `'Zizaco\Confide\ServiceProvider'` to the end of the `$providers` array +In your `config/app.php` add `'Zizaco\Confide\ServiceProvider'` to the end of the `providers` array 'providers' => array( @@ -63,14 +58,14 @@ In your `config/app.php` add `'Zizaco\Confide\ServiceProvider'` to the end of th ), -At the end of `config/app.php` add `'Confide' => 'Zizaco\Confide\ConfideFacade'` to the `$aliases` array +At the end of `config/app.php` add `'Confide' => 'Zizaco\Confide\Facade'` to the `aliases` array 'aliases' => array( 'App' => 'Illuminate\Support\Facades\App', 'Artisan' => 'Illuminate\Support\Facades\Artisan', ... - 'Confide' => 'Zizaco\Confide\ConfideFacade', + 'Confide' => 'Zizaco\Confide\Facade', ), @@ -90,23 +85,24 @@ It will generate the `_confide_setup_users_table.php` migration. You $ php artisan migrate -It will setup a table containing `email`, `password`, `confirmation_code` and `confirmed` fields, which are the default fields needed for Confide use. Feel free to add more fields to the database. +It will setup a table containing `email`, `password`, `remember_token`, `confirmation_code` and `confirmed` columns, which are the default fields needed for Confide use. Feel free to add more columns to the table later. Change your User model in `app/models/User.php` to: 'Zizaco\Confide\Facade'` entry in `config/app.php` `'providers'` and `'aliases'` respectively. +2. User model (with the same name as in `config/auth.php`) should implement `Zizaco\Confide\ConfideUserInterface` interface. This will cause to methods like `forgotPassword()` and `confirm()` to be available. **Optional steps:** -1. Use `Confide` facade to dump login and signup forms easly with `makeLoginForm()` and `makeSignupForm()`. You can render the forms within your views by doing `{{ Confide::makeLoginForm()->render() }}`. -2. Generate a controller with the template contained in Confide throught the artisan command `$ php artisan confide:controller`. If a controller with the same name exists it will **NOT** be overwritten. -3. Generate routes matching the controller template throught the artisan command `$ php artisan confide:routes`. Your `routes.php` will **NOT** be overwritten. +1. Optionally you can use the trait `Zizaco\Confide\ConfideUser` in your user model. This will save a lot of time and will use "confide's default" implementation for the user. If you wish more customization you can write your own code. +2. Use `Confide` facade to dump login and signup forms easly with `makeLoginForm()` and `makeSignupForm()`. You can render the forms within your views by doing `{{ Confide::makeLoginForm()->render() }}`. +3. Generate a **controller** and a **repository** with the template contained in Confide throught the artisan command `$ php artisan confide:controller`. If a controller with the same name exists it will **NOT** be overwritten. +4. Generate routes matching the controller template throught the artisan command `$ php artisan confide:routes`. Don't worry, your `routes.php` will **NOT** be overwritten. ### Advanced -#### Using custom table / model name +#### The `UserRepository` class + +You may have noticed that when generating the controller a `UserRepository` class has also been created. This class contains some code that doesn't belong to the "controller" purpose and will make your users controller a cleaner and more testable class. If you still have no idea why that class exists I recommend you to google _"Creating flexible Controllers in Laravel 4 using Repositories"_. _(wink)_ -You can change the model name that will be authenticated in the `config/auth.php` file. +#### Using custom class, table or model name + +You can change the model name that will be considered the user in the `config/auth.php` file. Confide uses the values present in that configuration file. To change the controller name when dumping the default controller template you can use the --name option. - $ php artisan confide:controller --name Employee + $ php artisan confide:controller --name=Employee Will result in `EmployeeController` Then, when dumping the routes, you should use the --controller option to match the existing controller. - $ php artisan confide:routes --controller Employee + $ php artisan confide:routes --controller=Employee + +You can also generate controllers with namespace + + $ php artisan confide:controller --name=MyProject\\Auth\\User + +**Warning:** In bash, you will need to use double '\\\\' backslashes. This will result in `MyProject\Auth\UserController`. Also the generated file will be inside a directory equivalent to the namespace. _(wink)_ #### Using custom form or emails @@ -162,86 +169,23 @@ First, publish the config files: Then edit the view names in `app/config/packages/zizaco/confide/config.php`. -#### Update an User - -To update an user already in the database you'll Need to make sure your ruleset is using the unique validator within the User model. - - 'unique:users,username', - 'email' => 'email' - ); - - ?> - - email = Input::get('email'); - - // Save - // This was previously update, but Ardent changed. - $user->updateUniques(); - - } - } - - ?> - -This will allow you to update the current user. - -#### Validate model fields - -To change the validation rules of the User model you can take a look at [Ardent](http://laravelbook.github.com/ardent/#validation "Ardent Validation Rulez"). For example: +#### Custom user validation - 'required|email', - 'password' => 'required|between:4,11|confirmed', - ); +To save an user that use the `Zizaco\Confide\ConfideUser` trait you'll need to make sure the `isValid` method is returning true. Take a look at the `Zizaco\Confide\UserValidator` class in order to understand the "default" user validation. Feel free to replace the validator by your own class and rules. - } - -Feel free to add more fields to your table and to the validation array. Then you should build your own sign-up form with the additional fields. - -NOTE: If you add fields to your validation rules into your model like above, do not forget you have to add those fields to the UserController store function also. If you forget this, the form will always return with an error. -Example: $user->terms = Input::get('terms'); +#### Passing additional information to the "make" methods -#### Passing additional information to the make methods - -If you want to pass additional parameters to the forms, you can use an alternate syntax to achieve this. +If you want to pass additional parameters to the forms being rendered, you can use an alternate syntax to achieve this. Instead of using the make method: - + Confide::makeResetPasswordForm( $token ): You would use: View::make(Config::get('confide::reset_password_form')) ->with('token', $token); - + It produces the same output, but you would be able to add more inputs using 'with' just like any other view. #### RESTful controller @@ -255,64 +199,52 @@ Will result in a [RESTful controller](https://github.com/laravel/docs/blob/maste Then, when dumping the routes, you should use the --restful option to match the existing controller. $ php artisan confide:routes --restful - + #### User roles and permissions -In order not to bloat Confide with not related features, the role and permission was developed as another package: [Entrust](https://github.com/Zizaco/entrust). This package couples very well with Confide. +In order not to bloat Confide with not related features, the role and permission was developed as another package: [Entrust](https://github.com/Zizaco/entrust). Enstrust couples very well with Confide. See [Entrust](https://github.com/Zizaco/entrust) #### Redirecting to previous route after login -When defining your filter you should use the Redirect::guest('user/login') within your auth filter. For example: +When defining your filter you should use the Redirect::guest('users/login') within your auth filter. For example: // filters.php - Route::filter('auth', function() - { - if ( Auth::guest() ) // If the user is not logged in - { - return Redirect::guest('user/login'); + Route::filter('auth', function() { + // If the user is not logged in + if (Auth::guest()) { + return Redirect::guest('users/login'); } }); // Only authenticated users will be able to access routes that begins with // 'admin'. Ex: 'admin/posts', 'admin/categories'. - Route::when('admin*', 'auth'); + Route::when('admin*', 'auth'); or, if you are using [Entrust](https://github.com/Zizaco/entrust) ;) // filters.php Entrust::routeNeedsRole( 'admin*', 'Admin', function(){ - return Redirect::guest('user/login'); + return Redirect::guest('users/login'); } ); -Finally, it'll auto redirect if your controller's user/login function uses Redirect:intended('a/default/url/here') after a successful login. +Finally, it'll auto redirect if your controller's users/login function uses Redirect:intended('a/default/url/here') after a successful login. The [generated controller](https://github.com/Zizaco/confide/blob/master/src/views/generators/controller.blade.php) does exactly this. - -#### Validating a route - -If you want to validate whether a route exists, the `Confide::checkAction` function is what you are looking for. - -Currently it is used within the views to determine Non-RESTful vs RESTful routes. ## Troubleshooting -__[Exception] SQLSTATE[HY000]: General error: 1364 Field 'confirmation_code' doesn't have a default value...__ +__I receive a "Your account may not be confirmed" when trying to login__ -If you overwrite the `beforeSave()` method in your model, make sure to call `parent::beforeSave()`: +You need to confirm a newly created user _(by "reaching" its `confirm()` method)_, otherwise you can disable the confirmation as a requirement to login in in the config file _(see bellow)_. You can easly confirm a user manually using Laravel's `artisan tinker` tool. - public function beforeSave( $forced = false ){ +__I'm not able to generate a controller with namespaces__ - parent::beforeSave( $forced) // Don't forget this +In bash, you will need to use double '\\\\' backslashes. Also the generated file will be inside a directory equivalent to the namespace: - // Your stuff - } - -__Confirmation link is not sent when user signup__ - -Same as above. If you overwrite the `afterSave()` method in your model, make sure to call `parent::afterSave()`: + $ php artisan confide:controller --name=MyProject\\Auth\\User __Users are able to login without confirming account__ @@ -320,6 +252,17 @@ If you want only confirmed users to login, in your `UserController`, instead of ## Release Notes +### Version 4.0.0 Beta 1 +* Dropped Ardent dependency. +* Updated to support Laravel 4.2 +* Dropped support for PHP 5.3 +* ConfideUser is going to be a trait+interface from now on. +* Controller generation now also generates a UserRepository class. +* Removed deprecated variables, functions and classes. +* All the codebase has been rewritten. + +__Upgrade note:__ A partial update from previous versions is not recommended. In order to upgrade from v3.* to v4.0.0 the best approach is to update the class names in the providers and aliases array, re-generate the user table with the new migration, re-write the "user" class and finally re-generate the controllers. It's very likely any customization made in your codebase will be affected. + ### Version 3.0.0 Updated to support Laravel 4.1 From 617e3aad43cb20d40036e428888c7f4fd4e94faf Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 23:14:54 -0300 Subject: [PATCH 084/115] Updated Zizaco\Confide\ConfideUserTest in order to match method name change in Eloquent --- tests/Zizaco/Confide/ConfideUserTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 6610771..371a27a 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -110,7 +110,7 @@ public function testShouldValidateAndSave() | Set |------------------------------------------------------------ */ - $user = m::mock('Zizaco\Confide\_ConfideUserStub[isValid,save,newQueryWithDeleted]'); + $user = m::mock('Zizaco\Confide\_ConfideUserStub[isValid,save,newQueryWithoutScopes]'); /* |------------------------------------------------------------ @@ -126,7 +126,7 @@ public function testShouldValidateAndSave() ->andReturn(true); // Throw an exception instead of actually saving the object - $user->shouldReceive('newQueryWithDeleted') + $user->shouldReceive('newQueryWithoutScopes') ->once() ->andReturnUsing(function(){ throw new \Exception('Saved in database'); From bd390d59affaa341b35dec4a717b74a930eabe0d Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sat, 12 Jul 2014 23:30:54 -0300 Subject: [PATCH 085/115] Updated Readme in order to include version locking to the troubleshooting section --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59f8a72..f68f5cd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Build Status](https://api.travis-ci.org/Zizaco/confide.png)](https://travis-ci.org/Zizaco/confide) [![ProjectStatus](http://stillmaintained.com/Zizaco/confide.png)](http://stillmaintained.com/Zizaco/confide) -Confide is a authentication solution for **Laravel4** made to eliminate repetitive tasks involving the management of users: Account creation, login, logout, confirmation by e-mail, password reset, etc. +Confide is an authentication solution for **Laravel4** made to eliminate repetitive tasks involving the management of users: Account creation, login, logout, confirmation by e-mail, password reset, etc. Confide aims to be simple to use, quick to configure and flexible. @@ -238,7 +238,7 @@ The [generated controller](https://github.com/Zizaco/confide/blob/master/src/vie __I receive a "Your account may not be confirmed" when trying to login__ -You need to confirm a newly created user _(by "reaching" its `confirm()` method)_, otherwise you can disable the confirmation as a requirement to login in in the config file _(see bellow)_. You can easly confirm a user manually using Laravel's `artisan tinker` tool. +You need to confirm a newly created user _(by "reaching" its `confirm()` method)_, otherwise you can disable the confirmation as a requirement to login in in the config file _(see bellow)_. You can easly confirm an user manually using Laravel's `artisan tinker` tool. __I'm not able to generate a controller with namespaces__ @@ -250,6 +250,14 @@ __Users are able to login without confirming account__ If you want only confirmed users to login, in your `UserController`, instead of simply calling `logAttempt( $input )`, call `logAttempt( $input, true )`. The second parameter stands for _"confirmed_only"_. +__My application is crashing since I ran composer update__ + +*Confide 4.0.0* was a huge update where all the codebase has been rewritten. Some classes changed, the generators has been improved in order to match some better practices (like repositories and separated validator classes). See the _Release Notes_ bellow. + +If you have a legacy project that uses an older version of Confide, don't worry. You will be always able to specify a previous version in your `composer.json` file. + +For example: `"zizaco/confide": "~3.2"` will avoid composer download version 4.0 but will be able to download bugfixes of version 3.2. + ## Release Notes ### Version 4.0.0 Beta 1 @@ -257,7 +265,7 @@ If you want only confirmed users to login, in your `UserController`, instead of * Updated to support Laravel 4.2 * Dropped support for PHP 5.3 * ConfideUser is going to be a trait+interface from now on. -* Controller generation now also generates a UserRepository class. +* Controller generation now also generates an UserRepository class. * Removed deprecated variables, functions and classes. * All the codebase has been rewritten. From be9fac28ddb15283f8f6834c8d980f0a22dd8af7 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 00:18:29 -0300 Subject: [PATCH 086/115] Tweaked some implementations regarding confirmation and lost password emails --- .../Confide/EloquentPasswordService.php | 21 +++++++++++++++++++ src/views/emails/confirm.blade.php | 4 ++-- src/views/emails/passwordreset.blade.php | 4 ++-- src/views/generators/controller.blade.php | 8 ++++++- src/views/generators/repository.blade.php | 3 +++ src/views/generators/routes.blade.php | 5 +++-- src/views/login.blade.php | 2 +- .../Confide/EloquentPasswordServiceTest.php | 7 ++++++- 8 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 4f5e25b..0795ae3 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -52,6 +52,8 @@ public function requestChangePassword(RemindableInterface $user) ->table('password_reminders') ->insert($values); + $this->sendEmail($user, $token); + return $token; } @@ -102,4 +104,23 @@ protected function unwrapEmail($email) return $email; } + + /** + * Sends an email containing the reset password link with the given token to + * the user + * @param RemindableInterface $user An existent user + * @param string $token Password reset token + * @return void + */ + protected function sendEmail($user, $token) + { + $config = $this->app['config']; + $lang = $this->app['translator']; + + $this->app['mailer']->send($config->get('confide::email_reset_password'), compact('user', 'token'), function($message) use ($user, $token, $lang) { + $message + ->to($user->email, $user->username) + ->subject($lang->get('confide::confide.email.password_reset.subject')); + }); + } } diff --git a/src/views/emails/confirm.blade.php b/src/views/emails/confirm.blade.php index a939f0c..847d630 100644 --- a/src/views/emails/confirm.blade.php +++ b/src/views/emails/confirm.blade.php @@ -3,8 +3,8 @@

{{ Lang::get('confide::confide.email.account_confirmation.greetings', array( 'name' => $user->username)) }},

{{ Lang::get('confide::confide.email.account_confirmation.body') }}

- - {{{ URL::to("user/confirm/{$user->confirmation_code}") }}} + + {{{ URL::to("users/confirm/{$user->confirmation_code}") }}}

{{ Lang::get('confide::confide.email.account_confirmation.farewell') }}

diff --git a/src/views/emails/passwordreset.blade.php b/src/views/emails/passwordreset.blade.php index ccb7b8e..2632bb0 100644 --- a/src/views/emails/passwordreset.blade.php +++ b/src/views/emails/passwordreset.blade.php @@ -3,8 +3,8 @@

{{ Lang::get('confide::confide.email.password_reset.greetings', array( 'name' => $user->username)) }},

{{ Lang::get('confide::confide.email.password_reset.body') }}

- - {{{ (Confide::checkAction('UserController@reset_password', array($token))) ? : URL::to('user/reset/'.$token) }}} + + {{ URL::to('users/reset_password/'.$token) }}

{{ Lang::get('confide::confide.email.password_reset.farewell') }}

diff --git a/src/views/generators/controller.blade.php b/src/views/generators/controller.blade.php index c7208ff..b4bb403 100644 --- a/src/views/generators/controller.blade.php +++ b/src/views/generators/controller.blade.php @@ -3,7 +3,7 @@ @if ($namespace) -use App, View, Input, Config, Redirect, Lang, Confide; +use App, View, Input, Config, Redirect, Lang, Mail, Confide; use Controller; @endif @@ -34,6 +34,12 @@ public function {{ (! $restful) ? 'store' : 'postIndex' }}() if ($user->id) { + Mail::send(Config::get('confide::email_account_confirmation'), compact('user'), function($message) use ($user) { + $message + ->to($user->email, $user->username) + ->subject(Lang::get('confide::confide.email.account_confirmation.subject')); + }); + return Redirect::action('{{ $namespace ? $namespace.'\\' : '' }}{{ $class }}@login') ->with( 'notice', Lang::get('confide::confide.alerts.account_created') ); } diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index 44bbdfe..1dcda72 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -32,6 +32,9 @@ public function signup($input) // auto validation. $user->password_confirmation = array_get($input, 'password_confirmation' ); + // Generate a random confirmation code + $user->confirmation_code = md5($user->username.time('U')); + // Save if valid. Password field will be hashed before save $this->save($user); diff --git a/src/views/generators/routes.blade.php b/src/views/generators/routes.blade.php index 72c2501..fa01117 100644 --- a/src/views/generators/routes.blade.php +++ b/src/views/generators/routes.blade.php @@ -15,7 +15,8 @@ @else // Confide RESTful route -Route::get('{{ $url }}/confirm/{code}', '{{ $controllerName }}@getConfirm'); -Route::get('{{ $url }}/reset/{token}', '{{ $controllerName }}@getReset'); +Route::get('{{ $url }}/confirm/{code}', '{{ $controllerName }}@getConfirm'); +Route::get('{{ $url }}/reset_password/{token}', '{{ $controllerName }}@getReset'); +Route::get('{{ $url }}/reset_password', '{{ $controllerName }}@postReset'); Route::controller( '{{ $url }}', '{{ $controllerName }}'); @endif diff --git a/src/views/login.blade.php b/src/views/login.blade.php index 78d9a5e..c3d194e 100644 --- a/src/views/login.blade.php +++ b/src/views/login.blade.php @@ -9,7 +9,7 @@ diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index bdf9d6a..4064c42 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -36,7 +36,7 @@ public function testSouldRequestChangePassword() $generatedToken = '123456789'; $user = m::mock('Illuminate\Auth\Reminders\RemindableInterface'); - $passService = m::mock('Zizaco\Confide\EloquentPasswordService[generateToken]',[]); + $passService = m::mock('Zizaco\Confide\EloquentPasswordService[generateToken,sendEmail]',[]); $db = m::mock('connection'); $passService->shouldAllowMockingProtectedMethods(); @@ -58,6 +58,11 @@ public function testSouldRequestChangePassword() $passService->shouldReceive('generateToken') ->andReturn($generatedToken); + // The email containing the reset link should be sent + $passService->shouldReceive('sendEmail') + ->once() + ->andReturn($user, $generatedToken); + // Mocks DB in order to check for the following query: // DB::table('password_reminders')->insert(array( // 'email'=> $email, From 144391a144b6ae57c31dde0f245383e70750afb7 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 00:49:20 -0300 Subject: [PATCH 087/115] Added new badges to README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index f68f5cd..15c88d6 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ [![Build Status](https://api.travis-ci.org/Zizaco/confide.png)](https://travis-ci.org/Zizaco/confide) [![ProjectStatus](http://stillmaintained.com/Zizaco/confide.png)](http://stillmaintained.com/Zizaco/confide) +[![Latest Stable Version](https://poser.pugx.org/zizaco/confide/v/stable.png)](https://packagist.org/packages/zizaco/confide) +[![Total Downloads](https://poser.pugx.org/zizaco/confide/downloads.png)](https://packagist.org/packages/zizaco/confide) +[![License](https://poser.pugx.org/zizaco/confide/license.png)](http://opensource.org/licenses/MIT) + +[![SensioLabsInsight](https://insight.sensiolabs.com/projects/ec420846-0af4-4df4-b424-be90d9c3f98e/small.png)](https://insight.sensiolabs.com/projects/ec420846-0af4-4df4-b424-be90d9c3f98e) Confide is an authentication solution for **Laravel4** made to eliminate repetitive tasks involving the management of users: Account creation, login, logout, confirmation by e-mail, password reset, etc. From b4291bfc313e2f8f9a6f9da04780a40268539ff5 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 00:50:37 -0300 Subject: [PATCH 088/115] Removed unused 'use' statements --- .gitignore | 1 - src/commands/ControllerCommand.php | 1 - src/commands/MigrationCommand.php | 1 - src/commands/RoutesCommand.php | 1 - 4 files changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index fc7ea17..8b7ef35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /vendor composer.lock -.DS_Store diff --git a/src/commands/ControllerCommand.php b/src/commands/ControllerCommand.php index 93f2d15..a358873 100644 --- a/src/commands/ControllerCommand.php +++ b/src/commands/ControllerCommand.php @@ -2,7 +2,6 @@ use Zizaco\Confide\Support\GenerateCommand; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; /** * This command renders the package view generator.contoller and also diff --git a/src/commands/MigrationCommand.php b/src/commands/MigrationCommand.php index da014a6..9c53139 100644 --- a/src/commands/MigrationCommand.php +++ b/src/commands/MigrationCommand.php @@ -2,7 +2,6 @@ use Zizaco\Confide\Support\GenerateCommand; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; /** * This command renders the package view generator.migration and also diff --git a/src/commands/RoutesCommand.php b/src/commands/RoutesCommand.php index f0a1fed..25eef97 100644 --- a/src/commands/RoutesCommand.php +++ b/src/commands/RoutesCommand.php @@ -2,7 +2,6 @@ use Zizaco\Confide\Support\GenerateCommand; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; /** * This command dumps some routes at the end of the routes.php From 1c0ba481f3dfd0eada48d5c6e1e9dae8a909ed28 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 01:17:44 -0300 Subject: [PATCH 089/115] Added a separated lang file for informal Dutch --- src/lang/nl/confide.php | 70 +------------------------------------- src/lang/nl_NL/confide.php | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 69 deletions(-) create mode 100644 src/lang/nl_NL/confide.php diff --git a/src/lang/nl/confide.php b/src/lang/nl/confide.php index 5be0816..c239806 100644 --- a/src/lang/nl/confide.php +++ b/src/lang/nl/confide.php @@ -1,8 +1,7 @@ 'Gebruikersnaam', - 'password' => 'Wachtwoord', - 'password_confirmation' => 'Bevestig wachtwoord', - 'e_mail' => 'E-mail', - 'username_e_mail' => 'Gebruikersnaam of e-mailadres', - - 'signup' => array( - 'title' => 'Registreren', - 'desc' => 'Registreer een nieuw account', - 'confirmation_required' => 'Bevestiging vereist', - 'submit' => 'Maak nieuw account', - ), - - 'login' => array( - 'title' => 'Inloggen', - 'desc' => 'Vul je gegevens in', - 'forgot_password' => '(wachtwoord vergeten)', - 'remember' => 'Onthoud mij', - 'submit' => 'Inloggen', - ), - - 'forgot' => array( - 'title' => 'Wachtwoord vergeten', - 'submit' => 'Doorgaan', - ), - - 'alerts' => array( - 'account_created' => 'Je account is succesvol aangemaakt. Controleer je e-mailinbox voor instructies om je account the bevestigen.', - 'too_many_attempts' => 'Te veel pogingen. Probeer het over een enkele minuten nog eens.', - 'wrong_credentials' => 'Verkeerde gebruikersnaam, e-mailadres of wachtwoord.', - 'not_confirmed' => 'Je account is waarschijnlijk niet bevestigd. Controleer je e-mailinbox voor de bevestigingslink.', - 'confirmation' => 'Je account is bevestigd! Je kunt nu inloggen.', - 'wrong_confirmation' => 'Verkeerde bevestigingscode.', - 'password_forgot' => 'De informatie voor het opnieuw instellen van je wachtwoord is verstuurd naar je e-mailadres.', - 'wrong_password_forgot' => 'Gebruiker niet gevonden.', - 'password_reset' => 'Je wachtwoord is succesvol veranderd.', - 'wrong_password_reset' => 'Verkeerd wachtwoord. Probeer het nog eens.', - 'wrong_token' => 'Het token om je wachtwoord opnieuw in te stellen is niet geldig.', - 'duplicated_credentials' => 'De ingevulde gegevens zijn al in gebruik. Probeer het eens met andere gegevens.', - ), - - 'email' => array( - 'account_confirmation' => array( - 'subject' => 'Accountbevestiging', - 'greetings' => 'Hallo :name', - 'body' => 'Klik op de onderstaande link om je account te bevestigen.', - 'farewell' => 'Met vriendelijke groet', - ), - - 'password_reset' => array( - 'subject' => 'Wachtwoord opnieuw instellen', - 'greetings' => 'Hallo :name', - 'body' => 'Klik op de onderstaande link om je wachtwoord opnieuw in te stellen.', - 'farewell' => 'Met vriendelijke groet', - ), - ), - -); -*/ diff --git a/src/lang/nl_NL/confide.php b/src/lang/nl_NL/confide.php new file mode 100644 index 0000000..a7b70af --- /dev/null +++ b/src/lang/nl_NL/confide.php @@ -0,0 +1,66 @@ + 'Gebruikersnaam', + 'password' => 'Wachtwoord', + 'password_confirmation' => 'Bevestig wachtwoord', + 'e_mail' => 'E-mail', + 'username_e_mail' => 'Gebruikersnaam of e-mailadres', + + 'signup' => array( + 'title' => 'Registreren', + 'desc' => 'Registreer een nieuw account', + 'confirmation_required' => 'Bevestiging vereist', + 'submit' => 'Maak nieuw account', + ), + + 'login' => array( + 'title' => 'Inloggen', + 'desc' => 'Vul je gegevens in', + 'forgot_password' => '(wachtwoord vergeten)', + 'remember' => 'Onthoud mij', + 'submit' => 'Inloggen', + ), + + 'forgot' => array( + 'title' => 'Wachtwoord vergeten', + 'submit' => 'Doorgaan', + ), + + 'alerts' => array( + 'account_created' => 'Je account is succesvol aangemaakt. Controleer je e-mailinbox voor instructies om je account the bevestigen.', + 'too_many_attempts' => 'Te veel pogingen. Probeer het over een enkele minuten nog eens.', + 'wrong_credentials' => 'Verkeerde gebruikersnaam, e-mailadres of wachtwoord.', + 'not_confirmed' => 'Je account is waarschijnlijk niet bevestigd. Controleer je e-mailinbox voor de bevestigingslink.', + 'confirmation' => 'Je account is bevestigd! Je kunt nu inloggen.', + 'wrong_confirmation' => 'Verkeerde bevestigingscode.', + 'password_forgot' => 'De informatie voor het opnieuw instellen van je wachtwoord is verstuurd naar je e-mailadres.', + 'wrong_password_forgot' => 'Gebruiker niet gevonden.', + 'password_reset' => 'Je wachtwoord is succesvol veranderd.', + 'wrong_password_reset' => 'Verkeerd wachtwoord. Probeer het nog eens.', + 'wrong_token' => 'Het token om je wachtwoord opnieuw in te stellen is niet geldig.', + 'duplicated_credentials' => 'De ingevulde gegevens zijn al in gebruik. Probeer het eens met andere gegevens.', + ), + + 'email' => array( + 'account_confirmation' => array( + 'subject' => 'Accountbevestiging', + 'greetings' => 'Hallo :name', + 'body' => 'Klik op de onderstaande link om je account te bevestigen.', + 'farewell' => 'Met vriendelijke groet', + ), + + 'password_reset' => array( + 'subject' => 'Wachtwoord opnieuw instellen', + 'greetings' => 'Hallo :name', + 'body' => 'Klik op de onderstaande link om je wachtwoord opnieuw in te stellen.', + 'farewell' => 'Met vriendelijke groet', + ), + ), + +); From 479bdbeb14b541543a54bd68e7842cf414fce0ad Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 01:18:13 -0300 Subject: [PATCH 090/115] Added Scruntinizer badge to README file --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 15c88d6..3b6261e 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ![Confide Poster](https://dl.dropbox.com/u/12506137/libs_bundles/confide.png) [![Build Status](https://api.travis-ci.org/Zizaco/confide.png)](https://travis-ci.org/Zizaco/confide) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Zizaco/confide/badges/quality-score.png)](https://scrutinizer-ci.com/g/Zizaco/confide/) [![ProjectStatus](http://stillmaintained.com/Zizaco/confide.png)](http://stillmaintained.com/Zizaco/confide) [![Latest Stable Version](https://poser.pugx.org/zizaco/confide/v/stable.png)](https://packagist.org/packages/zizaco/confide) [![Total Downloads](https://poser.pugx.org/zizaco/confide/downloads.png)](https://packagist.org/packages/zizaco/confide) From b005360db2e4d7ad23e787a974f29e23fc62a3c6 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 01:19:11 -0300 Subject: [PATCH 091/115] Tweaked php tag in templates in order to avoid mistakes in interpreters --- src/views/generators/controller.blade.php | 2 +- src/views/generators/repository.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/generators/controller.blade.php b/src/views/generators/controller.blade.php index b4bb403..18f6276 100644 --- a/src/views/generators/controller.blade.php +++ b/src/views/generators/controller.blade.php @@ -1,4 +1,4 @@ -{{ ' @if ($namespace) diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index 1dcda72..dc289a1 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -1,4 +1,4 @@ -{{ ' @if (strstr($model, '\\')) From 7e8938e60b7b0374b682cb80318048d1dfe4ed02 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 13 Jul 2014 09:52:34 +0100 Subject: [PATCH 092/115] Added branch alias --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index 2ddeec0..d13b6a2 100644 --- a/composer.json +++ b/composer.json @@ -34,5 +34,10 @@ "psr-0": { "Zizaco\\Confide": "src/" } + }, + "extra": { + "branch-alias": { + "dev-huge-update": "4.0-dev" + } } } From 5c9c96dd40a8470eb5073631e5d8e907abd4317c Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 13 Jul 2014 09:54:14 +0100 Subject: [PATCH 093/115] Updated dev-dependencies --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2ddeec0..70d85e3 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "illuminate/support": "~4.2" }, "require-dev": { - "mockery/mockery": "0.9.*@dev", + "phpunit/phpunit": "~4.0", + "mockery/mockery": "~0.8", "illuminate/database": "~4.2", "illuminate/auth": "~4.2", "illuminate/console": "~4.2" From e39125eab03458cf8cd2be909318cc8804a44c68 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 13 Jul 2014 09:56:48 +0100 Subject: [PATCH 094/115] Update .travis.yml --- .travis.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a6ef3e..dd8d548 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,13 @@ language: php php: - 5.4 + - 5.5 + - 5.6 + - hhvm before_script: - - curl -s http://getcomposer.org/installer | php - - php composer.phar install --dev + - travis_retry composer self-update + - travis_retry composer install --no-interaction --prefer-source --dev -script: phpunit +script: + - vendor/bin/phpunit --verbose From 5d13a4299c98cc9e84b982145d85a684148b0ee8 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 16:01:53 -0300 Subject: [PATCH 095/115] Added coveralls configuration and support package in order to track the code coverage of the project --- .coveralls.yml | 9 +++++++++ .travis.yml | 3 +++ composer.json | 7 ++++--- phpunit.xml.dist | 27 +++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 .coveralls.yml create mode 100644 phpunit.xml.dist diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..c1bdfd1 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,9 @@ +# .coveralls.yml example configuration + +# service name +service_name: travis-ci + +# for php-coveralls +src_dir: src +coverage_clover: build/logs/clover.xml +json_path: build/logs/coveralls-upload.json diff --git a/.travis.yml b/.travis.yml index dd8d548..1a04340 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,3 +12,6 @@ before_script: script: - vendor/bin/phpunit --verbose + +after_script: + - php vendor/bin/coveralls -v diff --git a/composer.json b/composer.json index e558e9f..cd0f747 100644 --- a/composer.json +++ b/composer.json @@ -18,11 +18,12 @@ "illuminate/support": "~4.2" }, "require-dev": { - "phpunit/phpunit": "~4.0", - "mockery/mockery": "~0.8", "illuminate/database": "~4.2", "illuminate/auth": "~4.2", - "illuminate/console": "~4.2" + "illuminate/console": "~4.2", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", + "mockery/mockery": "~0.8" }, "suggest": { "zizaco/entrust":"add Role-based Permissions to Laravel 4" diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..f778f56 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,27 @@ + + + + + ./src/Zizaco + ./src/commands + + + + + ./tests/ + + + + + + From fd37c995ccd9ed1409ad2ffc242a26333857b70d Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 16:27:51 -0300 Subject: [PATCH 096/115] Tweaked .travis.yml and added coveralls badge to README.md --- .travis.yml | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1a04340..2d81aea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ before_script: - travis_retry composer install --no-interaction --prefer-source --dev script: + - mkdir -p build/logs - vendor/bin/phpunit --verbose after_script: diff --git a/README.md b/README.md index 3b6261e..b633c37 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ![Confide Poster](https://dl.dropbox.com/u/12506137/libs_bundles/confide.png) [![Build Status](https://api.travis-ci.org/Zizaco/confide.png)](https://travis-ci.org/Zizaco/confide) +[![Coverage Status](https://coveralls.io/repos/Zizaco/confide/badge.png?branch=huge-update)](https://coveralls.io/r/Zizaco/confide?branch=huge-update) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Zizaco/confide/badges/quality-score.png)](https://scrutinizer-ci.com/g/Zizaco/confide/) [![ProjectStatus](http://stillmaintained.com/Zizaco/confide.png)](http://stillmaintained.com/Zizaco/confide) [![Latest Stable Version](https://poser.pugx.org/zizaco/confide/v/stable.png)](https://packagist.org/packages/zizaco/confide) From 27df8390c9f1197f4508e2f644af8bf341b65aed Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 16:41:16 -0300 Subject: [PATCH 097/115] Updated mockery to ~0.9 to fix preg_match() error in Mockery/Expectation.php:291 --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index cd0f747..d795c9c 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "illuminate/console": "~4.2", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", - "mockery/mockery": "~0.8" + "mockery/mockery": "~0.9" }, "suggest": { "zizaco/entrust":"add Role-based Permissions to Laravel 4" @@ -41,5 +41,6 @@ "branch-alias": { "dev-huge-update": "4.0-dev" } - } + }, + "minimum-stability": "dev" } From 35e9a19733f522243a93198dc18a4cb8ca72cb50 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 16:44:50 -0300 Subject: [PATCH 098/115] Tweaked .travis.yml to use phpunit.xml.dist in order produce the clover file --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2d81aea..11ac310 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ before_script: script: - mkdir -p build/logs - - vendor/bin/phpunit --verbose + - vendor/bin/phpunit -c phpunit.xml.dist --verbose after_script: - php vendor/bin/coveralls -v From 91ce84efc8d6f996ff13eef0ed6b8154d0460c8a Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 13 Jul 2014 19:05:23 -0300 Subject: [PATCH 099/115] Added unit tests for methods that were not covered --- .../Confide/CacheLoginThrottleService.php | 2 + src/Zizaco/Confide/EloquentRepository.php | 1 + .../Confide/CacheLoginThrottleServiceTest.php | 2 +- tests/Zizaco/Confide/ConfideTest.php | 113 ++++++++++++------ tests/Zizaco/Confide/ConfideUserTest.php | 96 +++++++++++++-- .../Confide/EloquentPasswordServiceTest.php | 64 ++++++++++ .../Zizaco/Confide/EloquentRepositoryTest.php | 27 +++++ 7 files changed, 258 insertions(+), 47 deletions(-) diff --git a/src/Zizaco/Confide/CacheLoginThrottleService.php b/src/Zizaco/Confide/CacheLoginThrottleService.php index 4db0f03..6f6ac02 100644 --- a/src/Zizaco/Confide/CacheLoginThrottleService.php +++ b/src/Zizaco/Confide/CacheLoginThrottleService.php @@ -76,6 +76,8 @@ protected function parseIdentity($identity) unset($identity['remember']); $identity = serialize($identity); } + + return $identity; } /** diff --git a/src/Zizaco/Confide/EloquentRepository.php b/src/Zizaco/Confide/EloquentRepository.php index e5c4766..4eebeb2 100644 --- a/src/Zizaco/Confide/EloquentRepository.php +++ b/src/Zizaco/Confide/EloquentRepository.php @@ -138,6 +138,7 @@ public function confirmByCode($code) protected function confirmUser($user) { $user->confirmed = true; + return $user->save(); } } diff --git a/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php b/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php index 46f6b5e..213c5b8 100644 --- a/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php +++ b/tests/Zizaco/Confide/CacheLoginThrottleServiceTest.php @@ -126,7 +126,7 @@ public function testShouldCheckIsThrottledOnNonThrottled() $this->assertFalse($throttleService->isThrottled($identity)); } - public function parseIdentity() + public function testShouldParseIdentity() { /* |------------------------------------------------------------ diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index 418946f..22d122b 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -23,8 +23,8 @@ public function testShouldGetModel() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); $modelInstance = m::mock('_mockedUser'); @@ -54,8 +54,8 @@ public function testShouldGetUser() */ $app = []; $app['auth'] = m::mock('Auth'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); $user = m::mock('_mockedUser'); @@ -84,8 +84,8 @@ public function testShouldConfirm() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); $modelInstance = m::mock('_mockedUser'); @@ -108,6 +108,51 @@ public function testShouldConfirm() $this->assertTrue($confide->confirm($code)); } + public function testShouldGetUserByEmailOrUsername() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + $confide = m::mock( + 'Zizaco\Confide\Confide'. + '[extractIdentityFromArray]', + [$repo, $passService, $loginThrottler, $app] + ); + $confide->shouldAllowMockingProtectedMethods(); + + $identity = ['email'=>'johndoe@example.com']; + $user = m::mock('_mockedUser'); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('extractIdentityFromArray') + ->once()->with($identity) + ->andReturn($identity['email']); + + $repo->shouldReceive('getUserByEmailOrUsername') + ->once()->with('johndoe@example.com') + ->andReturn($user); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + $user, + $confide->getUserByEmailOrUsername($identity) + ); + } + public function testShouldDoLogAttempt() { /* @@ -118,8 +163,8 @@ public function testShouldDoLogAttempt() $app = []; $app['auth'] = m::mock('Auth'); $app['hash'] = m::mock('Hash'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -186,8 +231,8 @@ public function testShouldFailLogAttemptIfThrottled() $app = []; $app['auth'] = m::mock('Auth'); $app['hash'] = m::mock('Hash'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -242,8 +287,8 @@ public function testShouldFailLogAttemptIfUserNotFound() $app = []; $app['auth'] = m::mock('Auth'); $app['hash'] = m::mock('Hash'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -302,8 +347,8 @@ public function testShouldFailLogAttemptIfUserNotConfirmed() $app = []; $app['auth'] = m::mock('Auth'); $app['hash'] = m::mock('Hash'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -362,8 +407,8 @@ public function testShouldFailLogAttemptIfWrongPass() $app = []; $app['auth'] = m::mock('Auth'); $app['hash'] = m::mock('Hash'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -426,8 +471,8 @@ public function testShouldDoLogAttemptIfNotConfirmed() $app = []; $app['auth'] = m::mock('Auth'); $app['hash'] = m::mock('Hash'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -492,8 +537,8 @@ public function testShouldExtractRememberFromArray() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -537,8 +582,8 @@ public function testShouldExtractIdentityFromArray() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -593,8 +638,8 @@ public function testShouldDoLoginThrottling() */ $config = m::mock('Config'); $app = ['config'=>$config]; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -644,8 +689,8 @@ public function testIsThrottled() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = m::mock( @@ -683,8 +728,8 @@ public function testShouldForgotPassword() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); @@ -729,8 +774,8 @@ public function testShouldGetUserByPasswordResetToken() |------------------------------------------------------------ */ $app = []; - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); @@ -778,8 +823,8 @@ public function testShouldDoLogout() */ $app = []; $app['auth'] = m::mock('Auth'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); $user = m::mock('_mockedUser'); @@ -810,8 +855,8 @@ public function testShouldMakeViews() $app = []; $app['config'] = m::mock('Config'); $app['view'] = m::mock('ViewEnv'); - $repo = m::mock('Zizaco\Confide\RepositoryInterface'); - $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); $confide = new Confide($repo, $passService, $loginThrottler, $app); $token = '12345'; diff --git a/tests/Zizaco/Confide/ConfideUserTest.php b/tests/Zizaco/Confide/ConfideUserTest.php index 371a27a..785df8c 100644 --- a/tests/Zizaco/Confide/ConfideUserTest.php +++ b/tests/Zizaco/Confide/ConfideUserTest.php @@ -182,6 +182,37 @@ public function testShouldNotSaveInvalid() $this->assertFalse($user->save()); } + public function testShouldGetErrors() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new _ConfideUserStub; + $newMessageBag = m::mock('Illuminate\Support\MessageBag'); + $existentMessageBag = m::mock('Illuminate\Support\MessageBag'); + $user->errors = $existentMessageBag; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + App::shouldReceive('make') + ->once()->with('Illuminate\Support\MessageBag') + ->andReturn($newMessageBag); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals($existentMessageBag, $user->errors()); + $user->errors = null; + $this->assertEquals($newMessageBag, $user->errors()); + } + public function testShouldGetAuthIdentifier() { /* @@ -215,7 +246,7 @@ public function testShouldGetAuthPassword() | Set |------------------------------------------------------------ */ - $user = m::mock('Zizaco\Confide\_ConfideUserStub[getKey]'); + $user = new _ConfideUserStub; $user->password = '1234'; /* @@ -226,7 +257,7 @@ public function testShouldGetAuthPassword() $this->assertEquals('1234', $user->getAuthPassword()); } - public function testShouldGetErrors() + public function testShouldGetRememberToken() { /* |------------------------------------------------------------ @@ -234,27 +265,68 @@ public function testShouldGetErrors() |------------------------------------------------------------ */ $user = new _ConfideUserStub; - $newMessageBag = m::mock('Illuminate\Support\MessageBag'); - $existentMessageBag = m::mock('Illuminate\Support\MessageBag'); - $user->errors = $existentMessageBag; + $user->remember_token = '1234'; /* |------------------------------------------------------------ - | Expectation + | Assertion |------------------------------------------------------------ */ - App::shouldReceive('make') - ->once()->with('Illuminate\Support\MessageBag') - ->andReturn($newMessageBag); + $this->assertEquals('1234', $user->getRememberToken()); + } + + public function testShouldSetRememberToken() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new _ConfideUserStub; + $user->remember_token = null; /* |------------------------------------------------------------ | Assertion |------------------------------------------------------------ */ - $this->assertEquals($existentMessageBag, $user->errors()); - $user->errors = null; - $this->assertEquals($newMessageBag, $user->errors()); + $user->setRememberToken('123'); + $this->assertEquals('123', $user->remember_token); + } + + public function testShouldGetRememberTokenName() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new _ConfideUserStub; + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals('remember_token', $user->getRememberTokenName()); + } + + public function testShouldGetReminderEmail() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = new _ConfideUserStub; + $user->email = 'someone@somewhere.com'; + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals('someone@somewhere.com', $user->getReminderEmail()); } } diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index 4064c42..de49c18 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -222,4 +222,68 @@ public function testShouldUnwrapEmail() $this->assertEquals($email, $passService->unwrapEmail($emailArray)); $this->assertEquals($email, $passService->unwrapEmail($emailObject)); } + + public function testShouldSendEmail() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $passService = m::mock('Zizaco\Confide\EloquentPasswordService[sendEmail]'); + $passService->shouldAllowMockingProtectedMethods(); + + $mailer = m::mock('Mailer'); + $config = m::mock('Config'); + $translator = m::mock('Translator'); + $passService->app['mailer'] = $mailer; + $passService->app['config'] = $config; + $passService->app['translator'] = $translator; + + $token = '123'; + $user = m::mock('UserWithEmail'); + $user->email = 'someone@somewhere.com'; + $user->username = 'Someone'; + + $test = $this; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $passService->shouldReceive('sendEmail') + ->passthru(); + + $mailer->shouldReceive('send') + ->once()->with('view.name', ['user'=>$user, 'token'=>$token], m::any()) + ->andReturnUsing(function($a,$b,$closure) use ($test, $user) { + $message = m::mock('Message'); + + $message->shouldReceive('to') + ->once()->with($user->email, $user->username) + ->andReturn($message); + + $message->shouldReceive('subject') + ->once()->with('the-email-subject') + ->andReturn($message); + + $closure($message); + }); + + $translator->shouldReceive('get') + ->once()->with('confide::confide.email.password_reset.subject') + ->andReturn('the-email-subject'); + + $config->shouldReceive('get') + ->once()->with('confide::email_reset_password') + ->andReturn('view.name'); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $passService->sendEmail($user, $token); + } } diff --git a/tests/Zizaco/Confide/EloquentRepositoryTest.php b/tests/Zizaco/Confide/EloquentRepositoryTest.php index 125e7d4..5991ad8 100644 --- a/tests/Zizaco/Confide/EloquentRepositoryTest.php +++ b/tests/Zizaco/Confide/EloquentRepositoryTest.php @@ -239,4 +239,31 @@ public function testShouldConfirmByCode() $this->assertTrue($repo->confirmByCode($confirmCode)); $this->assertFalse($repo->confirmByCode($wrongConfirmCode)); } + + public function testShouldConfirmUser() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $user = m::mock('_mockedUser'); + $repo = m::mock('Zizaco\Confide\EloquentRepository[confirmUser]',[]); + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $user->shouldReceive('save') + ->once() + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($repo->confirmUser($user)); + } } From f7cf607e14cc987a2f172098d68ad04220290c0a Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 13 Jul 2014 23:14:32 +0100 Subject: [PATCH 100/115] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d795c9c..51d53ed 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "illuminate/auth": "~4.2", "illuminate/console": "~4.2", "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "dev-master", + "satooshi/php-coveralls": "~0.7", "mockery/mockery": "~0.9" }, "suggest": { From 19f3eb775697114bef7552f31d89cd5078443939 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Mon, 14 Jul 2014 20:43:18 -0300 Subject: [PATCH 101/115] Added info about how to use a custom validator in REAMDE.md --- README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b633c37..d6ba323 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,28 @@ Then edit the view names in `app/config/packages/zizaco/confide/config.php`. #### Custom user validation -To save an user that use the `Zizaco\Confide\ConfideUser` trait you'll need to make sure the `isValid` method is returning true. Take a look at the `Zizaco\Confide\UserValidator` class in order to understand the "default" user validation. Feel free to replace the validator by your own class and rules. +You can implement your own validator by creating a class that implements the `UserValidatorInterface` and registering that class as *"confide.user_validator"*. + +For example, create your custom validator class: + + + // app/models/MyOwnValidator.php + class MyOwnValidator implements UserValidatorInterface { + + public function validate(ConfideUserInterface $user) + { + unset($user->password_confirmation); + return true; // If the user valid + } + } + +Then register it in IoC container as *"confide.user_validator"* + + // app/start/global.php + ... + App::bind('confide.user_validator', 'MyOwnValidator'); + +Also, don't forget that your validator should unset the 'password_confirmation' attribute of the user before saving it. #### Passing additional information to the "make" methods From 7c3b0e4435449627dffb6483ae671a45982f0c86 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Tue, 15 Jul 2014 23:33:36 -0300 Subject: [PATCH 102/115] Removed curly brackets usage around opening php tag in order to avoid rendering problem --- src/views/generators/controller.blade.php | 2 +- src/views/generators/migration.blade.php | 2 +- src/views/generators/repository.blade.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/generators/controller.blade.php b/src/views/generators/controller.blade.php index 18f6276..4108c29 100644 --- a/src/views/generators/controller.blade.php +++ b/src/views/generators/controller.blade.php @@ -1,4 +1,4 @@ -{{ '<'.'?php' }}{{ $namespace ? ' namespace '.$namespace.';' : '' }} +{{ $namespace ? ' namespace '.$namespace.';' : '' }} @if ($namespace) diff --git a/src/views/generators/migration.blade.php b/src/views/generators/migration.blade.php index d351884..1fa6071 100644 --- a/src/views/generators/migration.blade.php +++ b/src/views/generators/migration.blade.php @@ -1,4 +1,4 @@ -{{ '<'.'?php' }} + use Illuminate\Database\Migrations\Migration; diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index dc289a1..d829921 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -1,4 +1,4 @@ -{{ '<'.'?php' }}{{ strstr($model, '\\') ? ' namespace '.substr($model, 0, -strlen(strrchr($model, '\\'))).';' : '' }} +{{ strstr($model, '\\') ? ' namespace '.substr($model, 0, -strlen(strrchr($model, '\\'))).';' : '' }} @if (strstr($model, '\\')) From a6c90f5fa4cf77f96c651ded563c05373605cad6 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Tue, 15 Jul 2014 23:42:39 -0300 Subject: [PATCH 103/115] Fixed bug of validating attributes when the password was in the Eloquent attribute --- src/Zizaco/Confide/UserValidator.php | 4 ++++ tests/Zizaco/Confide/UserValidatorTest.php | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 7a99ee0..5a04128 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -132,6 +132,10 @@ public function validateIsUnique(ConfideUserInterface $user) public function validateAttributes(ConfideUserInterface $user, $ruleset = 'create') { $attributes = $user->toArray(); + + // Force getting password since it may be hidden from array form + $attributes['password'] = $user->getAuthPassword(); + $rules = $this->rules[$ruleset]; $validator = App::make('validator') diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index ca07d75..45c426e 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -215,18 +215,33 @@ public function testShouldValidateAttributes() | Expectation |------------------------------------------------------------ */ + $userA->shouldReceive('toArray') ->andReturn(['username'=>'foo']); + // Password must be retrieved separately since it may + // be hidden from toArray method. + $userA->shouldReceive('getAuthPassword') + ->andReturn('secret'); + $userB->shouldReceive('toArray') ->andReturn(['username'=>'bar']); + $userB->shouldReceive('getAuthPassword') + ->andReturn('p@ss'); + $laravelValidator->shouldReceive('make') - ->with(['username'=>'foo'], $validator->rules['create']) + ->with( + ['username'=>'foo', 'password'=>'secret'], + $validator->rules['create'] + ) ->once()->andReturn($laravelValidator); $laravelValidator->shouldReceive('make') - ->with(['username'=>'bar'], $validator->rules['create']) + ->with( + ['username'=>'bar', 'password'=>'p@ss'], + $validator->rules['create'] + ) ->once()->andReturn($laravelValidator); $laravelValidator->shouldReceive('fails') From db3b5ce991aaa89b07b62d515f66d600da12d186 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Jul 2014 21:03:34 -0300 Subject: [PATCH 104/115] Updated EloquentPasswordService in order to use the user model attribute in order to know in which database the queries will be performed --- .../Confide/EloquentPasswordService.php | 7 +++- .../Confide/EloquentPasswordServiceTest.php | 37 ++++++++++++------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 0795ae3..813981f 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -48,7 +48,7 @@ public function requestChangePassword(RemindableInterface $user) ); $this->app['db'] - ->connection() + ->connection($user->connection) ->table('password_reminders') ->insert($values); @@ -65,8 +65,11 @@ public function requestChangePassword(RemindableInterface $user) */ public function getEmailByToken($token) { + $connection = $this->app['confide.repository'] + ->model()->connection; + $email = $this->app['db'] - ->connection() + ->connection($connection) ->table('password_reminders') ->select('email')->where('token','=',$token) ->first(); diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index de49c18..e976646 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -36,6 +36,7 @@ public function testSouldRequestChangePassword() $generatedToken = '123456789'; $user = m::mock('Illuminate\Auth\Reminders\RemindableInterface'); + $user->connection = 'db_name'; $passService = m::mock('Zizaco\Confide\EloquentPasswordService[generateToken,sendEmail]',[]); $db = m::mock('connection'); @@ -60,17 +61,17 @@ public function testSouldRequestChangePassword() // The email containing the reset link should be sent $passService->shouldReceive('sendEmail') - ->once() - ->andReturn($user, $generatedToken); + ->once()->with($user, $generatedToken); // Mocks DB in order to check for the following query: - // DB::table('password_reminders')->insert(array( - // 'email'=> $email, - // 'token'=> $token, - // 'created_at'=> new \DateTime - //)); + // DB::connection('db_name') + // ->table('password_reminders')->insert(array( + // 'email'=> $email, + // 'token'=> $token, + // 'created_at'=> new \DateTime + // )); $db->shouldReceive('connection') - ->once() + ->once()->with($user->connection) ->andReturn( $db ); $db->shouldReceive('table') @@ -105,19 +106,26 @@ public function testShouldGetEmailByToken() | Set |------------------------------------------------------------ */ - $userEmail = 'someone@somewhere.com'; - $token = '123456789'; + $userEmail = 'someone@somewhere.com'; + $token = '123456789'; $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); - $passService->shouldAllowMockingProtectedMethods(); - $db = m::mock('connection'); + $db = m::mock('connection'); + $repository = m::mock('Zizaco\Confide\RepositoryInterface'); + $userModel = m::mock('Zizaco\Confide\ConfideUserInterface'); + $passService->shouldAllowMockingProtectedMethods(); + $userModel->connection = 'db_name'; $passService->app['db'] = $db; + $passService->app['confide.repository'] = $repository; /* |------------------------------------------------------------ | Expectation |------------------------------------------------------------ */ + $repository->shouldReceive('model') + ->andReturn($userModel); + $passService->shouldReceive('getEmailByToken') ->passthru(); @@ -126,12 +134,13 @@ public function testShouldGetEmailByToken() ->andReturn($userEmail); // Mocks DB in order to check for the following query: - // DB::table('password_reminders') + // DB::connection('db_name') + // ->table('password_reminders') // ->select('email') // ->where('token','=',$token) // ->first(); $db->shouldReceive('connection') - ->once() + ->once()->with($userModel->connection) ->andReturn( $db ); $db->shouldReceive('table') From 59109e7e90d3c4aa9900c051eb59c1c0828a31c4 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Jul 2014 22:20:52 -0300 Subject: [PATCH 105/115] Added destroyToken method to PasswordService in order to be able to remove used 'password_reminder' records --- .../Confide/EloquentPasswordService.php | 20 ++++++ .../Confide/PasswordServiceInterface.php | 9 +++ .../Confide/EloquentPasswordServiceTest.php | 61 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 813981f..512f128 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -79,6 +79,26 @@ public function getEmailByToken($token) return $email; } + /** + * Delete the record of the given token from database + * + * @param string $token + * @return boolean Success + */ + public function destroyToken($token) + { + $connection = $this->app['confide.repository'] + ->model()->connection; + + $affected = $this->app['db'] + ->connection($connection) + ->table('password_reminders') + ->where('token','=',$token) + ->delete(); + + return $affected > 0; + } + /** * Generates a random password change token * diff --git a/src/Zizaco/Confide/PasswordServiceInterface.php b/src/Zizaco/Confide/PasswordServiceInterface.php index 3e477dc..85cbed6 100644 --- a/src/Zizaco/Confide/PasswordServiceInterface.php +++ b/src/Zizaco/Confide/PasswordServiceInterface.php @@ -23,8 +23,17 @@ public function requestChangePassword(RemindableInterface $user); /** * Returns the email associated with the given reset * password token + * * @param string $token * @return string Email */ public function getEmailByToken($token); + + /** + * Delete the record of the given token from database + * + * @param string $token + * @return boolean Success + */ + public function destroyToken($token); } diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index e976646..4965a27 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -173,6 +173,67 @@ public function testShouldGetEmailByToken() ); } + public function testShouldDestroyToken() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $token = '123456789'; + $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); + $db = m::mock('connection'); + $repository = m::mock('Zizaco\Confide\RepositoryInterface'); + $userModel = m::mock('Zizaco\Confide\ConfideUserInterface'); + + $userModel->connection = 'db_name'; + $passService->app['db'] = $db; + $passService->app['confide.repository'] = $repository; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $repository->shouldReceive('model') + ->andReturn($userModel); + + $passService->shouldReceive('destroyToken') + ->passthru(); + + // Mocks DB in order to check for the following query: + // DB::connection('db_name') + // ->table('password_reminders') + // ->where('token','=',$token) + // ->delete(); + $db->shouldReceive('connection') + ->once()->with($userModel->connection) + ->andReturn( $db ); + + $db->shouldReceive('table') + ->with('password_reminders') + ->andReturn( $db ) + ->once(); + + $db->shouldReceive('where') + ->with('token', '=', $token) + ->andReturn( $db ) + ->once(); + + $db->shouldReceive('delete') + ->once() + ->andReturn(1); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue( + $passService->destroyToken($token) + ); + } + public function testShouldGenerateToken() { /* From b060bd453dcaa6c4cfa09ca10dad8ce432b1ab36 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Jul 2014 22:25:15 -0300 Subject: [PATCH 106/115] Added destroyForgotPasswordToken to Confide main class in order to properly access the PasswordService destroyToken method --- src/Zizaco/Confide/Confide.php | 12 +++++++ src/views/generators/repository.blade.php | 4 +++ tests/Zizaco/Confide/ConfideTest.php | 39 +++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/Zizaco/Confide/Confide.php b/src/Zizaco/Confide/Confide.php index 8214c6e..a91b60e 100644 --- a/src/Zizaco/Confide/Confide.php +++ b/src/Zizaco/Confide/Confide.php @@ -229,6 +229,18 @@ public function forgotPassword($email) return false; } + /** + * Delete the record of the given token from 'password_reminders' + * table. + * + * @param string $token Token retrieved from a forgotPassword + * @return boolean Success + */ + public function destroyForgotPasswordToken($token) + { + return $this->passService->destroyToken($token); + } + /** * Returns a user that corresponds to the given reset * password token or false if there is no user with the diff --git a/src/views/generators/repository.blade.php b/src/views/generators/repository.blade.php index d829921..de34ecb 100644 --- a/src/views/generators/repository.blade.php +++ b/src/views/generators/repository.blade.php @@ -98,6 +98,10 @@ public function resetPassword($input) $result = $this->save($user); } + // If result is positive, destroy token + if ($result) + Confide::destroyForgotPasswordToken($input['token']); + return $result; } diff --git a/tests/Zizaco/Confide/ConfideTest.php b/tests/Zizaco/Confide/ConfideTest.php index 22d122b..0b0aab7 100644 --- a/tests/Zizaco/Confide/ConfideTest.php +++ b/tests/Zizaco/Confide/ConfideTest.php @@ -766,6 +766,45 @@ public function testShouldForgotPassword() $this->assertFalse($confide->forgotPassword('wrong@somewhere.com')); } + public function testShouldDestroyForgotPasswordToken() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $app = []; + $repo = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\PasswordServiceInterface'); + $loginThrottler = m::mock('Zizaco\Confide\LoginThrottleServiceInterface'); + + $confide = m::mock( + 'Zizaco\Confide\Confide[destroyForgotPasswordToken]', + [$repo, $passService, $loginThrottler, $app] + ); + + $token = '123456789'; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $confide->shouldReceive('destroyForgotPasswordToken') + ->passthru(); + + $passService->shouldReceive('destroyToken') + ->once()->with($token) + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertTrue($confide->destroyForgotPasswordToken($token)); + } + public function testShouldGetUserByPasswordResetToken() { /* From e0dc5cf48b89c998f348360cdea350e379ba5ed1 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Jul 2014 22:58:51 -0300 Subject: [PATCH 107/115] Updated EloquentPasswordService in order to retrieve connection name from user model using 'getConnectionName' --- .../Confide/EloquentPasswordService.php | 21 ++++-- .../Confide/EloquentPasswordServiceTest.php | 70 ++++++++++++++----- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index 512f128..c129c4b 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -48,7 +48,7 @@ public function requestChangePassword(RemindableInterface $user) ); $this->app['db'] - ->connection($user->connection) + ->connection($user->getConnectionName()) ->table('password_reminders') ->insert($values); @@ -65,8 +65,7 @@ public function requestChangePassword(RemindableInterface $user) */ public function getEmailByToken($token) { - $connection = $this->app['confide.repository'] - ->model()->connection; + $connection = $this->getConnection(); $email = $this->app['db'] ->connection($connection) @@ -87,8 +86,7 @@ public function getEmailByToken($token) */ public function destroyToken($token) { - $connection = $this->app['confide.repository'] - ->model()->connection; + $connection = $this->getConnection(); $affected = $this->app['db'] ->connection($connection) @@ -99,6 +97,19 @@ public function destroyToken($token) return $affected > 0; } + /** + * Returns a possible custom connection that may has being used + * for the user model. If null is returned by this method than + * the default connection is going to be used. + * + * @return string Original $connection value of the user model. + */ + protected function getConnection() + { + return $this->app['confide.repository'] + ->model()->getConnectionName(); + } + /** * Generates a random password change token * diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index 4965a27..443d949 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -36,7 +36,6 @@ public function testSouldRequestChangePassword() $generatedToken = '123456789'; $user = m::mock('Illuminate\Auth\Reminders\RemindableInterface'); - $user->connection = 'db_name'; $passService = m::mock('Zizaco\Confide\EloquentPasswordService[generateToken,sendEmail]',[]); $db = m::mock('connection'); @@ -54,6 +53,10 @@ public function testSouldRequestChangePassword() $user->shouldReceive('getReminderEmail') ->andReturn($userEmail); + // Retrieve the connection name that is being used in the user model + $user->shouldReceive('getConnectionName') + ->andReturn('db_name'); + // The PasswordService generate token method is the responsible // for generating tokens $passService->shouldReceive('generateToken') @@ -71,7 +74,7 @@ public function testSouldRequestChangePassword() // 'created_at'=> new \DateTime // )); $db->shouldReceive('connection') - ->once()->with($user->connection) + ->once()->with('db_name') ->andReturn( $db ); $db->shouldReceive('table') @@ -110,25 +113,22 @@ public function testShouldGetEmailByToken() $token = '123456789'; $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); $db = m::mock('connection'); - $repository = m::mock('Zizaco\Confide\RepositoryInterface'); $userModel = m::mock('Zizaco\Confide\ConfideUserInterface'); $passService->shouldAllowMockingProtectedMethods(); - $userModel->connection = 'db_name'; $passService->app['db'] = $db; - $passService->app['confide.repository'] = $repository; /* |------------------------------------------------------------ | Expectation |------------------------------------------------------------ */ - $repository->shouldReceive('model') - ->andReturn($userModel); - $passService->shouldReceive('getEmailByToken') ->passthru(); + $passService->shouldReceive('getConnection') + ->once()->andReturn('db_name'); + $passService->shouldReceive('unwrapEmail') ->once()->with(['email'=>$userEmail]) ->andReturn($userEmail); @@ -140,7 +140,7 @@ public function testShouldGetEmailByToken() // ->where('token','=',$token) // ->first(); $db->shouldReceive('connection') - ->once()->with($userModel->connection) + ->once()->with('db_name') ->andReturn( $db ); $db->shouldReceive('table') @@ -183,31 +183,28 @@ public function testShouldDestroyToken() $token = '123456789'; $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); $db = m::mock('connection'); - $repository = m::mock('Zizaco\Confide\RepositoryInterface'); - $userModel = m::mock('Zizaco\Confide\ConfideUserInterface'); - $userModel->connection = 'db_name'; + $passService->shouldAllowMockingProtectedMethods(); $passService->app['db'] = $db; - $passService->app['confide.repository'] = $repository; /* |------------------------------------------------------------ | Expectation |------------------------------------------------------------ */ - $repository->shouldReceive('model') - ->andReturn($userModel); - $passService->shouldReceive('destroyToken') ->passthru(); + $passService->shouldReceive('getConnection') + ->once()->andReturn('db_name'); + // Mocks DB in order to check for the following query: // DB::connection('db_name') // ->table('password_reminders') // ->where('token','=',$token) // ->delete(); $db->shouldReceive('connection') - ->once()->with($userModel->connection) + ->once()->with('db_name') ->andReturn( $db ); $db->shouldReceive('table') @@ -234,6 +231,45 @@ public function testShouldDestroyToken() ); } + public function testShouldGetConnection() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $repository = m::mock('Zizaco\Confide\RepositoryInterface'); + $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); + $modelInstance = m::mock('Zizaco\Confide\ConfideUserInterface'); + + $passService->shouldAllowMockingProtectedMethods(); + $passService->app['confide.repository'] = $repository; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $passService->shouldReceive('getConnection') + ->passthru(); + + $repository->shouldReceive('model') + ->once()->andReturn($modelInstance); + + $modelInstance->shouldReceive('getConnectionName') + ->once()->andReturn('db_name'); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + 'db_name', + $passService->getConnection() + ); + } + public function testShouldGenerateToken() { /* From 7876f0a4c760cb00a38c5474931e8df29d69fb1e Mon Sep 17 00:00:00 2001 From: Zizaco Date: Wed, 16 Jul 2014 23:33:25 -0300 Subject: [PATCH 108/115] Updated EloquentPasswordService::getEmailByToken in order to use an oldest valid date when querying for 'password_reminders'. This way a password_reminder will expire --- .../Confide/EloquentPasswordService.php | 26 ++++++++- .../Confide/EloquentPasswordServiceTest.php | 56 ++++++++++++++++++- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index c129c4b..b0dc3a2 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -70,7 +70,9 @@ public function getEmailByToken($token) $email = $this->app['db'] ->connection($connection) ->table('password_reminders') - ->select('email')->where('token','=',$token) + ->select('email') + ->where('token','=',$token) + ->where('created_at','>=',$this->getOldestValidDate()) ->first(); $email = $this->unwrapEmail($email); @@ -140,8 +142,9 @@ protected function unwrapEmail($email) } /** - * Sends an email containing the reset password link with the given token to - * the user + * Sends an email containing the reset password link with the + * given token to the user + * * @param RemindableInterface $user An existent user * @param string $token Password reset token * @return void @@ -157,4 +160,21 @@ protected function sendEmail($user, $token) ->subject($lang->get('confide::confide.email.password_reset.subject')); }); } + + /** + * Returns a date to limit the acceptable password reset + * requests. + * + * @return string 'Y-m-d H:i:s' formated string + */ + protected function getOldestValidDate() + { + // Instantiate a carbon object (that is a dependency of + // 'illuminate/database') + $carbon = $this->app['Carbon\Carbon']; + + return $carbon->now() + ->subHours(7) + ->toDateTimeString(); + } } diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index 443d949..7366bba 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -109,8 +109,9 @@ public function testShouldGetEmailByToken() | Set |------------------------------------------------------------ */ - $userEmail = 'someone@somewhere.com'; - $token = '123456789'; + $userEmail = 'someone@somewhere.com'; + $token = '123456789'; + $oldestValidDate = '2014-07-16 22:20:26'; $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); $db = m::mock('connection'); $userModel = m::mock('Zizaco\Confide\ConfideUserInterface'); @@ -129,6 +130,9 @@ public function testShouldGetEmailByToken() $passService->shouldReceive('getConnection') ->once()->andReturn('db_name'); + $passService->shouldReceive('getOldestValidDate') + ->once()->andReturn($oldestValidDate); + $passService->shouldReceive('unwrapEmail') ->once()->with(['email'=>$userEmail]) ->andReturn($userEmail); @@ -158,6 +162,11 @@ public function testShouldGetEmailByToken() ->andReturn( $db ) ->once(); + $db->shouldReceive('where') + ->with('created_at', '>=', $oldestValidDate) + ->andReturn( $db ) + ->once(); + $db->shouldReceive('first') ->once() ->andReturn(['email' => $userEmail]); @@ -392,4 +401,47 @@ public function testShouldSendEmail() */ $passService->sendEmail($user, $token); } + + public function testShouldGetOldestValidDate() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $oldestValidDate = '2014-07-16 22:20:26'; + $carbon = m::mock('Carbon\Carbon'); + $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); + + $passService->shouldAllowMockingProtectedMethods(); + $passService->app['Carbon\Carbon'] = $carbon; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + $passService->shouldReceive('getOldestValidDate') + ->passthru(); + + $carbon->shouldReceive('now') + ->once()->andReturn($carbon); + + $carbon->shouldReceive('subHours') + ->once()->with(7) + ->andReturn($carbon); + + $carbon->shouldReceive('toDateTimeString') + ->once()->andReturn($oldestValidDate); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $this->assertEquals( + $oldestValidDate, + $passService->getOldestValidDate() + ); + } } From 139d44be2410d5d1798d7d820a33f452e79eb372 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 17 Jul 2014 00:09:53 -0300 Subject: [PATCH 109/115] Improved UserValidator in order to attach an error MessageBag instead of replace it, and also to set the error message 'key' properly for password_confirmation. --- src/Zizaco/Confide/UserValidator.php | 25 +++++++--- tests/Zizaco/Confide/UserValidatorTest.php | 54 ++++++++++++++++++++-- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index 5a04128..b49aeec 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -2,6 +2,7 @@ use Illuminate\Support\Facades\App as App; use Illuminate\Support\Facades\Lang as Lang; +use Illuminate\Support\MessageBag; /** * This is the default validator used by ConfideUser. You may overwrite this @@ -90,7 +91,11 @@ public function validatePassword(ConfideUserInterface $user) return true; } else { - $this->attachErrorMsg($user, 'validation.confirmed::confide.alerts.wrong_password_reset'); + $this->attachErrorMsg( + $user, + 'validation.confirmed::confide.alerts.wrong_confirmation', + 'password_confirmation' + ); return false; } } @@ -118,7 +123,9 @@ public function validateIsUnique(ConfideUserInterface $user) return true; } - $this->attachErrorMsg($user, 'confide::confide.alerts.duplicated_credentials'); + $this->attachErrorMsg( + $user, 'confide::confide.alerts.duplicated_credentials' + ); return false; } @@ -154,13 +161,19 @@ public function validateAttributes(ConfideUserInterface $user, $ruleset = 'creat * Creates a \Illuminate\Support\MessageBag object, add the error message * to it and then set the errors attribute of the user with that bag * @param ConfideUserInterface $user - * @param string $errorMsg The error messgae + * @param string $errorMsg The error message + * @param string $key The key if the error message * @return void */ - public function attachErrorMsg(ConfideUserInterface $user, $errorMsg) + public function attachErrorMsg(ConfideUserInterface $user, $errorMsg, $key = 'confide') { - $messageBag = App::make('Illuminate\Support\MessageBag'); - $messageBag->add('confide', Lang::get($errorMsg)); + $messageBag = $user->errors; + + if (! $messageBag instanceof MessageBag) { + $messageBag = App::make('Illuminate\Support\MessageBag'); + } + + $messageBag->add($key, Lang::get($errorMsg)); $user->errors = $messageBag; } } diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 45c426e..3d09875 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -109,7 +109,11 @@ public function testShouldValidatePassword() $validator->shouldReceive('attachErrorMsg') ->atLeast(1) - ->with(m::any(), 'validation.confirmed::confide.alerts.wrong_password_reset'); + ->with( + m::any(), + 'validation.confirmed::confide.alerts.wrong_confirmation', + 'password_confirmation' + ); /* |------------------------------------------------------------ @@ -260,14 +264,14 @@ public function testShouldValidateAttributes() $this->assertEquals($errorBag, $userB->errors); } - public function testShouldAttachErrorMsg() + public function testShouldAttachErrorMsgOnEmpty() { /* |------------------------------------------------------------ | Set |------------------------------------------------------------ */ - $errorBag = m::mock('ErrorBag'); + $errorBag = m::mock('Illuminate\Support\MessageBag'); App::shouldReceive('make') ->with('Illuminate\Support\MessageBag') @@ -275,6 +279,46 @@ public function testShouldAttachErrorMsg() $validator = new UserValidator; $user = m::mock('Zizaco\Confide\ConfideUserInterface'); + $user->errors = null; + + /* + |------------------------------------------------------------ + | Expectation + |------------------------------------------------------------ + */ + Lang::shouldReceive('get') + ->once()->with('foobar') + ->andReturn('translated_foobar'); + + $errorBag->shouldReceive('add') + ->with('confide', 'translated_foobar') + ->andReturn(true); + + /* + |------------------------------------------------------------ + | Assertion + |------------------------------------------------------------ + */ + $validator->attachErrorMsg($user, 'foobar'); + $this->assertInstanceOf('Illuminate\Support\MessageBag', $user->errors); + } + + public function testShouldAttachErrorMsgOnExisting() + { + /* + |------------------------------------------------------------ + | Set + |------------------------------------------------------------ + */ + $errorBag = m::mock('Illuminate\Support\MessageBag'); + + App::shouldReceive('make') + ->with('Illuminate\Support\MessageBag') + ->never(); + + $validator = new UserValidator; + $user = m::mock('Zizaco\Confide\ConfideUserInterface'); + $user->errors = $errorBag; /* |------------------------------------------------------------ @@ -286,7 +330,8 @@ public function testShouldAttachErrorMsg() ->andReturn('translated_foobar'); $errorBag->shouldReceive('add') - ->with('confide', 'translated_foobar'); + ->with('confide', 'translated_foobar') + ->andReturn(true); /* |------------------------------------------------------------ @@ -294,5 +339,6 @@ public function testShouldAttachErrorMsg() |------------------------------------------------------------ */ $validator->attachErrorMsg($user, 'foobar'); + $this->assertInstanceOf('Illuminate\Support\MessageBag', $user->errors); } } From 73d873f8c66fdc1c4f1ea50f5ca9537289e4cf94 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 17 Jul 2014 00:23:34 -0300 Subject: [PATCH 110/115] Updated .travis.yml in order to allow_failure for non-stable PHP 5.6 --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 11ac310..44fc78a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,10 @@ php: - 5.6 - hhvm +matrix: + allow_failures: + - php: 5.6 + before_script: - travis_retry composer self-update - travis_retry composer install --no-interaction --prefer-source --dev From 93f3ba179eb8e1d5dbee3ac561d82fecb32aeaef Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 17 Jul 2014 00:49:16 -0300 Subject: [PATCH 111/115] Updated release notes in README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d6ba323..4a525be 100644 --- a/README.md +++ b/README.md @@ -179,13 +179,13 @@ Then edit the view names in `app/config/packages/zizaco/confide/config.php`. #### Custom user validation You can implement your own validator by creating a class that implements the `UserValidatorInterface` and registering that class as *"confide.user_validator"*. - + For example, create your custom validator class: - + // app/models/MyOwnValidator.php class MyOwnValidator implements UserValidatorInterface { - + public function validate(ConfideUserInterface $user) { unset($user->password_confirmation); @@ -198,7 +198,7 @@ Then register it in IoC container as *"confide.user_validator"* // app/start/global.php ... App::bind('confide.user_validator', 'MyOwnValidator'); - + Also, don't forget that your validator should unset the 'password_confirmation' attribute of the user before saving it. #### Passing additional information to the "make" methods @@ -288,6 +288,12 @@ For example: `"zizaco/confide": "~3.2"` will avoid composer download version 4.0 ## Release Notes +### Version 4.0.0 Beta 2 +* UserValidator now adds errors to a existing MessageBag instead of replacing it. +* Password reset token will expire after 7 days. +* Added support for custom connections using the $connection attribute of the model. +* Password reset requests are deleted after being used. + ### Version 4.0.0 Beta 1 * Dropped Ardent dependency. * Updated to support Laravel 4.2 From 07d1bdac9d5fb77b48a1836cab5f93e27fb1292c Mon Sep 17 00:00:00 2001 From: Zizaco Date: Thu, 17 Jul 2014 22:28:52 -0300 Subject: [PATCH 112/115] Updated README.md in order to include troubleshoot ing information about cleaning the password_confirmation attribute of user. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 4a525be..269786c 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Set the properly values to the `config/auth.php`. This values will be used by co Set the `address` and `name` from the `from` array in `config/mail.php`. Those will be used to send account confirmation and password reset emails to the users. + ### User model Now generate the Confide migration and the reminder password table migration: @@ -264,6 +265,10 @@ The [generated controller](https://github.com/Zizaco/confide/blob/master/src/vie ## Troubleshooting +__[2014-07-18 01:13:15] production.ERROR: exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'password_confirmation' in 'field list' (SQL: insert into \`users\` ...__ + +The `password_confirmation` attribute should be removed from the object before being sent to the database. Make sure your user model implement the `ConfideUserInterface` and that it use the `ConfideUser` trait [as described above](#user-model). Otherwise if you are using a custom validator, you will have to unset `password_confirmation` before saving the user. + __I receive a "Your account may not be confirmed" when trying to login__ You need to confirm a newly created user _(by "reaching" its `confirm()` method)_, otherwise you can disable the confirmation as a requirement to login in in the config file _(see bellow)_. You can easly confirm an user manually using Laravel's `artisan tinker` tool. From c2ada2b9af2f7e43761366c9f58599ec079a65c1 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Sun, 20 Jul 2014 07:25:14 +0000 Subject: [PATCH 113/115] Improve default UserValidator behavior --- src/Zizaco/Confide/UserValidator.php | 31 ++++++++++++++-------- tests/Zizaco/Confide/UserValidatorTest.php | 8 +++--- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/Zizaco/Confide/UserValidator.php b/src/Zizaco/Confide/UserValidator.php index b49aeec..c8ea445 100644 --- a/src/Zizaco/Confide/UserValidator.php +++ b/src/Zizaco/Confide/UserValidator.php @@ -65,9 +65,9 @@ public function validate(ConfideUserInterface $user, $ruleset = 'create') $this->repo = App::make('confide.repository'); // Validate object - $result = $this->validatePassword($user) && - $this->validateIsUnique($user) && - $this->validateAttributes($user, $ruleset); + $result = $this->validateAttributes($user, $ruleset) ? true : false; + $result = ($this->validatePassword($user) && $result) ? true : false; + $result = ($this->validateIsUnique($user) && $result) ? true : false; return $result; } @@ -113,20 +113,29 @@ public function validatePassword(ConfideUserInterface $user) public function validateIsUnique(ConfideUserInterface $user) { $identity = [ - 'username' => $user->username, 'email' => $user->email, + 'username' => $user->username, ]; - $similar = $this->repo->getUserByIdentity($identity); + foreach($identity as $attribute => $value) { + + $similar = $this->repo->getUserByIdentity([$attribute => $value]); + + if (!$similar || $similar->getKey() == $user->getKey()) { + unset($identity[$attribute]); + } else { + $this->attachErrorMsg( + $user, 'confide::confide.alerts.duplicated_credentials', $attribute + ); + } - if (!$similar || $similar->getKey() == $user->getKey()) { - return true; } - $this->attachErrorMsg( - $user, 'confide::confide.alerts.duplicated_credentials' - ); - return false; + if(!$identity) { + return true; + } + + return false; } /** diff --git a/tests/Zizaco/Confide/UserValidatorTest.php b/tests/Zizaco/Confide/UserValidatorTest.php index 3d09875..06282b7 100644 --- a/tests/Zizaco/Confide/UserValidatorTest.php +++ b/tests/Zizaco/Confide/UserValidatorTest.php @@ -175,14 +175,14 @@ public function testShouldValidateIsUnique() ->andReturn($userD->id); $repo->shouldReceive('getUserByIdentity') - ->andReturnUsing(function($user) use ($userB, $userC) { - if ($user['email'] == $userB->email) return $userB; - if ($user['email'] == $userC->email) return $userC; + ->andReturnUsing(function($user) use ($userB, $userC) { + if (isset($user['email']) && $user['email'] == $userB->email) return $userB; + if (isset($user['email']) && $user['email'] == $userC->email) return $userC; }); $validator->shouldReceive('attachErrorMsg') ->atLeast(1) - ->with(m::any(), 'confide::confide.alerts.duplicated_credentials'); + ->with(m::any(), 'confide::confide.alerts.duplicated_credentials', 'email'); /* |------------------------------------------------------------ From b9081d4dda1463b511b11ce24657122efbb92641 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 20 Jul 2014 12:26:34 -0300 Subject: [PATCH 114/115] Config to be able to customize the duration of the reset password requests --- src/Zizaco/Confide/EloquentPasswordService.php | 3 ++- src/config/config.php | 18 +++++++----------- .../Confide/EloquentPasswordServiceTest.php | 8 +++++++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/Zizaco/Confide/EloquentPasswordService.php b/src/Zizaco/Confide/EloquentPasswordService.php index b0dc3a2..ffcae8e 100644 --- a/src/Zizaco/Confide/EloquentPasswordService.php +++ b/src/Zizaco/Confide/EloquentPasswordService.php @@ -172,9 +172,10 @@ protected function getOldestValidDate() // Instantiate a carbon object (that is a dependency of // 'illuminate/database') $carbon = $this->app['Carbon\Carbon']; + $config = $this->app['config']; return $carbon->now() - ->subHours(7) + ->subHours($config->get('confide::confide.password_reset_expiration', 7)) ->toDateTimeString(); } } diff --git a/src/config/config.php b/src/config/config.php index 8a6fc61..c21d319 100644 --- a/src/config/config.php +++ b/src/config/config.php @@ -75,20 +75,16 @@ /* |-------------------------------------------------------------------------- - | Signup (create) Cache + | Password reset expiration |-------------------------------------------------------------------------- | - | By default you will only can only register once every 2 hours - | (120 minutes) because you are not able to receive a registration - | email more often then that. - | - | You can adjust that limitation here, set to 0 for no caching. - | Time is in minutes. - | + | By default. A password reset request will expire after 7 hours. With the + | line below you will be able to customize the duration of the reset + | requests here. | */ - 'signup_cache' => 120, - + 'password_reset_expiration' => 7, // hours + /* |-------------------------------------------------------------------------- | Signup E-mail and confirmation (true or false) @@ -106,7 +102,7 @@ | signup_confirm: | is to decide of a member needs to be confirmed before he is able to login | so when you set this to true, then a member has to be confirmed before - | he is able to login, so if you want to use an IPN for confirmation, be + | he is able to login, so if you want to use an IPN for confirmation, be | sure that the ipn process also changes the confirmed flag in the member | table, otherwise they will not be able to login after the payment. | diff --git a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php index 7366bba..5805df1 100644 --- a/tests/Zizaco/Confide/EloquentPasswordServiceTest.php +++ b/tests/Zizaco/Confide/EloquentPasswordServiceTest.php @@ -411,10 +411,12 @@ public function testShouldGetOldestValidDate() */ $oldestValidDate = '2014-07-16 22:20:26'; $carbon = m::mock('Carbon\Carbon'); + $config = m::mock('Config'); $passService = m::mock('Zizaco\Confide\EloquentPasswordService'); $passService->shouldAllowMockingProtectedMethods(); $passService->app['Carbon\Carbon'] = $carbon; + $passService->app['config'] = $config; /* |------------------------------------------------------------ @@ -424,11 +426,15 @@ public function testShouldGetOldestValidDate() $passService->shouldReceive('getOldestValidDate') ->passthru(); + $config->shouldReceive('get') + ->once()->with('confide::confide.password_reset_expiration', 7) + ->andReturn(14); + $carbon->shouldReceive('now') ->once()->andReturn($carbon); $carbon->shouldReceive('subHours') - ->once()->with(7) + ->once()->with(14) ->andReturn($carbon); $carbon->shouldReceive('toDateTimeString') From d4ffb979e1dd9210c537ba3d7b342aa5ecc70969 Mon Sep 17 00:00:00 2001 From: Zizaco Date: Sun, 20 Jul 2014 12:44:55 -0300 Subject: [PATCH 115/115] Updated README.md in order to include information about the Beta 3 --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c2a669d..116e4e7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Confide Poster](https://dl.dropbox.com/u/12506137/libs_bundles/confide.png) [![Build Status](https://api.travis-ci.org/Zizaco/confide.png)](https://travis-ci.org/Zizaco/confide) -[![Coverage Status](https://coveralls.io/repos/Zizaco/confide/badge.png?branch=huge-update)](https://coveralls.io/r/Zizaco/confide?branch=huge-update) +[![Coverage Status](https://coveralls.io/repos/Zizaco/confide/badge.png?branch=master)](https://coveralls.io/r/Zizaco/confide?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Zizaco/confide/badges/quality-score.png)](https://scrutinizer-ci.com/g/Zizaco/confide/) [![ProjectStatus](http://stillmaintained.com/Zizaco/confide.png)](http://stillmaintained.com/Zizaco/confide) [![Latest Stable Version](https://poser.pugx.org/zizaco/confide/v/stable.png)](https://packagist.org/packages/zizaco/confide) @@ -293,6 +293,12 @@ For example: `"zizaco/confide": "~3.2"` will avoid composer download version 4.0 ## Release Notes +### Version 4.0.0 Beta 3 +* Now you can customize how long will take for a password reset request to expire (default to 7 hours). +* Reordered validations +* Now all validations are called even if one of them fails. So all validation messages are sent at once. +* `validateIsUnique` method now sends key to attachErrorMsg and also check for errors on each `$identity` field at once + ### Version 4.0.0 Beta 2 * UserValidator now adds errors to an existing MessageBag instead of replacing it. * Password reset token will expire after 7 days.