En el post anterior, vimos el inicio de sesión usando lo que trae Laravel y modificando sus clases para adaptarlas al uso de JWT’s.
Este post es una versión de lo visto en sendos post de registro y de cierre de sesión. Pero esta vez, vamos a rehacerlos al estilo del post anterior: usando las vistas, rutas , controladores y eventos de Laravel.
Empezamos por el Registro. Las rutas a usar son las siguientes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// muestra el formulario de registro Route::get('register', function () { return view('auth.register'); })->name('register'); // procesa el formulario para enviar el email Route::group(['guard' => 'api'], function () { Route::post('register', 'Auth\RegisterController@register'); }); // verifica la cuenta cuando pulse el link en el email Route::get('account/activation/{token}', [ 'uses' => 'Auth\RegisterController@activate', 'as' => 'account_activation', ]); |
Ahora el controlador:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
use App\Http\Controllers\Controller; use App\User; use Illuminate\Auth\Events\Registered; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; class RegisterController extends Controller { use RegistersUsers; protected $redirectTo = '/home'; public function __construct() { $this->middleware('guest'); } public function register(Request $request) { $this->validator($request->all())->validate(); if ($this->isAPIGuard()) { event(new Registered($user = new User($request->all() ))); return response()->success(['message' => 'user_registered']); } event(new Registered($user = new User($request->all()))); } protected function validator(array $data) { return Validator::make($data, [ 'name' => 'required|max:255', 'email' => 'required|email|max:255|unique:users', 'password' => 'required|min:4|confirmed', 'timezone' => 'max:50', ]); } public function activate($token) { try { $user = User::where('registration_token', $token)->firstOrFail(); $user->registration_token = null; $user->active = true; $user->save(); return response()->success(['message' => "email_verified"]); } catch (Exception $e) { return response()->error('error_verifying_email', $e->getStatusCode()); } } } |
Por último, creamos el manejador del evento «Registered» disparado en las líneas 24 y 29:
1 2 3 4 5 6 7 8 9 10 |
. . . . class EventServiceProvider extends ServiceProvider { protected $listen = [ 'Illuminate\Auth\Events\Registered' => [ 'App\Listeners\SendRegistrationNotification', ], ]; . . . . } |
1 |
php artisan event:generate |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class SendRegistrationNotification { . . . . public function handle(Registered $event) { $token = str_random(60); $user = $event->user; $user->role = 'user'; $user->registration_token = $token; $user->save(); $user->notify(new \App\Notifications\Registration($token)); } } |
Crearemos la notificación en forma de email disparado en la línea 13 del Listener anterior:
1 |
php artisan make:notification Registration |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
use App\User; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; class Registration extends Notification implements ShouldQueue { use Queueable; public $actionUrl; public function __construct($token) { $this->actionUrl = route('account_activation',$token); } public function via($notifiable) { return ['mail']; } public function toMail($notifiable) { return (new MailMessage) ->line('You are receiving this email because you have to activate your account.') ->action('Activate my account', $this->actionUrl) ->line('If you did not request a password reset, no further action is required.'); } . . . . } |
Ahora veamos como cerrar la sesión. La ruta será la siguiente:
1 2 3 4 |
Route::group(['guard' => 'api'], function () { Route::get('logout', 'Auth\LoginController@logout') ->name('logout')->middleware('auth:api'); }); |
Editaremos el controlador de sesión para incluír la función de logout. El LoginController usa un trait «AuthenticateUsers» que tiene la función «logout» que necesitamos. Lo que haremos será copiar esa función, pegarla directamente en el LoginController y editarla.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class LoginController extends Controller { public function logout(Request $request) { event(new \Illuminate\Auth\Events\Logout($this->guard()->user())); $this->guard()->logout(); if ($this->isAPIGuard()) { return response()->success(['message' => 'logged_out']); } $request->session()->flush(); $request->session()->regenerate(); return redirect('/'); } } |
Y por último, creamos el manejador del evento disparado en la línea 5:
1 2 3 4 5 6 7 8 9 10 |
. . . . class EventServiceProvider extends ServiceProvider { protected $listen = [ 'Illuminate\Auth\Events\Logout' => [ 'App\Listeners\UpdateLastLoggedAtOnLogout', ], ]; . . . . } |
1 |
php artisan event:generate |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
. . . . use Illuminate\Auth\Events\Logout; class UpdateLastLoggedAtOnLogout { . . . . public function handle(Logout $event) { // para que no se actualice la columna "updated_at" $event->user->timestamps = false; $event->user->online = false; $event->user->last_logged_at = $event->user->current_login_time; $event->user->save(); } } |
En resumen, hemos cubierto todo lo aprendido en posts anteriores y aplicado de forma elegante sin ser intrusivos con lo que Laravel trae por defecto.