Bouncer

Bouncer es una librería que nos permite administrar roles y habilidades en cualquier aplicación que use modelos del ORM Eloquent. Bouncer además posee una sintaxis expresiva y fluida que te permite usarlo sólo cuando quieras e ignorarlo cuando no lo necesites.

Bouncer es compatible y puede ser usado en conjunto con las políticas de acceso de Laravel.

Instalación

Bouncer puede ser instalado con Composer ejecutando el siguiente comando en la terminal dentro del directorio de tu proyecto:

composer require silber/bouncer v1.0.0-rc.1

En Laravel 5.5 o superior los service providers y alias son registrados automáticamente. Si no estás utilizando la versión 5.5 o superior realiza los siguientes pasos:

  • Agrega un nuevo elemento al arreglo providers:

Silber\Bouncer\BouncerServiceProvider::class,

  • Agrega un nuevo alias al arreglo aliases:

'Bouncer' => Silber\Bouncer\BouncerFacade::class,

Hecho esto, el siguiente paso es incluir el trait HasRolesAndAbilities de Bouncer en tu modelo de usuario:

use Silber\Bouncer\Database\HasRolesAndAbilities;

class User extends Model
{
    use HasRolesAndAbilities;
}

Los roles y habilidades de Bouncer son dinámicos y se guardan en una base de datos, por lo que necesitaremos ejecutar algunas migraciones. Lo primero es copiar las migraciones a nuestro proyecto con el siguiente comando:

php artisan vendor:publish --tag="bouncer.migrations"

Una vez hecho esto podemos ejecutar php artisan migrate para ejecutar las migraciones y crear las tablas.

La migración creará cuatro tablas: abilities, roles, assigned_roles y permissions.

Al momento de usar Bouncer en tu código debes importar su alias, colocando la siguiente línea al principio del archivo:

use Bouncer;

Puedes ver este proceso paso a paso y detallado en la lección Roles y permisos dinámicos en Laravel con Bouncer del curso Técnicas de Autorización con Laravel.

Crear roles y habilidades

Al utilizar Bouncer no tienes que crear un rol o habilidad por adelantado, ya que éste las creará automáticamente si no existen. Simplemente debes pasar el nombre del rol al que deseas asignar la habilidad y por supuesto la habilidad como tal:

Bouncer::allow('editor')->to('create-posts');

En el ejemplo de arriba estamos creando un rol llamado editor y dándole la habilidad de crear posts. Bouncer se encargará de crear por ti los registros de Role y Ability.

El modelo Role pertenece a la tabla roles mientras que el modelo Ability pertenece a la tabla abilities. Dichas tablas se encargan de almacenar nuestros roles y habilidades, respectivamente.

Si quieres agregar datos más personalizados a un rol o habilidad, como por ejemplo el campo título, puedes agregar los roles y habilidades manualmente utilizando los métodos role y ability en la clase Bouncer:

// Crear rol con atributos personalizados:

$editor = Bouncer::role()->create([
    'name' => 'editor',
    'title' => 'Editor of the blog',
]);

// Crear habilidad con atributos personalizados:

$create = Bouncer::ability()->create([
    'name' => 'create-posts',
    'title' => 'Create blog posts',
]);

// Asignar la habilidad $create al rol $editor
Bouncer::allow($editor)->to($create);

Asignando roles a un usuario

Podemos asignar un rol a un usuario utilizando el método assign, pasando el usuario como argumento a to:

// Asignar llamando a assign y to:

Bouncer::assign('admin')->to($user);

// También puedes llamar al método assign directamente en el modelo del usuario:

$user->assign('admin');

Asignar habilidades directamente

Es posible asignar una habilidad directamente a un usuario sin asignarle un rol. Esto lo logramos utilizando el método allow, pasando como argumento el usuario y luego con el método to pasamos la habilidad que queremos asignar:

Bouncer::allow($user)->to('post-comments');

En este caso estaríamos asignando a un usuario la habilidad de publicar comentarios. Al igual que con los roles, también puedes asignar una habilidad directamente en el modelo de usuario, utilizando allow:

$user->allow('post-comments');

Restringir habilidades a un modelo

Probablemente algunas veces quieras restringir una habilidad a un modelo en específico. Para hacer esto simplemente pasa el modelo como segundo argumento a to:

Bouncer::allow($user)->to('delete', Comment::class);

En el ejemplo superior estaríamos permitiendo a los usuarios eliminar registros pero sólo del modelo Comment.

Propiedad de modelos

Utilizando el concepto de propiedad de modelos un usuario puede ser dueño de sus propios modelos y administrarlos:

Bouncer::allow($user)->toOwn(Comment::class);

Esto permitirá que el usuario pueda realizar cualquier acción sobre un modelo Comment si el valor del atributo user_id de dicho modelo Comment es igual al valor del id del usuario, es decir si: $comment->user_id === $user->id.

Podemos restringir las habilidades llamando al método to:

Bouncer::allow($user)->toOwn(Comment::class)->to('delete');

O podemos pasar también un arreglo con la lista de habilidades que queremos permitir si el usuario es el «propietario» del modelo:

Bouncer::allow($user)->toOwn(Comment::class)->to(['delete', 'update']);

Si queremos permitir que un usuario o rol pueda realizar acciones sobre todos los modelos podemos usar toOwnEverything:

// $user podrá realizar acciones sobre todos los modelos que "posea":

Bouncer::allow($user)->toOwnEverything();

// También podemos restringir las habilidades:

Bouncer::allow($user)->toOwnEverything()->to('update');

El concepto de propiedad de modelos es explicado a fondo en la lección Propiedad de modelos con Bouncer en Laravel del curso Técnicas de Autorización con Laravel.

Remover habilidades

Podemos remover habilidades previamente asignadas a un usuario utilizando el método disallow pasando como argumento el usuario o rol y concatenando to con la habilidad que queremos remover:

Bouncer::disallow($user)->to('delete-posts');

// También lo puedes hacer directamente:

$user->disallow('delete-posts');

Si la habilidad fue asignada a través de un rol necesitas decirle a Bouncer que remueva la habilidad del rol:

Bouncer::disallow('editor')->to('delete-posts');

Si quieres remover la habilidad sólo en un modelo en específico pasa el nombre del modelo como segundo argumento:

Bouncer::disallow($user)->to('delete', Post::class);

Comandos para la consola

Bouncer nos permite eliminar habilidades que no están siendo usadas. Podemos remover dos tipos de habilidades:

  •  Habilidades que ya no están asignadas a ningún usuario (Unassigned).
  •  Habilidades cuyos modelos han sido eliminados (Orphaned).

Para eliminar las habilidades que ya no están asignadas (Unassigned) ejecutamos en la terminal:

php artisan bouncer:clean --unassigned

Para eliminar las habilidades cuyos modelos ya no existen (Orphaned) ejecutamos en la terminal:

php artisan bouncer:clean --orphaned

Si ejecutas php artisan bouncer:clean directamente y sin pasarle ningún argumento eliminarás tanto las habilidades Unassigned como Orphaned.

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:

Espero que te haya gustado este material. No olvides seguirnos en Twitter y suscribirte a nuestro boletín:

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.