Bouncer est une approche élégante et indépendante du framework pour gérer les rôles et les capacités de toute application utilisant des modèles Eloquent.
bouncer:clean
Bouncer est une approche élégante et indépendante du framework pour gérer les rôles et les capacités de toute application utilisant des modèles Eloquent. Avec une syntaxe expressive et fluide, il reste le plus possible hors de votre portée : utilisez-le quand vous le souhaitez, ignorez-le quand vous ne le souhaitez pas.
Pour une liste rapide et visuelle des fonctionnalités de Bouncer, consultez l'aide-mémoire.
Bouncer fonctionne bien avec d'autres capacités que vous avez codées en dur dans votre propre application. Votre code est toujours prioritaire : si votre code autorise une action, Bouncer n'interférera pas.
Une fois installé, vous pouvez simplement indiquer au videur ce que vous souhaitez autoriser au portail :
// Give a user the ability to create posts
Bouncer:: allow ( $ user )-> to ( ' create ' , Post::class);
// Alternatively, do it through a role
Bouncer:: allow ( ' admin ' )-> to ( ' create ' , Post::class);
Bouncer:: assign ( ' admin ' )-> to ( $ user );
// You can also grant an ability only to a specific model
Bouncer:: allow ( $ user )-> to ( ' edit ' , $ post );
Lorsque vous vérifiez les capacités à la porte de Laravel, Bouncer sera automatiquement consulté. Si Bouncer voit une capacité qui a été accordée à l'utilisateur actuel (que ce soit directement ou via un rôle), il autorisera la vérification.
Remarque : Bouncer v1.0.2 nécessite PHP 8.2+ et Laravel/Eloquent 11+.
Si vous utilisez Laravel v6-v10, utilisez Bouncer v1.0.1. Si vous utilisez Laravel v5.5-v5.8, utilisez Bouncer RC6.
Installez Bouncer avec composer :
composer require silber/bouncer
Ajoutez le trait de Bouncer à votre modèle utilisateur :
use Silber Bouncer Database HasRolesAndAbilities ;
class User extends Model
{
use HasRolesAndAbilities;
}
Maintenant, pour exécuter les migrations de Bouncer. Publiez d'abord les migrations dans le répertoire migrations
de votre application, en exécutant la commande suivante :
php artisan vendor:publish --tag="bouncer.migrations"
Enfin, exécutez les migrations :
php artisan migrate
Chaque fois que vous utilisez la façade Bouncer
dans votre code, n'oubliez pas d'ajouter cette ligne à vos importations d'espace de noms en haut du fichier :
use Bouncer ;
Pour plus d'informations sur les façades Laravel, reportez-vous à la documentation Laravel.
Installez Bouncer avec composer :
composer require silber/bouncer
Configurez la base de données avec le composant Eloquent Capsule :
use Illuminate Database Capsule Manager as Capsule ;
$ capsule = new Capsule ;
$ capsule -> addConnection ([ /* connection config */ ]);
$ capsule -> setAsGlobal ();
Reportez-vous à la documentation d'Eloquent Capsule pour plus de détails.
Exécutez les migrations à l'aide de l'une des méthodes suivantes :
Utilisez un outil tel que vagabond pour exécuter des migrations Laravel en dehors d'une application Laravel. Vous trouverez les migrations nécessaires dans le fichier stub des migrations.
Alternativement, vous pouvez exécuter le SQL brut directement dans votre base de données.
Ajoutez le trait de Bouncer à votre modèle utilisateur :
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database HasRolesAndAbilities ;
class User extends Model
{
use HasRolesAndAbilities;
}
Créez une instance de Bouncer :
use Silber Bouncer Bouncer ;
$ bouncer = Bouncer:: create ();
// If you are in a request with a current user
// that you'd wish to check permissions for,
// pass that user to the "create" method:
$ bouncer = Bouncer:: create ( $ user );
Si vous utilisez l'injection de dépendances dans votre application, vous pouvez enregistrer l'instance Bouncer
en tant que singleton dans le conteneur :
use Silber Bouncer Bouncer ;
use Illuminate Container Container ;
Container:: getInstance ()-> singleton (Bouncer::class, function () {
return Bouncer:: create ();
});
Vous pouvez désormais injecter Bouncer
dans n'importe quelle classe qui en a besoin.
La méthode create
crée une instance Bouncer
avec des valeurs par défaut raisonnables. Pour le personnaliser entièrement, utilisez la méthode make
pour obtenir une instance d'usine. Appelez create()
sur la fabrique pour créer l'instance Bouncer
:
use Silber Bouncer Bouncer ;
$ bouncer = Bouncer:: make ()
-> withCache ( $ customCacheInstance )
-> create ();
Consultez la classe Factory
pour voir toutes les personnalisations disponibles.
Définissez le modèle utilisé comme modèle utilisateur dans votre application :
$ bouncer -> useUserModel (User::class);
Pour une configuration supplémentaire, consultez la section Configuration ci-dessous.
Par défaut, les requêtes de Bouncer sont mises en cache pour la requête en cours. Pour de meilleures performances, vous souhaiterez peut-être activer la mise en cache des requêtes croisées.
L’ajout de rôles et de capacités aux utilisateurs est extrêmement simple. Vous n’êtes pas obligé de créer un rôle ou une capacité à l’avance. Passez simplement le nom du rôle/capacité, et Bouncer le créera s'il n'existe pas.
Remarque : les exemples ci-dessous utilisent tous la façade
Bouncer
. Si vous n'utilisez pas de façades, vous pouvez injecter une instance deSilberBouncerBouncer
dans votre classe.
Créons un rôle appelé admin
et donnons-lui la possibilité de ban-users
de notre site :
Bouncer:: allow ( ' admin ' )-> to ( ' ban-users ' );
C'est ça. Dans les coulisses, Bouncer créera pour vous à la fois un modèle Role
et un modèle Ability
.
Si vous souhaitez ajouter des attributs supplémentaires au rôle/capacité, comme un titre lisible par l'homme, vous pouvez les créer manuellement à l'aide des méthodes role
et ability
de la classe Bouncer
:
$ admin = Bouncer:: role ()-> firstOrCreate ([
' name ' => ' admin ' ,
' title ' => ' Administrator ' ,
]);
$ ban = Bouncer:: ability ()-> firstOrCreate ([
' name ' => ' ban-users ' ,
' title ' => ' Ban users ' ,
]);
Bouncer:: allow ( $ admin )-> to ( $ ban );
Pour maintenant donner le rôle admin
à un utilisateur, dites simplement au videur que l'utilisateur donné doit se voir attribuer le rôle d'administrateur :
Bouncer:: assign ( ' admin ' )-> to ( $ user );
Alternativement, vous pouvez appeler la méthode assign
directement sur l'utilisateur :
$ user -> assign ( ' admin ' );
Parfois, vous souhaiterez peut-être donner directement une capacité à un utilisateur, sans utiliser de rôle :
Bouncer:: allow ( $ user )-> to ( ' ban-users ' );
Ici aussi, vous pouvez accomplir la même chose directement depuis l'utilisateur :
$ user -> allow ( ' ban-users ' );
Parfois, vous souhaiterez peut-être restreindre une capacité à un type de modèle spécifique. Passez simplement le nom du modèle comme deuxième argument :
Bouncer:: allow ( $ user )-> to ( ' edit ' , Post::class);
Si vous souhaitez limiter la possibilité à une instance de modèle spécifique, transmettez plutôt le modèle réel :
Bouncer:: allow ( $ user )-> to ( ' edit ' , $ post );
Utilisez la méthode toOwn
pour permettre aux utilisateurs de gérer leurs propres modèles :
Bouncer:: allow ( $ user )-> toOwn (Post::class);
Désormais, lors de la vérification à la porte si l'utilisateur peut effectuer une action sur une publication donnée, l' user_id
de la publication sera comparé à l' id
de l'utilisateur connecté (cela peut être personnalisé). S'ils correspondent, la porte autorisera l'action.
Ce qui précède accordera toutes les capacités sur les modèles « possédés » par un utilisateur. Vous pouvez restreindre les capacités en faisant suivre d'un appel à la méthode to
:
Bouncer:: allow ( $ user )-> toOwn (Post::class)-> to ( ' view ' );
// Or pass it an array of abilities:
Bouncer:: allow ( $ user )-> toOwn (Post::class)-> to ([ ' view ' , ' update ' ]);
Vous pouvez également permettre aux utilisateurs de posséder tous types de modèles dans votre application :
Bouncer:: allow ( $ user )-> toOwnEverything ();
// And to restrict ownership to a given ability
Bouncer:: allow ( $ user )-> toOwnEverything ()-> to ( ' view ' );
Le videur peut également retirer un rôle précédemment attribué à un utilisateur :
Bouncer:: retract ( ' admin ' )-> from ( $ user );
Ou faites-le directement sur l'utilisateur :
$ user -> retract ( ' admin ' );
Le videur peut également supprimer une capacité précédemment accordée à un utilisateur :
Bouncer:: disallow ( $ user )-> to ( ' ban-users ' );
Ou directement sur l'utilisateur :
$ user -> disallow ( ' ban-users ' );
Remarque : si l'utilisateur a un rôle qui lui permet de
ban-users
, il aura toujours cette capacité. Pour le refuser, supprimez la capacité du rôle ou retirez le rôle de l'utilisateur.
Si la capacité a été accordée via un rôle, dites au videur de supprimer la capacité du rôle à la place :
Bouncer:: disallow ( ' admin ' )-> to ( ' ban-users ' );
Pour supprimer une capacité pour un type de modèle spécifique, transmettez son nom comme deuxième argument :
Bouncer:: disallow ( $ user )-> to ( ' delete ' , Post::class);
Attention : si l'utilisateur a la possibilité de
delete
une instance spécifique$post
, le code ci-dessus ne supprimera pas cette capacité. Vous devrez supprimer la capacité séparément - en passant le$post
réel comme deuxième argument - comme indiqué ci-dessous.
Pour supprimer une capacité pour une instance de modèle spécifique, transmettez plutôt le modèle réel :
Bouncer:: disallow ( $ user )-> to ( ' delete ' , $ post );
Remarque : la méthode
disallow
supprime uniquement les capacités qui étaient précédemment accordées à cet utilisateur/rôle. Si vous souhaitez interdire un sous-ensemble de ce qu'une capacité plus générale a autorisé, utilisez la méthodeforbid
.
Bouncer vous permet également d' forbid
une capacité donnée, pour un contrôle plus fin. Parfois, vous souhaiterez peut-être accorder à un utilisateur/rôle une capacité qui couvre un large éventail d'actions, mais restreindre ensuite un petit sous-ensemble de ces actions.
Voici quelques exemples :
Vous pouvez autoriser un utilisateur à afficher de manière générale tous les documents, mais disposer d'un document spécifique hautement classifié qu'il ne devrait pas être autorisé à afficher :
Bouncer:: allow ( $ user )-> to ( ' view ' , Document::class);
Bouncer:: forbid ( $ user )-> to ( ' view ' , $ classifiedDocument );
Vous souhaiterez peut-être autoriser vos superadmin
à tout faire dans votre application, y compris ajouter/supprimer des utilisateurs. Ensuite, vous pouvez avoir un rôle admin
qui peut tout faire en plus de gérer les utilisateurs :
Bouncer:: allow ( ' superadmin ' )-> everything ();
Bouncer:: allow ( ' admin ' )-> everything ();
Bouncer:: forbid ( ' admin ' )-> toManage (User::class);
Vous souhaiterez peut-être bannir occasionnellement des utilisateurs, en supprimant leur autorisation pour toutes les capacités. Cependant, supprimer tous leurs rôles et capacités signifierait que lorsque l'interdiction serait levée, nous devrons déterminer quels étaient leurs rôles et capacités d'origine.
Utiliser une capacité interdite signifie qu’ils peuvent conserver tous leurs rôles et capacités existants, mais ne sont toujours pas autorisés à quoi que ce soit. Nous pouvons y parvenir en créant un rôle spécial banned
, pour lequel nous interdirons tout :
Bouncer:: forbid ( ' banned ' )-> everything ();
Ensuite, chaque fois que nous souhaitons bannir un utilisateur, nous lui attribuerons le rôle banned
:
Bouncer:: assign ( ' banned ' )-> to ( $ user );
Pour supprimer l'interdiction, nous allons simplement retirer le rôle de l'utilisateur :
Bouncer:: retract ( ' banned ' )-> from ( $ user );
Comme vous pouvez le constater, les capacités interdites de Bouncer vous donnent un contrôle très précis sur les autorisations de votre application.
Pour supprimer une capacité interdite, utilisez la méthode unforbid
:
Bouncer:: unforbid ( $ user )-> to ( ' view ' , $ classifiedDocument );
Remarque : cela supprimera toute capacité précédemment interdite. Il n'autorisera pas automatiquement la capacité si elle n'est pas déjà autorisée par une autre capacité régulière accordée à cet utilisateur/rôle.
Remarque : De manière générale, vous ne devriez pas avoir besoin de vérifier directement les rôles. Il est préférable d'autoriser un rôle à certaines capacités, puis de vérifier ces capacités à la place. Si ce dont vous avez besoin est très général, vous pouvez créer des capacités très larges. Par exemple, une capacité
access-dashboard
est toujours meilleure que de vérifier directement les rôlesadmin
oueditor
. Dans les rares cas où vous souhaitez vérifier un rôle, cette fonctionnalité est disponible ici.
Le videur peut vérifier si un utilisateur a un rôle spécifique :
Bouncer:: is ( $ user )-> a ( ' moderator ' );
Si le rôle que vous vérifiez commence par une voyelle, vous souhaiterez peut-être utiliser la méthode an
alias :
Bouncer:: is ( $ user )-> an ( ' admin ' );
A l'inverse, vous pouvez également vérifier si un utilisateur n'a pas un rôle spécifique :
Bouncer:: is ( $ user )-> notA ( ' moderator ' );
Bouncer:: is ( $ user )-> notAn ( ' admin ' );
Vous pouvez vérifier si un utilisateur possède l'un des nombreux rôles suivants :
Bouncer:: is ( $ user )-> a ( ' moderator ' , ' editor ' );
Vous pouvez également vérifier si l'utilisateur dispose de tous les rôles attribués :
Bouncer:: is ( $ user )-> all ( ' editor ' , ' moderator ' );
Vous pouvez également vérifier si un utilisateur n'a aucun des rôles donnés :
Bouncer:: is ( $ user )-> notAn ( ' editor ' , ' moderator ' );
Ces contrôles peuvent également être effectués directement sur l'utilisateur :
$ user -> isAn ( ' admin ' );
$ user -> isA ( ' subscriber ' );
$ user -> isNotAn ( ' admin ' );
$ user -> isNotA ( ' subscriber ' );
$ user -> isAll ( ' editor ' , ' moderator ' );
Vous pouvez interroger vos utilisateurs selon s'ils ont un rôle donné :
$ users = User:: whereIs ( ' admin ' )-> get ();
Vous pouvez également transmettre plusieurs rôles pour rechercher des utilisateurs possédant l'un des rôles donnés :
$ users = User:: whereIs ( ' superadmin ' , ' admin ' )-> get ();
Pour rechercher des utilisateurs disposant de tous les rôles donnés, utilisez la méthode whereIsAll
:
$ users = User:: whereIsAll ( ' sales ' , ' marketing ' )-> get ();
Vous pouvez obtenir tous les rôles d'un utilisateur directement à partir du modèle utilisateur :
$ roles = $ user -> getRoles ();
Vous pouvez obtenir toutes les capacités d'un utilisateur directement à partir du modèle utilisateur :
$ abilities = $ user -> getAbilities ();
Cela renverra une collection des capacités autorisées de l'utilisateur, y compris toutes les capacités accordées à l'utilisateur via ses rôles.
Vous pouvez également obtenir une liste de capacités qui ont été explicitement interdites :
$ forbiddenAbilities = $ user -> getForbiddenAbilities ();
L'autorisation des utilisateurs est gérée directement à Laravel's Gate
ou sur le modèle utilisateur ( $user->can($ability)
).
Pour plus de commodité, la classe Bouncer
fournit ces méthodes passthrough :
Bouncer:: can ( $ ability );
Bouncer:: can ( $ ability , $ model );
Bouncer:: canAny ( $ abilities );
Bouncer:: canAny ( $ abilities , $ model );
Bouncer:: cannot ( $ ability );
Bouncer:: cannot ( $ ability , $ model );
Bouncer:: authorize ( $ ability );
Bouncer:: authorize ( $ ability , $ model );
Ceux-ci appellent directement leurs méthodes équivalentes sur la classe Gate
.
Bouncer n'ajoute pas ses propres directives de lame. Puisque Bouncer fonctionne directement avec la porte de Laravel, utilisez simplement sa directive @can
pour vérifier les capacités de l'utilisateur actuel :
@can ('update', $post)
< a href =" {{ route('post.update', $post) }} " > Edit Post </ a >
@endcan
Étant donné que la vérification directe des rôles n'est généralement pas recommandée, Bouncer n'est pas livré avec une directive distincte pour cela. Si vous insistez toujours pour vérifier les rôles, vous pouvez le faire en utilisant la directive générale @if
:
@ if ( $ user -> isAn ( ' admin ' ))
//
@endif
Toutes les requêtes exécutées par Bouncer sont mises en cache pour la requête en cours. Si vous activez la mise en cache des requêtes croisées, le cache persistera dans différentes requêtes.
Chaque fois que vous en avez besoin, vous pouvez actualiser entièrement le cache du videur :
Bouncer:: refresh ();
Remarque : l'actualisation complète du cache pour tous les utilisateurs utilise des balises de cache si elles sont disponibles. Tous les pilotes de cache ne prennent pas en charge cela. Reportez-vous à la documentation de Laravel pour voir si votre pilote prend en charge les balises de cache. Si votre pilote ne prend pas en charge les balises de cache, l'appel de
refresh
peut être un peu lent, en fonction du nombre d'utilisateurs de votre système.
Alternativement, vous pouvez actualiser le cache uniquement pour un utilisateur spécifique :
Bouncer:: refreshFor ( $ user );
Remarque : lors de l'utilisation d'étendues multi-tenant, cela actualisera uniquement le cache pour l'utilisateur dans le contexte de l'étendue actuelle. Pour effacer les données mises en cache pour le même utilisateur dans un contexte de portée différent, elles doivent être appelées depuis cette portée.
Bouncer prend entièrement en charge les applications multi-locataires, vous permettant d'intégrer de manière transparente les rôles et les capacités de Bouncer pour tous les locataires au sein de la même application.
Pour commencer, publiez d’abord le middleware de portée dans votre application :
php artisan vendor:publish --tag="bouncer.middleware"
Le middleware sera désormais publié sur app/Http/Middleware/ScopeBouncer.php
. Ce middleware est l'endroit où vous indiquez à Bouncer quel locataire utiliser pour la demande en cours. Par exemple, en supposant que vos utilisateurs disposent tous d’un attribut account_id
, voici à quoi ressemblerait votre middleware :
public function handle ( $ request , Closure $ next )
{
$ tenantId = $ request -> user ()-> account_id ;
Bouncer:: scope ()-> to ( $ tenantId );
return $ next ( $ request );
}
Vous êtes bien sûr libre de modifier ce middleware pour l'adapter aux besoins de votre application, comme extraire les informations du locataire d'un sous-domaine, etc.
Maintenant que le middleware est en place, assurez-vous de l'enregistrer dans votre noyau HTTP :
protected $ middlewareGroups = [
' web ' => [
// Keep the existing middleware here, and add this:
App Http Middleware ScopeBouncer::class,
]
];
Toutes les requêtes de Bouncer seront désormais limitées au locataire donné.
En fonction de la configuration de votre application, vous ne souhaiterez peut-être pas que toutes les requêtes soient limitées au locataire actuel. Par exemple, vous pouvez disposer d'un ensemble fixe de rôles/capacités qui sont les mêmes pour tous les locataires et permettre uniquement à vos utilisateurs de contrôler quels utilisateurs se voient attribuer quels rôles et quels rôles ont quelles capacités. Pour y parvenir, vous pouvez indiquer à la portée de Bouncer de couvrir uniquement les relations entre les modèles de Bouncer, mais pas les modèles eux-mêmes :
Bouncer:: scope ()-> to ( $ tenantId )-> onlyRelations ();
De plus, votre application peut même ne pas permettre à ses utilisateurs de contrôler les capacités dont dispose un rôle donné. Dans ce cas, indiquez à la portée de Bouncer d'exclure les capacités de rôle de la portée, afin que ces relations restent globales pour tous les locataires :
Bouncer:: scope ()-> to ( $ tenantId )-> onlyRelations ()-> dontScopeRoleAbilities ();
Si vos besoins sont encore plus spécialisés que ce qui est décrit ci-dessus, vous pouvez créer votre propre Scope
avec la logique personnalisée dont vous avez besoin :
use Silber Bouncer Contracts Scope ;
class MyScope implements Scope
{
// Whatever custom logic your app needs
}
Ensuite, chez un fournisseur de services, enregistrez votre périmètre personnalisé :
Bouncer:: scope ( new MyScope );
Bouncer appellera les méthodes sur l'interface Scope
à différents moments de son exécution. Vous êtes libre de les gérer en fonction de vos besoins spécifiques.
Bouncer est livré avec des paramètres par défaut raisonnables, donc la plupart du temps, aucune configuration ne devrait être nécessaire. Pour un contrôle plus fin, Bouncer peut être personnalisé en appelant diverses méthodes de configuration sur la classe Bouncer
.
Si vous n'utilisez qu'une ou deux de ces options de configuration, vous pouvez les coller dans la méthode boot
de votre AppServiceProvider
principal. S'ils commencent à croître, vous pouvez créer une classe BouncerServiceProvider
distincte dans votre répertoire app/Providers
(n'oubliez pas de l'enregistrer dans le tableau de configuration providers
).
Par défaut, toutes les requêtes exécutées par Bouncer sont mises en cache pour la requête en cours. Pour de meilleures performances, vous souhaiterez peut-être utiliser la mise en cache des requêtes croisées :
Bouncer:: cache ();
Attention : si vous activez la mise en cache des requêtes croisées, vous êtes responsable d'actualiser le cache chaque fois que vous apportez des modifications aux rôles/capacités de l'utilisateur. Pour savoir comment actualiser le cache, lisez Actualiser le cache.
Au contraire, vous pouvez parfois souhaiter désactiver complètement le cache, même au sein d'une même requête :
Bouncer:: dontCache ();
Ceci est particulièrement utile dans les tests unitaires, lorsque vous souhaitez exécuter des assertions sur des rôles/capacités qui viennent d'être accordés.
Pour modifier les noms des tables de base de données utilisées par Bouncer, transmettez un tableau associatif à la méthode tables
. Les clés doivent être les noms de table par défaut de Bouncer et les valeurs doivent être les noms de table que vous souhaitez utiliser. Vous n'êtes pas obligé de transmettre tous les noms de tables ; uniquement ceux que vous souhaitez modifier.
Bouncer:: tables ([
' abilities ' => ' my_abilities ' ,
' permissions ' => ' granted_abilities ' ,
]);
La migration publiée de Bouncer utilise les noms de table de cette configuration, alors assurez-vous de les avoir en place avant d'exécuter la migration.
Vous pouvez facilement étendre les modèles Role
et Ability
intégrés de Bouncer :
namespace App Models ;
use Silber Bouncer Database Ability as BouncerAbility ;
class Ability extends BouncerAbility
{
// custom code
}
namespace App Models ;
use Silber Bouncer Database Role as BouncerRole ;
class Role extends BouncerRole
{
// custom code
}
Alternativement, vous pouvez utiliser les traits IsAbility
et IsRole
de Bouncer sans réellement étendre les modèles de Bouncer :
namespace App Models ;
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database Concerns IsAbility ;
class Ability extends Model
{
use IsAbility;
// custom code
}
namespace App Models ;
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database Concerns IsRole ;
class Role extends Model
{
use IsRole;
// custom code
}
Si vous utilisez les traits au lieu d'étendre les modèles de Bouncer, assurez-vous de définir vous-même le nom $table
et les champs $fillable
appropriés.
Quelle que soit la méthode que vous utilisez, l'étape suivante consiste à dire à Bouncer d'utiliser vos modèles personnalisés :
Bouncer:: useAbilityModel ( App Models Ability::class);
Bouncer:: useRoleModel ( App Models Role::class);
Remarque : Eloquent détermine la clé étrangère des relations en fonction du nom du modèle parent (voir la documentation Eloquent). Pour garder les choses simples, nommez vos classes personnalisées de la même manière que celles de Bouncer :
Ability
etRole
, respectivement.Si vous devez utiliser des noms différents, veillez à mettre à jour votre fichier de migration ou à remplacer les méthodes de relation pour définir explicitement leurs clés étrangères.
Par défaut, Bouncer utilise automatiquement le modèle utilisateur du garde d'authentification par défaut.
Si vous utilisez Bouncer avec un garde autre que celui par défaut et qu'il utilise un modèle utilisateur différent, vous devez informer Bouncer du modèle utilisateur que vous souhaitez utiliser :
Bouncer:: useUserModel ( App Admin::class);
Dans Bouncer, la notion de propriété est utilisée pour permettre aux utilisateurs d'effectuer des actions sur les modèles qu'ils « possèdent ».
Par défaut, Bouncer vérifiera l' user_id
du modèle par rapport à la clé primaire de l'utilisateur actuel. Si nécessaire, cela peut être défini sur un attribut différent :
Bouncer:: ownedVia ( ' userId ' );
Si différents modèles utilisent des colonnes différentes pour la propriété, vous pouvez les enregistrer séparément :
Bouncer:: ownedVia (Post::class, ' created_by ' );
Bouncer:: ownedVia (Order::class, ' entered_by ' );
Pour un meilleur contrôle, vous pouvez passer une fermeture avec votre logique personnalisée :
Bouncer:: ownedVia (Game::class, function ( $ game , $ user ) {
return $ game -> team_id == $ user -> team_id ;
});
Il y a certains concepts dans Bouncer sur lesquels les gens continuent de poser des questions, voici donc une courte liste de certains de ces sujets :
L'ensemencement des rôles et des capacités initiaux peut être effectué dans une classe de semence Laravel classique. Commencez par créer un fichier seeder spécifique pour Bouncer :
php artisan make:seeder BouncerSeeder
Placez tous vos codes de rôles et de capacités de seeding dans la méthode run
du seeder. Voici un exemple de ce à quoi cela pourrait ressembler :
use Bouncer ;
use Illuminate Database Seeder ;
class BouncerSeeder extends Seeder
{
public function run ()
{
Bouncer:: allow ( ' superadmin ' )-> everything ();
Bouncer:: allow ( ' admin ' )-> everything ();
Bouncer:: forbid ( ' admin ' )-> toManage (User::class);
Bouncer:: allow ( ' editor ' )-> to ( ' create ' , Post::class);
Bouncer:: allow ( ' editor ' )-> toOwn (Post::class);
// etc.
}
}
Pour l'exécuter réellement, transmettez le nom de classe du seeder à l'option class
de la commande db:seed
:
php artisan db:seed --class=BouncerSeeder
scope
de Bouncer peut être utilisée pour diviser différentes parties du site, créant un silo pour chacune d'entre elles avec son propre ensemble de rôles et de capacités :
Créez un middleware ScopeBouncer
qui prend un $identifier
et le définit comme portée actuelle :
use Bouncer , Closure ;
class ScopeBouncer
{
public function handle ( $ request , Closure $ next , $ identifier )
{
Bouncer:: scope ()-> to ( $ identifier );
return $ next ( $ request );
}
}
Enregistrez ce nouveau middleware en tant que middleware de route dans votre classe HTTP Kernel :
protected $ routeMiddleware = [
// Keep the other route middleware, and add this:
' scope-bouncer ' => App Http Middleware ScopeBouncer::class,
];
Dans votre fournisseur de services d'itinéraires, appliquez ce middleware avec un identifiant différent pour les itinéraires publics et les itinéraires du tableau de bord, respectivement :
Route:: middleware ([ ' web ' , ' scope-bouncer:1 ' ])
-> namespace ( $ this -> namespace )
-> group ( base_path ( ' routes/public.php ' ));
Route:: middleware ([ ' web ' , ' scope-bouncer:2 ' ])
-> namespace ( $ this -> namespace )
-> group ( base_path ( ' routes/dashboard.php ' ));
C'est ça. Tous les rôles et capacités seront désormais définis séparément pour chaque section de votre site. Pour affiner l’étendue de la portée, consultez Personnalisation de la portée de Bouncer.
À partir de Laravel 5.4, le jeu de caractères par défaut de la base de données est désormais utf8mb4
. Si vous utilisez des versions antérieures de certaines bases de données (MySQL inférieur à 5.7.7 ou MariaDB inférieur à 10.2.2) avec Laravel 5.4+, vous obtiendrez une erreur SQL lorsque vous tenterez de créer un index sur une colonne de chaîne. Pour résoudre ce problème, modifiez la longueur de chaîne par défaut de Laravel dans votre AppServiceProvider
:
use Illuminate Support Facades Schema ;
public function boot ()
{
Schema:: defaultStringLength ( 191 );
}
Vous pouvez en savoir plus dans cet article de Laravel News.
Les colonnes JSON sont un ajout relativement nouveau à MySQL (5.7.8) et MariaDB (10.2.7). Si vous utilisez une ancienne version de ces bases de données, vous ne pouvez pas utiliser de colonnes JSON.
La meilleure solution serait de mettre à niveau votre base de données. Si cela n'est pas possible actuellement, vous pouvez modifier votre fichier de migration publié pour utiliser une colonne text
à la place :
- $table->json('options')->nullable();
+ $table->text('options')->nullable();
bouncer:clean
La commande bouncer:clean
supprime les capacités inutilisées. L'exécution de cette commande supprimera 2 types de capacités inutilisées :
Capacités non attribuées - capacités qui ne sont attribuées à personne. Par exemple:
Bouncer:: allow ( $ user )-> to ( ' view ' , Plan::class);
Bouncer:: disallow ( $ user )-> to ( ' view ' , Plan::class);
À ce stade, la capacité « afficher les plans » n’est attribuée à personne, elle sera donc supprimée.
Remarque : selon le contexte de votre application, vous ne souhaiterez peut-être pas les supprimer. Si vous laissez vos utilisateurs gérer les capacités dans l'interface utilisateur de votre application, vous ne souhaiterez probablement pas supprimer les capacités non attribuées. Voir ci-dessous.
Capacités orphelines - capacités de modèle dont les modèles ont été supprimés :
Bouncer:: allow ( $ user )-> to ( ' delete ' , $ plan );
$ plan -> delete ();
Puisque le plan n’existe plus, la capacité n’est plus d’aucune utilité, elle sera donc supprimée.
Si vous souhaitez uniquement supprimer un type de capacité inutilisée, exécutez-le avec l'un des indicateurs suivants :
php artisan bouncer:clean --unassigned
php artisan bouncer:clean --orphaned
Si vous ne lui transmettez aucun drapeau, il supprimera les deux types de capacités inutilisées.
Pour exécuter automatiquement cette commande périodiquement, ajoutez-la à la planification du noyau de votre console :
$ schedule -> command ( ' bouncer:clean ' )-> weekly ();
// Adding abilities for users
Bouncer:: allow ( $ user )-> to ( ' ban-users ' );
Bouncer:: allow ( $ user )-> to ( ' edit ' , Post::class);
Bouncer:: allow ( $ user )-> to ( ' delete ' , $ post );
Bouncer:: allow ( $ user )-> everything ();
Bouncer:: allow ( $ user )-> toManage (Post::class);
Bouncer:: allow ( $ user )-> toManage ( $ post );
Bouncer:: allow ( $ user )-> to ( ' view ' )-> everything ();
Bouncer:: allow ( $ user )-> toOwn (Post::class);
Bouncer:: allow ( $ user )-> toOwnEverything ();
// Removing abilities uses the same syntax, e.g.
Bouncer:: disallow ( $ user )-> to ( ' delete ' , $ post );
Bouncer:: disallow ( $ user )-> toManage (Post::class);
Bouncer:: disallow ( $ user )-> toOwn (Post::class);
// Adding & removing abilities for roles
Bouncer:: allow ( ' admin ' )-> to ( ' ban-users ' );
Bouncer:: disallow ( ' admin ' )-> to ( ' ban-users ' );
// You can also forbid specific abilities with the same syntax...
Bouncer:: forbid ( $ user )-> to ( ' delete ' , $ post );
// And also remove a forbidden ability with the same syntax...
Bouncer:: unforbid ( $ user )-> to ( ' delete ' , $ post );
// Re-syncing a user's abilities
Bouncer:: sync ( $ user )-> abilities ( $ abilities );
// Assigning & retracting roles from users
Bouncer:: assign ( ' admin ' )-> to ( $ user );
Bouncer:: retract ( ' admin ' )-> from ( $ user );
// Assigning roles to multiple users by ID
Bouncer:: assign ( ' admin ' )-> to ([ 1 , 2 , 3 ]);
// Re-syncing a user's roles
Bouncer:: sync ( $ user )-> roles ( $ roles );
// Checking the current user's abilities
$ boolean = Bouncer:: can ( ' ban-users ' );
$ boolean = Bouncer:: can ( ' edit ' , Post::class);
$ boolean = Bouncer:: can ( ' delete ' , $ post );
$ boolean = Bouncer:: cannot ( ' ban-users ' );
$ boolean = Bouncer:: cannot ( ' edit ' , Post::class);
$ boolean = Bouncer:: cannot ( ' delete ' , $ post );
// Checking a user's roles
$ boolean = Bouncer:: is ( $ user )-> a ( ' subscriber ' );
$ boolean = Bouncer:: is ( $ user )-> an ( ' admin ' );
$ boolean = Bouncer:: is ( $ user )-> notA ( ' subscriber ' );
$ boolean = Bouncer:: is ( $ user )-> notAn ( ' admin ' );
$ boolean = Bouncer:: is ( $ user )-> a ( ' moderator ' , ' editor ' );
$ boolean = Bouncer:: is ( $ user )-> all ( ' moderator ' , ' editor ' );
Bouncer:: cache ();
Bouncer:: dontCache ();
Bouncer:: refresh ();
Bouncer:: refreshFor ( $ user );
Certaines de ces fonctionnalités sont également disponibles directement sur le modèle utilisateur :
$ user -> allow ( ' ban-users ' );
$ user -> allow ( ' edit ' , Post::class);
$ user -> allow ( ' delete ' , $ post );
$ user -> disallow ( ' ban-users ' );
$ user -> disallow ( ' edit ' , Post::class);
$ user -> disallow ( ' delete ' , $ post );
$ user -> assign ( ' admin ' );
$ user -> retract ( ' admin ' );
$ boolean = $ user -> isAn ( ' admin ' );
$ boolean = $ user -> isAn ( ' editor ' , ' moderator ' );
$ boolean = $ user -> isAll ( ' moderator ' , ' editor ' );
$ boolean = $ user -> isNotAn ( ' admin ' , ' moderator ' );
// Querying users by their roles
$ users = User:: whereIs ( ' superadmin ' )-> get ();
$ users = User:: whereIs ( ' superadmin ' , ' admin ' )-> get ();
$ users = User:: whereIsAll ( ' sales ' , ' marketing ' )-> get ();
$ abilities = $ user -> getAbilities ();
$ forbidden = $ user -> getForbiddenAbilities ();
Parmi les paquets bajillion que Spatie a si gracieusement accordés à la communauté, vous trouverez l'excellent paquet laravel-permission. Comme Bouncer, il s'intègre parfaitement aux contrôles de porte et d'autorisation intégrés de Laravel, mais propose un ensemble différent de choix de conception en ce qui concerne la syntaxe, la structure de la base de données et les fonctionnalités.
Bouncer est un logiciel open source sous licence MIT