Commit 1ff70b6d authored by Nicolas Widart's avatar Nicolas Widart

Squashed 'Modules/User/' changes from 8b9a95b..4417311

4417311 Abstract the final reset password part
c8be3b4 Using the user repository on complete reset
c46ed46 Fixing reset complete route
cacca3d Removing unused imports
38f5999 Abstracting first reset pwd step
f891810 Correct the module name
1fa89b3 User the user repository
97094e3 Merge branch 'feature/decouple_authentication' into develop
e72ee46 Abstract the user activation actions
661f9dd Fix confirm pwd link
f0555ae Fix email views
747351a Fix event name
d6ac09b Import the sentinel exceptions
60d7f9e Abstracting the registration
ab67c78 Abstracting the logout method
73c729c Abstracting the Login action
f474bb6 Bind the interface to the sentinel implementation
3478dd7 Adding first pass to a Auth interface

git-subtree-dir: Modules/User
git-subtree-split: 44173119c4e3c8ddff1f075fe915d8965d6f153c
parent 6994f095
...@@ -6,9 +6,26 @@ use Illuminate\Support\Facades\Event; ...@@ -6,9 +6,26 @@ use Illuminate\Support\Facades\Event;
use Laracasts\Commander\CommandHandler; use Laracasts\Commander\CommandHandler;
use Modules\User\Events\UserHasBegunResetProcess; use Modules\User\Events\UserHasBegunResetProcess;
use Modules\User\Exceptions\UserNotFoundException; use Modules\User\Exceptions\UserNotFoundException;
use Modules\User\Repositories\AuthenticationRepository;
use Modules\User\Repositories\UserRepository;
class BeginResetProcessCommandHandler implements CommandHandler class BeginResetProcessCommandHandler implements CommandHandler
{ {
/**
* @var UserRepository
*/
private $user;
/**
* @var AuthenticationRepository
*/
private $auth;
public function __construct(UserRepository $user, AuthenticationRepository $auth)
{
$this->user = $user;
$this->auth = $auth;
}
/** /**
* Handle the command * Handle the command
* *
...@@ -20,14 +37,14 @@ class BeginResetProcessCommandHandler implements CommandHandler ...@@ -20,14 +37,14 @@ class BeginResetProcessCommandHandler implements CommandHandler
{ {
$user = $this->findUser((array) $command); $user = $this->findUser((array) $command);
$reminder = Reminder::exists($user) ?: Reminder::create($user); $code = $this->auth->createReminderCode($user);
Event::fire('Modules.Session.Events.UserHasBegunResetProcess', new UserHasBegunResetProcess($user, $reminder)); Event::fire('Modules.User.Events.UserHasBegunResetProcess', new UserHasBegunResetProcess($user, $code));
} }
private function findUser($credentials) private function findUser($credentials)
{ {
$user = Sentinel::findByCredentials((array) $credentials); $user = $this->user->findByCredentials((array) $credentials);
if ($user) { if ($user) {
return $user; return $user;
} }
......
<?php namespace Modules\User\Commands; <?php namespace Modules\User\Commands;
use Cartalyst\Sentinel\Laravel\Facades\Reminder;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Laracasts\Commander\CommandHandler; use Laracasts\Commander\CommandHandler;
use Modules\User\Exceptions\InvalidOrExpiredResetCode;
use Modules\User\Exceptions\UserNotFoundException; use Modules\User\Exceptions\UserNotFoundException;
use Modules\User\Repositories\AuthenticationRepository;
use Modules\User\Repositories\UserRepository;
class CompleteResetProcessCommandHandler implements CommandHandler class CompleteResetProcessCommandHandler implements CommandHandler
{ {
protected $input; protected $input;
/**
* @var UserRepository
*/
private $user;
/**
* @var AuthenticationRepository
*/
private $auth;
public function __construct(UserRepository $user, AuthenticationRepository $auth)
{
$this->user = $user;
$this->auth = $auth;
}
/** /**
* Handle the command * Handle the command
...@@ -21,11 +36,9 @@ class CompleteResetProcessCommandHandler implements CommandHandler ...@@ -21,11 +36,9 @@ class CompleteResetProcessCommandHandler implements CommandHandler
{ {
$this->input = $command; $this->input = $command;
$this->form->validate((array) $this->input);
$user = $this->findUser(); $user = $this->findUser();
if (!Reminder::complete($user, $this->input->code, $this->input->password)) { if (!$this->auth->completeResetPassword($user, $this->input->code, $this->input->password)) {
throw new InvalidOrExpiredResetCode; throw new InvalidOrExpiredResetCode;
} }
...@@ -34,7 +47,7 @@ class CompleteResetProcessCommandHandler implements CommandHandler ...@@ -34,7 +47,7 @@ class CompleteResetProcessCommandHandler implements CommandHandler
public function findUser() public function findUser()
{ {
$user = Sentinel::findById($this->input->userId); $user = $this->user->find($this->input->userId);
if ($user) { if ($user) {
return $user; return $user;
} }
......
...@@ -4,11 +4,28 @@ use Cartalyst\Sentinel\Laravel\Facades\Sentinel; ...@@ -4,11 +4,28 @@ use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Laracasts\Commander\CommandHandler; use Laracasts\Commander\CommandHandler;
use Modules\User\Events\UserHasRegistered; use Modules\User\Events\UserHasRegistered;
use Modules\User\Repositories\AuthenticationRepository;
use Modules\User\Repositories\RoleRepository;
class RegisterNewUserCommandHandler implements CommandHandler class RegisterNewUserCommandHandler implements CommandHandler
{ {
protected $input; protected $input;
/**
* @var AuthenticationRepository
*/
private $auth;
/**
* @var RoleRepository
*/
private $role;
public function __construct(AuthenticationRepository $auth, RoleRepository $role)
{
$this->auth = $auth;
$this->role = $role;
}
/** /**
* Handle the command * Handle the command
* *
...@@ -23,20 +40,20 @@ class RegisterNewUserCommandHandler implements CommandHandler ...@@ -23,20 +40,20 @@ class RegisterNewUserCommandHandler implements CommandHandler
$this->assignUserToUsersGroup($user); $this->assignUserToUsersGroup($user);
Event::fire('Modules.Session.Events.UserHasRegistered', new UserHasRegistered($user)); Event::fire('Modules.User.Events.UserHasRegistered', new UserHasRegistered($user));
return $user; return $user;
} }
private function createUser() private function createUser()
{ {
return Sentinel::getUserRepository()->create((array) $this->input); return $this->auth->register((array) $this->input);
} }
private function assignUserToUsersGroup($user) private function assignUserToUsersGroup($user)
{ {
$group = Sentinel::findRoleByName('User'); $role = $this->role->findByName('User');
$group->users()->attach($user); $this->auth->assignRole($user, $role);
} }
} }
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
class UserHasBegunResetProcess class UserHasBegunResetProcess
{ {
public $user; public $user;
public $reminder; public $code;
public function __construct($user, $reminder) public function __construct($user, $code)
{ {
$this->user = $user; $this->user = $user;
$this->reminder = $reminder; $this->code = $code;
} }
} }
<?php namespace Modules\User\Http\Controllers; <?php namespace Modules\User\Http\Controllers;
use Cartalyst\Sentinel\Checkpoints\NotActivatedException;
use Cartalyst\Sentinel\Checkpoints\ThrottlingException;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\View;
use Laracasts\Commander\CommanderTrait; use Laracasts\Commander\CommanderTrait;
...@@ -13,13 +10,20 @@ use Modules\User\Http\Requests\LoginRequest; ...@@ -13,13 +10,20 @@ use Modules\User\Http\Requests\LoginRequest;
use Modules\User\Http\Requests\RegisterRequest; use Modules\User\Http\Requests\RegisterRequest;
use Modules\User\Http\Requests\ResetCompleteRequest; use Modules\User\Http\Requests\ResetCompleteRequest;
use Modules\User\Http\Requests\ResetRequest; use Modules\User\Http\Requests\ResetRequest;
use Modules\User\Repositories\AuthenticationRepository;
class AuthController class AuthController
{ {
use CommanderTrait; use CommanderTrait;
public function __construct() /**
* @var AuthenticationRepository
*/
private $auth;
public function __construct(AuthenticationRepository $auth)
{ {
$this->auth = $auth;
} }
public function getLogin() public function getLogin()
...@@ -34,19 +38,14 @@ class AuthController ...@@ -34,19 +38,14 @@ class AuthController
'password' => $request->password 'password' => $request->password
]; ];
$remember = (bool)$request->get('remember_me', false); $remember = (bool)$request->get('remember_me', false);
try {
if (Sentinel::authenticate($credentials, $remember)) { $error = $this->auth->login($credentials, $remember);
if (!$error) {
Flash::success('Successfully logged in.'); Flash::success('Successfully logged in.');
return Redirect::route('dashboard.index', compact('user')); return Redirect::route('dashboard.index');
}
Flash::error('Invalid login or password.');
} catch (NotActivatedException $e) {
Flash::error('Account not yet validated. Please check your email.');
} catch (ThrottlingException $e) {
$delay = $e->getDelay();
Flash::error("Your account is blocked for {$delay} second(s).");
} }
Flash::error($error);
return Redirect::back()->withInput(); return Redirect::back()->withInput();
} }
...@@ -66,11 +65,21 @@ class AuthController ...@@ -66,11 +65,21 @@ class AuthController
public function getLogout() public function getLogout()
{ {
Sentinel::logout(); $this->auth->logout();
return Redirect::route('login'); return Redirect::route('login');
} }
public function getActivate($userId, $code)
{
if ($this->auth->activate($userId, $code)) {
Flash::success('Account activated. You can now login.');
return Redirect::route('login');
}
Flash::error('There was an error with the activation.');
return Redirect::route('register');
}
public function getReset() public function getReset()
{ {
return View::make('user::public.reset.begin'); return View::make('user::public.reset.begin');
...@@ -105,16 +114,13 @@ class AuthController ...@@ -105,16 +114,13 @@ class AuthController
); );
} catch (UserNotFoundException $e) { } catch (UserNotFoundException $e) {
Flash::error('The user no longer exists.'); Flash::error('The user no longer exists.');
return Redirect::back()->withInput(); return Redirect::back()->withInput();
} catch(InvalidOrExpiredResetCode $e) { } catch (InvalidOrExpiredResetCode $e) {
Flash::error('Invalid or expired reset code.'); Flash::error('Invalid or expired reset code.');
return Redirect::back()->withInput(); return Redirect::back()->withInput();
} }
Flash::success('Password has been reset. You can now login with your new password.'); Flash::success('Password has been reset. You can now login with your new password.');
return Redirect::route('login'); return Redirect::route('login');
} }
} }
<?php namespace Modules\User\Listeners; <?php namespace Modules\User\Listeners;
use Cartalyst\Sentinel\Laravel\Facades\Activation;
use Illuminate\Mail\Message; use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Laracasts\Commander\Events\EventListener; use Laracasts\Commander\Events\EventListener;
use Modules\User\Repositories\AuthenticationRepository;
class SendRegistrationConfirmationEmail extends EventListener class SendRegistrationConfirmationEmail extends EventListener
{ {
/**
* @var AuthenticationRepository
*/
private $auth;
public function __construct(AuthenticationRepository $auth)
{
$this->auth = $auth;
}
public function whenUserHasRegistered($event) public function whenUserHasRegistered($event)
{ {
$user = $event->user; $user = $event->user;
$activation = Activation::create($user); $activation = $this->auth->createActivation($user);
$data = [ $data = [
'user' => $user, 'user' => $user,
'activationcode' => $activation->code 'activationcode' => $activation->code
]; ];
Mail::queue('session::emails.welcome',$data,
Mail::queue('user::emails.welcome',$data,
function (Message $m) use ($user) { function (Message $m) use ($user) {
$m->to($user->email)->subject('Welcome.'); $m->to($user->email)->subject('Welcome.');
} }
......
...@@ -9,9 +9,9 @@ class SendResetCodeEmail extends EventListener ...@@ -9,9 +9,9 @@ class SendResetCodeEmail extends EventListener
public function whenUserHasBegunResetProcess($event) public function whenUserHasBegunResetProcess($event)
{ {
$user = $event->user; $user = $event->user;
$code = $event->reminder->code; $code = $event->code;
Mail::queue('SessionModule::emails.reminder', compact('user', 'code'), function(Message $m) use ($user) Mail::queue('user::emails.reminder', compact('user', 'code'), function(Message $m) use ($user)
{ {
$m->to($user->email)->subject('Reset your account password.'); $m->to($user->email)->subject('Reset your account password.');
}); });
......
...@@ -82,6 +82,10 @@ class UserServiceProvider extends ServiceProvider ...@@ -82,6 +82,10 @@ class UserServiceProvider extends ServiceProvider
'Modules\User\Repositories\RoleRepository', 'Modules\User\Repositories\RoleRepository',
'Modules\User\Repositories\Sentinel\SentinelRoleRepository' 'Modules\User\Repositories\Sentinel\SentinelRoleRepository'
); );
$this->app->bind(
'Modules\User\Repositories\AuthenticationRepository',
'Modules\User\Repositories\Sentinel\SentinelAuthenticationRepository'
);
} }
private function registerMiddleware($router) private function registerMiddleware($router)
......
<?php namespace Modules\User\Repositories;
interface AuthenticationRepository
{
/**
* Authenticate a user
* @param array $credentials
* @param bool $remember Remember the user
* @return mixed
*/
public function login(array $credentials, $remember = false);
/**
* Register a new user.
* @param array $user
* @return bool
*/
public function register(array $user);
/**
* Activate the given used id
* @param int $userId
* @param string $code
* @return mixed
*/
public function activate($userId, $code);
/**
* Assign a role to the given user.
* @param \Modules\User\Repositories\UserRepository $user
* @param \Modules\User\Repositories\RoleRepository $role
* @return mixed
*/
public function assignRole($user, $role);
/**
* Log the user out of the application.
* @return mixed
*/
public function logout();
/**
* Create an activation code for the given user
* @param $user
* @return mixed
*/
public function createActivation($user);
/**
* Create a reminders code for the given user
* @param $user
* @return mixed
*/
public function createReminderCode($user);
/**
* Completes the reset password process
* @param $user
* @param string $code
* @param string $password
* @return bool
*/
public function completeResetPassword($user, $code, $password);
}
...@@ -39,4 +39,11 @@ interface RoleRepository ...@@ -39,4 +39,11 @@ interface RoleRepository
* @return mixed * @return mixed
*/ */
public function delete($id); public function delete($id);
/**
* Find a role by its name
* @param string $name
* @return mixed
*/
public function findByName($name);
} }
<?php namespace Modules\User\Repositories\Sentinel;
use Cartalyst\Sentinel\Checkpoints\NotActivatedException;
use Cartalyst\Sentinel\Checkpoints\ThrottlingException;
use Cartalyst\Sentinel\Laravel\Facades\Activation;
use Cartalyst\Sentinel\Laravel\Facades\Reminder;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Modules\User\Repositories\AuthenticationRepository;
class SentinelAuthenticationRepository implements AuthenticationRepository
{
/**
* Authenticate a user
* @param array $credentials
* @param bool $remember Remember the user
* @return mixed
*/
public function login(array $credentials, $remember = false)
{
try {
if (Sentinel::authenticate($credentials, $remember)) {
return false;
}
return 'Invalid login or password.';
} catch (NotActivatedException $e) {
return 'Account not yet validated. Please check your email.';
} catch (ThrottlingException $e) {
$delay = $e->getDelay();
return "Your account is blocked for {$delay} second(s).";
}
}
/**
* Register a new user.
* @param array $user
* @return bool
*/
public function register(array $user)
{
return Sentinel::getUserRepository()->create((array) $user);
}
/**
* Assign a role to the given user.
* @param \Modules\User\Repositories\UserRepository $user
* @param \Modules\User\Repositories\RoleRepository $role
* @return mixed
*/
public function assignRole($user, $role)
{
return $role->users()->attach($user);
}
/**
* Log the user out of the application.
* @return bool
*/
public function logout()
{
return Sentinel::logout();
}
/**
* Activate the given used id
* @param int $userId
* @param string $code
* @return mixed
*/
public function activate($userId, $code)
{
$user = Sentinel::findById($userId);
return Activation::complete($user, $code);
}
/**
* Create an activation code for the given user
* @param \Modules\User\Repositories\UserRepository $user
* @return mixed
*/
public function createActivation($user)
{
return Activation::create($user);
}
/**
* Create a reminders code for the given user
* @param \Modules\User\Repositories\UserRepository $user
* @return mixed
*/
public function createReminderCode($user)
{
$reminder = Reminder::exists($user) ?: Reminder::create($user);
return $reminder->code;
}
/**
* Completes the reset password process
* @param $user
* @param string $code
* @param string $password
* @return bool
*/
public function completeResetPassword($user, $code, $password)
{
return Reminder::complete($user, $code, $password);
}
}
...@@ -69,4 +69,14 @@ class SentinelRoleRepository implements RoleRepository ...@@ -69,4 +69,14 @@ class SentinelRoleRepository implements RoleRepository
return $role->delete(); return $role->delete();
} }
/**
* Find a role by its name
* @param string $name
* @return mixed
*/
public function findByName($name)
{
return Sentinel::findRoleByName($name);
}
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
use Cartalyst\Sentinel\Laravel\Facades\Activation; use Cartalyst\Sentinel\Laravel\Facades\Activation;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel; use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Modules\Session\Exceptions\UserNotFoundException; use Modules\User\Exceptions\UserNotFoundException;
use Modules\User\Repositories\UserRepository; use Modules\User\Repositories\UserRepository;
class SentinelUserRepository implements UserRepository class SentinelUserRepository implements UserRepository
...@@ -113,4 +113,14 @@ class SentinelUserRepository implements UserRepository ...@@ -113,4 +113,14 @@ class SentinelUserRepository implements UserRepository
throw new UserNotFoundException; throw new UserNotFoundException;
} }
/**
* Find a user by its credentials
* @param array $credentials
* @return mixed
*/
public function findByCredentials(array $credentials)
{
return Sentinel::findByCredentials($credentials);
}
} }
...@@ -57,4 +57,11 @@ interface UserRepository ...@@ -57,4 +57,11 @@ interface UserRepository
* @return mixed * @return mixed
*/ */
public function delete($id); public function delete($id);
/**
* Find a user by its credentials
* @param array $credentials
* @return mixed
*/
public function findByCredentials(array $credentials);
} }
...@@ -72,7 +72,7 @@ background-color: #f6f6f6; ...@@ -72,7 +72,7 @@ background-color: #f6f6f6;
</tr> </tr>
<tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;"> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> <td class="content-block" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
To reset your password, complete this form: {{ URL::to("reset/{$user['id']}/{$code}") }}. To reset your password, complete this form: {{ URL::to("auth/reset/{$user['id']}/{$code}") }}.
</td> </td>
</tr> </tr>
<tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;"> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
......
...@@ -82,7 +82,7 @@ background-color: #f6f6f6; ...@@ -82,7 +82,7 @@ background-color: #f6f6f6;
</tr> </tr>
<tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;"> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> <td class="content-block" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
<a href="{{ URL::to('activate/' . $user['id'] . '/' . $activationcode) }}" class="btn-primary" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background: #348eda; margin: 0; padding: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Confirm email address</a> <a href="{{ URL::to('auth/activate/' . $user['id'] . '/' . $activationcode) }}" class="btn-primary" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background: #348eda; margin: 0; padding: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Confirm email address</a>
</td> </td>
</tr> </tr>
<tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;"> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment