En este tutorial aprenderemos a implementar Bouncer en Laravel. Bouncer es una librería que nos permite administrar roles y habilidades en cualquier aplicación que use modelos del ORM Eloquent.
Para poder continuar con este tutorial es importante que primero revises el post Manejo de roles y habilidades en Eloquent con Bouncer donde aprenderás a instalar y configurar Bouncer.
Luego de instalar Laravel y Bouncer, copiado las migraciones y realizada la configuración necesaria, podemos comenzar a crear nuestro ejemplo. Recuerda que todos los pasos de instalación y configuración son explicados en el tutorial Manejo de roles y habilidades en Eloquent con Bouncer.
Para este tutorial crearemos una pequeña aplicación que contará con dos modelos: Post
y Comment
además del modelo User
que ya incluye Laravel. A continuación te explico el funcionamiento de cada modelo:
Post
: este modelo almacenará posts o publicaciones creadas por los usuarios.Comment
: este modelo se encargará de almacenar los comentarios de las publicaciones.
También tendremos un rol y dos habilidades:
- El rol admin es asignado a los administradores y permite realizar todo tipo de acciones.
- La habilidad Create Post es asignada a los autores y permite crear posts.
- La habilidad Delete Comment es asignada a los autores al momento de crear un comentario y permite a dicho autor eliminar sus propios comentarios.
Básicamente, en nuestra aplicación los autores podrán crear posts o publicaciones y dejar comentarios en dichas publicaciones. Estos tienen el control de sus propios comentarios y pueden eliminarlos, siempre y cuando hayan sido creados por ellos mismos. Sólo los administradores pueden eliminar los comentarios de cualquier usuario.
Asegúrate de ejecutar php artisan make:auth
antes de continuar, para activar la autenticación por defecto de Laravel.
Creando el modelo Post
Al inicio del tutorial mencionamos que usaremos dos modelos: Post
y Comment
. Como en este tutorial nos centraremos en la creación de los posts vamos primero a crear el modelo Post
:
// Ejecuta el siguiente comando en la terminal: php artisan make:model Post -mc
Dentro del modelo Post
agregamos:
class Post extends Model { protected $guarded = []; public function comments() { return $this->hasMany(Comment::class); } public function user() { return $this->belongsTo(User::class); } }
También debemos editar el modelo User
que viene por defecto con Laravel. Recuerda implementar el trait HasRolesAndAbilities
que pertenece a Bouncer. En el modelo User
agregaremos los métodos necesarios para la relación entre los usuarios y los posts:
class User extends Authenticatable { // ... public function posts() { return $this->hasMany(Post::class); } }
Creando el seeder
En nuestro archivo DatabaseSeeder.php
agregaremos dos usuarios y los almacenaremos en las variables $user
y $creatorOfPosts
:
<?php use Bouncer; use App\User; class DatabaseSeeder extends Seeder { public function run() { $user = factory(User::class)->create([ 'name' => 'Foo Bar', 'email' => '[email protected]', 'password' => bcrypt('secret') ]); $creatorOfPosts = factory(User::class)->create([ 'name' => 'Creator of Posts', 'email' => '[email protected]', 'password' => bcrypt('secret') ]); } }
No olvides importar los modelos y el alias Bouncer al principio del archivo.
En el mismo archivo DatabaseSeeder.php
también crearemos y asignaremos el rol admin
y la habilidad Create Post al segundo usuario que hemos creado:
<?php //... class DatabaseSeeder extends Seeder { public function run() { // ... // Creamos el rol de administrador Bouncer::allow('admin')->everything(); // Asignamos el rol de administrador a $user $user->assign('admin'); // Asignamos al autor la habilidad de crear posts $creatorOfPosts->allow('create', Post::class); } }
Luego de hacer esto podemos ejecutar las migraciones y los seeders con el comando php artisan migrate:refresh --seed
.
Controladores
Para continuar con nuestra aplicación debemos agregar la lógica al controlador PostController
. Este controlador fue creado automáticamente al generar el modelo Post
(puesto que usamos la opción -c
). A continuación vamos a agregar la lógica para listar y crear posts al controlador PostController.php
:
class PostController extends Controller { public function index() { $posts = Post::paginate(10); return view('posts.index', compact('posts')); } public function create() { return view('posts.create'); } public function store(Request $request) { auth()->user()->posts()->create($request->all()); return redirect()->action('PostController@index'); } public function show(Post $post) { return view('posts.show', compact('post')); } }
Rutas
En el archivo web.php
vamos a agregar las rutas que nos van a permitir realizar las diferentes acciones en nuestra aplicación:
Route::group(['middleware' => 'auth'], function () { Route::get('/home', 'PostController@index')->name('posts.index'); Route::group(['middleware' => 'can:create,App\Post'], function () { Route::get('/posts/create', 'PostController@create')->name('posts.create'); Route::post('/posts', 'PostController@store')->name('posts.store'); }); }); Route::get('posts/{post}', 'PostController@show')->name('posts.show');
Observa como mediante can:create,App\Post
protegemos las rutas para que sólo los autores que pueden crear posts puedan acceder a los recursos que permiten ejecutar dicha acción.
Vistas
Finalmente podemos agregar las vistas de nuestra aplicación. Dentro del directorio resources/views/posts
agrega las siguientes vistas:
Archivo index.blade.php:
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Posts</div> <div class="card-body"> @foreach ($posts as $post) <div class="card mb-3"> <div class="card-body"> <h3> <a href="{{ route('posts.show', $post) }}">{{ $post->title }}</a> </h3> <hr> {{ $post->body }} </div> </div> @endforeach </div> </div> </div> </div> </div> @endsection
Archivo create.blade.php:
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Crear nuevo post</div> <div class="card-body"> <form method="POST" action="{{ route('posts.store') }}"> @csrf <div class="form-group"> <label for="title">Titulo</label> <input type="text" class="form-control" name="title" required> </div> <div class="form-group"> <label for="body">Contenido</label> <textarea name="body" class="form-control" cols="30" rows="10"></textarea> </div> <div class="form-group"> <button type="submit" class="btn btn-primary">Publicar</button> </div> </form> </div> </div> </div> </div> </div> @endsection
En el archivo resources/views/layouts/app.blade.php
agregamos un enlace para la creación de los nuevos posts, esto lo hacemos dentro de la etiqueta ul ubicada después del comentario «Left Side Of Navbar», de esta forma:
<!-- Left Side Of Navbar --> <ul class="navbar-nav mr-auto"> @can ('create', App\Post::class) <li> <a href="{{ route('posts.create') }}" class="nav-link">Crear Post</a> </li> @endcan </ul>
Utilizando la directiva @can
comprobamos si el usuario tiene la habilidad para crear posts.
Si tienes alguna pregunta o inquietud no dudes en dejarla en los comentarios. En el próximo tutorial agregaremos todo lo relacionado a los comentarios.
Puedes ver y descargar el código de este ejemplo en GitHub: laravel-bouncer-example.
Si te ha gustado este tutorial y te interesa el tema de manejo de roles y habilidades puedes ver una explicación detallada y a fondo en el curso Técnicas de Autorización con Laravel donde aprenderás no sólo a utilizar Bouncer sino también sobre muchos otros temas respecto al manejo de roles, permisos y autorización:
- Roles y permisos dinámicos en Laravel con Bouncer
- Propiedad de modelos con Bouncer en Laravel
- Definición de roles y habilidades mediante seeders con Laravel y Bouncer
- Uso de las directivas de autorización @can @cannot y @elsecan en Blade
No olvides seguirnos en Twitter y suscribirte a nuestro boletín:
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.