Bouncer é uma abordagem elegante e independente de estrutura para gerenciar funções e habilidades para qualquer aplicativo usando modelos Eloquent.
bouncer:clean
Bouncer é uma abordagem elegante e independente de estrutura para gerenciar funções e habilidades para qualquer aplicativo usando modelos Eloquent. Com uma sintaxe expressiva e fluente, ele fica fora do seu caminho o máximo possível: use quando quiser, ignore quando não quiser.
Para obter uma lista rápida e visível dos recursos do Bouncer, verifique a folha de dicas.
O Bouncer funciona bem com outras habilidades que você codificou em seu próprio aplicativo. Seu código sempre tem precedência: se o seu código permitir uma ação, o Bouncer não interferirá.
Uma vez instalado, você pode simplesmente dizer ao segurança o que deseja permitir no portão:
// 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 );
Ao verificar as habilidades no portão do Laravel, o Bouncer será automaticamente consultado. Se o Bouncer vir uma habilidade que foi concedida ao usuário atual (seja diretamente ou por meio de uma função), ele autorizará a verificação.
Nota : Bouncer v1.0.2 requer PHP 8.2+ e Laravel/Eloquent 11+.
Se você estiver no Laravel v6-v10, use o Bouncer v1.0.1. Se você estiver no Laravel v5.5-v5.8, use o Bouncer RC6.
Instale o Bouncer com o compositor:
composer require silber/bouncer
Adicione a característica do Bouncer ao seu modelo de usuário:
use Silber Bouncer Database HasRolesAndAbilities ;
class User extends Model
{
use HasRolesAndAbilities;
}
Agora, para executar as migrações do Bouncer. Primeiro publique as migrações no diretório migrations
do seu aplicativo, executando o seguinte comando:
php artisan vendor:publish --tag="bouncer.migrations"
Por fim, execute as migrações:
php artisan migrate
Sempre que você usar a fachada Bouncer
em seu código, lembre-se de adicionar esta linha às importações de seu namespace na parte superior do arquivo:
use Bouncer ;
Para obter mais informações sobre as fachadas do Laravel, consulte a documentação do Laravel.
Instale o Bouncer com o compositor:
composer require silber/bouncer
Configure o banco de dados com o componente Eloquent Capsule:
use Illuminate Database Capsule Manager as Capsule ;
$ capsule = new Capsule ;
$ capsule -> addConnection ([ /* connection config */ ]);
$ capsule -> setAsGlobal ();
Consulte a documentação do Eloquent Capsule para obter mais detalhes.
Execute as migrações por um dos seguintes métodos:
Use uma ferramenta como o vagabond para executar migrações do Laravel fora de um aplicativo Laravel. Você encontrará as migrações necessárias no arquivo stub de migrações.
Alternativamente, você pode executar o SQL bruto diretamente em seu banco de dados.
Adicione a característica do Bouncer ao seu modelo de usuário:
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database HasRolesAndAbilities ;
class User extends Model
{
use HasRolesAndAbilities;
}
Crie uma instância do 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 );
Se estiver usando injeção de dependência em seu aplicativo, você poderá registrar a instância Bouncer
como um singleton no contêiner:
use Silber Bouncer Bouncer ;
use Illuminate Container Container ;
Container:: getInstance ()-> singleton (Bouncer::class, function () {
return Bouncer:: create ();
});
Agora você pode injetar Bouncer
em qualquer classe que precise dele.
O método create
cria uma instância Bouncer
com padrões razoáveis. Para personalizá-lo totalmente, use o método make
para obter uma instância de fábrica. Chame create()
na fábrica para criar a instância Bouncer
:
use Silber Bouncer Bouncer ;
$ bouncer = Bouncer:: make ()
-> withCache ( $ customCacheInstance )
-> create ();
Confira a aula Factory
para ver todas as customizações disponíveis.
Defina qual modelo será usado como modelo de usuário em todo o seu aplicativo:
$ bouncer -> useUserModel (User::class);
Para configuração adicional, verifique a seção Configuração abaixo.
Por padrão, as consultas do Bouncer são armazenadas em cache para a solicitação atual. Para obter melhor desempenho, convém ativar o cache de solicitações cruzadas.
Adicionar funções e habilidades aos usuários é extremamente fácil. Você não precisa criar uma função ou habilidade antecipadamente. Basta passar o nome da função/habilidade e o Bouncer a criará caso ela não exista.
Nota: todos os exemplos abaixo usam a fachada
Bouncer
. Se você não usa fachadas, você pode injetar uma instância deSilberBouncerBouncer
em sua classe.
Vamos criar uma função chamada admin
e dar a ela a capacidade de ban-users
do nosso site:
Bouncer:: allow ( ' admin ' )-> to ( ' ban-users ' );
É isso. Nos bastidores, Bouncer criará um modelo Role
e um modelo Ability
para você.
Se quiser adicionar atributos adicionais à função/habilidade, como um título legível por humanos, você pode criá-los manualmente usando os métodos role
e ability
na 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 );
Para agora atribuir a função admin
a um usuário, basta dizer ao segurança que o usuário deve receber a função de administrador:
Bouncer:: assign ( ' admin ' )-> to ( $ user );
Alternativamente, você pode chamar o método assign
diretamente no usuário:
$ user -> assign ( ' admin ' );
Às vezes você pode querer dar uma habilidade diretamente a um usuário, sem usar uma função:
Bouncer:: allow ( $ user )-> to ( ' ban-users ' );
Aqui também você pode fazer o mesmo diretamente do usuário:
$ user -> allow ( ' ban-users ' );
Às vezes você pode querer restringir uma habilidade a um tipo de modelo específico. Basta passar o nome do modelo como segundo argumento:
Bouncer:: allow ( $ user )-> to ( ' edit ' , Post::class);
Se você quiser restringir a capacidade a uma instância de modelo específica, passe o modelo real:
Bouncer:: allow ( $ user )-> to ( ' edit ' , $ post );
Use o método toOwn
para permitir que os usuários gerenciem seus próprios modelos:
Bouncer:: allow ( $ user )-> toOwn (Post::class);
Agora, ao verificar no portão se o usuário pode realizar alguma ação em determinado post, o user_id
do post será comparado ao id
do usuário logado (pode ser customizado). Se corresponderem, o portão permitirá a ação.
O acima irá conceder todas as habilidades nos modelos "de propriedade" do usuário. Você pode restringir as habilidades seguindo-o com uma chamada ao método 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 ' ]);
Você também pode permitir que os usuários possuam todos os tipos de modelos em seu aplicativo:
Bouncer:: allow ( $ user )-> toOwnEverything ();
// And to restrict ownership to a given ability
Bouncer:: allow ( $ user )-> toOwnEverything ()-> to ( ' view ' );
O segurança também pode retirar uma função previamente atribuída de um usuário:
Bouncer:: retract ( ' admin ' )-> from ( $ user );
Ou faça isso diretamente no usuário:
$ user -> retract ( ' admin ' );
O segurança também pode remover uma habilidade concedida anteriormente a um usuário:
Bouncer:: disallow ( $ user )-> to ( ' ban-users ' );
Ou diretamente no usuário:
$ user -> disallow ( ' ban-users ' );
Nota: se o usuário tiver uma função que permita
ban-users
, ele ainda terá essa capacidade. Para desautorizá-lo, remova a capacidade da função ou retire a função do usuário.
Se a habilidade foi concedida através de uma função, diga ao segurança para remover a habilidade da função:
Bouncer:: disallow ( ' admin ' )-> to ( ' ban-users ' );
Para remover uma habilidade de um tipo de modelo específico, passe seu nome como segundo argumento:
Bouncer:: disallow ( $ user )-> to ( ' delete ' , Post::class);
Aviso: se o usuário puder
delete
uma instância$post
específica, o código acima não removerá essa capacidade. Você terá que remover a habilidade separadamente - passando o$post
real como um segundo argumento - conforme mostrado abaixo.
Para remover uma capacidade de uma instância de modelo específica, passe o modelo real:
Bouncer:: disallow ( $ user )-> to ( ' delete ' , $ post );
Nota : o método
disallow
remove apenas habilidades que foram fornecidas anteriormente a este usuário/função. Se você quiser proibir um subconjunto do que uma habilidade mais geral permitiu, use o métodoforbid
.
Bouncer também permite forbid
uma determinada habilidade, para um controle mais refinado. Às vezes você pode desejar conceder a um usuário/função uma habilidade que cubra uma ampla gama de ações, mas depois restringir um pequeno subconjunto dessas ações.
Aqui estão alguns exemplos:
Você pode permitir que um usuário visualize todos os documentos de maneira geral, mas tenha um documento específico altamente confidencial que ele não deveria ter permissão de visualizar:
Bouncer:: allow ( $ user )-> to ( ' view ' , Document::class);
Bouncer:: forbid ( $ user )-> to ( ' view ' , $ classifiedDocument );
Você pode permitir que seus superadmin
façam tudo em seu aplicativo, incluindo adicionar/remover usuários. Então você pode ter uma função admin
que pode fazer tudo além de gerenciar usuários:
Bouncer:: allow ( ' superadmin ' )-> everything ();
Bouncer:: allow ( ' admin ' )-> everything ();
Bouncer:: forbid ( ' admin ' )-> toManage (User::class);
Você pode querer banir usuários ocasionalmente, removendo sua permissão para todos os níveis. No entanto, remover todas as suas funções e habilidades significaria que, quando o banimento for removido, teremos que descobrir quais eram suas funções e habilidades originais.
Usar uma habilidade proibida significa que eles podem manter todas as suas funções e habilidades existentes, mas ainda assim não serem autorizados para nada. Podemos conseguir isso criando uma função banned
especial, para a qual proibiremos tudo:
Bouncer:: forbid ( ' banned ' )-> everything ();
Então, sempre que quisermos banir um usuário, atribuiremos a ele a função banned
:
Bouncer:: assign ( ' banned ' )-> to ( $ user );
Para remover o banimento, simplesmente retiraremos a função do usuário:
Bouncer:: retract ( ' banned ' )-> from ( $ user );
Como você pode ver, as habilidades proibidas do Bouncer oferecem muito controle granular sobre as permissões do seu aplicativo.
Para remover uma habilidade proibida, use o método unforbid
:
Bouncer:: unforbid ( $ user )-> to ( ' view ' , $ classifiedDocument );
Nota : isso removerá qualquer habilidade anteriormente proibida. Ela não permitirá automaticamente a habilidade se ela ainda não for permitida por uma habilidade regular diferente concedida a este usuário/função.
Nota : De modo geral, você não deve precisar verificar as funções diretamente. É melhor permitir certas habilidades para uma função e, em vez disso, verificar essas habilidades. Se o que você precisa é muito geral, você pode criar habilidades muito amplas. Por exemplo, uma capacidade
access-dashboard
é sempre melhor do que verificar diretamente as funçõesadmin
oueditor
. Para as raras ocasiões em que você deseja verificar uma função, essa funcionalidade está disponível aqui.
O segurança pode verificar se um usuário tem uma função específica:
Bouncer:: is ( $ user )-> a ( ' moderator ' );
Se a função que você está verificando começa com uma vogal, você pode usar o método an
alias:
Bouncer:: is ( $ user )-> an ( ' admin ' );
Pelo contrário, você também pode verificar se um usuário não tem uma função específica:
Bouncer:: is ( $ user )-> notA ( ' moderator ' );
Bouncer:: is ( $ user )-> notAn ( ' admin ' );
Você pode verificar se um usuário tem uma das muitas funções:
Bouncer:: is ( $ user )-> a ( ' moderator ' , ' editor ' );
Você também pode verificar se o usuário possui todas as funções fornecidas:
Bouncer:: is ( $ user )-> all ( ' editor ' , ' moderator ' );
Você também pode verificar se um usuário não possui nenhuma das funções fornecidas:
Bouncer:: is ( $ user )-> notAn ( ' editor ' , ' moderator ' );
Essas verificações também podem ser feitas diretamente no usuário:
$ user -> isAn ( ' admin ' );
$ user -> isA ( ' subscriber ' );
$ user -> isNotAn ( ' admin ' );
$ user -> isNotA ( ' subscriber ' );
$ user -> isAll ( ' editor ' , ' moderator ' );
Você pode consultar seus usuários para saber se eles têm uma determinada função:
$ users = User:: whereIs ( ' admin ' )-> get ();
Você também pode passar várias funções para consultar usuários que tenham qualquer uma das funções fornecidas:
$ users = User:: whereIs ( ' superadmin ' , ' admin ' )-> get ();
Para consultar usuários que possuem todas as funções fornecidas, use o método whereIsAll
:
$ users = User:: whereIsAll ( ' sales ' , ' marketing ' )-> get ();
Você pode obter todas as funções de um usuário diretamente do modelo de usuário:
$ roles = $ user -> getRoles ();
Você pode obter todas as habilidades de um usuário diretamente do modelo de usuário:
$ abilities = $ user -> getAbilities ();
Isso retornará uma coleção de habilidades permitidas ao usuário, incluindo quaisquer habilidades concedidas ao usuário por meio de suas funções.
Você também pode obter uma lista de habilidades que foram explicitamente proibidas:
$ forbiddenAbilities = $ user -> getForbiddenAbilities ();
A autorização de usuários é feita diretamente no Laravel's Gate
, ou no modelo de usuário ( $user->can($ability)
).
Por conveniência, a classe Bouncer
fornece estes métodos de passagem:
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 );
Eles chamam diretamente seus métodos equivalentes na classe Gate
.
Bouncer não adiciona suas próprias diretivas de blade. Como o Bouncer trabalha diretamente com o portão do Laravel, basta usar sua diretiva @can
para verificar as habilidades do usuário atual:
@can ('update', $post)
< a href =" {{ route('post.update', $post) }} " > Edit Post </ a >
@endcan
Como a verificação direta de funções geralmente não é recomendada, o Bouncer não vem com uma diretiva separada para isso. Se você ainda insiste em verificar funções, você pode fazer isso usando a diretiva geral @if
:
@ if ( $ user -> isAn ( ' admin ' ))
//
@endif
Todas as consultas executadas pelo Bouncer são armazenadas em cache para a solicitação atual. Se você ativar o cache de solicitações cruzadas, o cache persistirá em diferentes solicitações.
Sempre que precisar, você pode atualizar totalmente o cache do segurança:
Bouncer:: refresh ();
Observação: a atualização completa do cache para todos os usuários usa tags de cache, se estiverem disponíveis. Nem todos os drivers de cache suportam isso. Consulte a documentação do Laravel para ver se o seu driver suporta tags de cache. Se o seu driver não suportar tags de cache, a chamada de
refresh
poderá ser um pouco lenta, dependendo da quantidade de usuários no seu sistema.
Alternativamente, você pode atualizar o cache apenas para um usuário específico:
Bouncer:: refreshFor ( $ user );
Observação : ao usar escopos de multilocação, isso atualizará apenas o cache do usuário no contexto do escopo atual. Para limpar os dados armazenados em cache do mesmo usuário em um contexto de escopo diferente, eles devem ser chamados dentro desse escopo.
O Bouncer oferece suporte total a aplicativos multilocatários, permitindo integrar perfeitamente as funções e habilidades do Bouncer para todos os locatários no mesmo aplicativo.
Para começar, primeiro publique o middleware de escopo em seu aplicativo:
php artisan vendor:publish --tag="bouncer.middleware"
O middleware agora será publicado em app/Http/Middleware/ScopeBouncer.php
. Este middleware é onde você informa ao Bouncer qual locatário usar para a solicitação atual. Por exemplo, supondo que todos os seus usuários tenham um atributo account_id
, seu middleware ficaria assim:
public function handle ( $ request , Closure $ next )
{
$ tenantId = $ request -> user ()-> account_id ;
Bouncer:: scope ()-> to ( $ tenantId );
return $ next ( $ request );
}
É claro que você está livre para modificar esse middleware para atender às necessidades do seu aplicativo, como extrair as informações do locatário de um subdomínio e outros.
Agora com o middleware instalado, certifique-se de registrá-lo em seu Kernel HTTP:
protected $ middlewareGroups = [
' web ' => [
// Keep the existing middleware here, and add this:
App Http Middleware ScopeBouncer::class,
]
];
Todas as consultas do Bouncer agora terão como escopo o locatário determinado.
Dependendo da configuração do seu aplicativo, talvez você não queira que todas as consultas tenham como escopo o locatário atual. Por exemplo, você pode ter um conjunto fixo de funções/habilidades que são iguais para todos os locatários e permitir apenas que seus usuários controlem quais usuários recebem quais funções e quais funções têm quais habilidades. Para conseguir isso, você pode dizer ao escopo do Bouncer para definir apenas o escopo dos relacionamentos entre os modelos do Bouncer, mas não dos modelos em si:
Bouncer:: scope ()-> to ( $ tenantId )-> onlyRelations ();
Além disso, seu aplicativo pode nem permitir que seus usuários controlem quais habilidades uma determinada função possui. Nesse caso, diga ao escopo do Bouncer para excluir habilidades de função do escopo, para que esses relacionamentos permaneçam globais em todos os locatários:
Bouncer:: scope ()-> to ( $ tenantId )-> onlyRelations ()-> dontScopeRoleAbilities ();
Se suas necessidades forem ainda mais especializadas do que as descritas acima, você poderá criar seu próprio Scope
com qualquer lógica personalizada necessária:
use Silber Bouncer Contracts Scope ;
class MyScope implements Scope
{
// Whatever custom logic your app needs
}
Em seguida, em um provedor de serviços, registre seu escopo customizado:
Bouncer:: scope ( new MyScope );
O Bouncer chamará os métodos na interface Scope
em vários pontos de sua execução. Você é livre para lidar com eles de acordo com suas necessidades específicas.
O Bouncer vem com padrões razoáveis, portanto, na maioria das vezes, não deve haver necessidade de nenhuma configuração. Para um controle mais refinado, o Bouncer pode ser personalizado chamando vários métodos de configuração na classe Bouncer
.
Se você usar apenas uma ou duas dessas opções de configuração, poderá inseri-las no método boot
principal do AppServiceProvider
. Se eles começarem a crescer, você poderá criar uma classe BouncerServiceProvider
separada em seu diretório app/Providers
(lembre-se de registrá-la no array de configuração providers
).
Por padrão, todas as consultas executadas pelo Bouncer são armazenadas em cache para a solicitação atual. Para obter melhor desempenho, você pode usar o cache de solicitação cruzada:
Bouncer:: cache ();
Aviso: se você ativar o cache de solicitação cruzada, será responsável por atualizar o cache sempre que fizer alterações nas funções/habilidades do usuário. Para saber como atualizar o cache, leia atualizando o cache.
Pelo contrário, às vezes você pode querer desabilitar completamente o cache, mesmo dentro da mesma solicitação:
Bouncer:: dontCache ();
Isto é particularmente útil em testes unitários, quando você deseja executar asserções contra funções/habilidades que acabaram de ser concedidas.
Para alterar os nomes das tabelas do banco de dados usados pelo Bouncer, passe um array associativo para o método tables
. As chaves devem ser os nomes das tabelas padrão do Bouncer e os valores devem ser os nomes das tabelas que você deseja usar. Você não precisa passar todos os nomes de tabelas; apenas aqueles que você deseja alterar.
Bouncer:: tables ([
' abilities ' => ' my_abilities ' ,
' permissions ' => ' granted_abilities ' ,
]);
A migração publicada do Bouncer usa os nomes de tabela desta configuração, portanto, certifique-se de tê-los em vigor antes de executar a migração.
Você pode estender facilmente os modelos integrados Role
e Ability
do 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
}
Alternativamente, você pode usar as características IsAbility
e IsRole
do Bouncer sem realmente estender nenhum dos modelos do 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
}
Se você usar as características em vez de estender os modelos do Bouncer, certifique-se de definir você mesmo o nome $table
e os campos $fillable
adequados.
Independentemente do método usado, a próxima etapa é dizer ao Bouncer para usar seus modelos personalizados:
Bouncer:: useAbilityModel ( App Models Ability::class);
Bouncer:: useRoleModel ( App Models Role::class);
Nota : O Eloquent determina a chave estrangeira dos relacionamentos com base no nome do modelo pai (consulte a documentação do Eloquent). Para manter as coisas simples, nomeie suas classes personalizadas da mesma forma que Bouncer:
Ability
eRole
, respectivamente.Se você precisar usar nomes diferentes, atualize seu arquivo de migração ou substitua os métodos de relacionamento para definir explicitamente suas chaves estrangeiras.
Por padrão, o Bouncer usa automaticamente o modelo de usuário do protetor de autenticação padrão.
Se você estiver usando o Bouncer com uma proteção não padrão e ele usar um modelo de usuário diferente, informe ao Bouncer sobre o modelo de usuário que deseja usar:
Bouncer:: useUserModel ( App Admin::class);
No Bouncer, o conceito de propriedade é usado para permitir que os usuários executem ações nos modelos que “possuem”.
Por padrão, o Bouncer verificará o user_id
do modelo em relação à chave primária do usuário atual. Se necessário, isso pode ser definido como um atributo diferente:
Bouncer:: ownedVia ( ' userId ' );
Se modelos diferentes usarem colunas diferentes para propriedade, você poderá registrá-los separadamente:
Bouncer:: ownedVia (Post::class, ' created_by ' );
Bouncer:: ownedVia (Order::class, ' entered_by ' );
Para maior controle, você pode passar um encerramento com sua lógica personalizada:
Bouncer:: ownedVia (Game::class, function ( $ game , $ user ) {
return $ game -> team_id == $ user -> team_id ;
});
Existem alguns conceitos no Bouncer que as pessoas continuam perguntando, então aqui está uma pequena lista de alguns desses tópicos:
A propagação das funções e habilidades iniciais pode ser feita em uma classe semeadora regular do Laravel. Comece criando um arquivo seeder específico para o Bouncer:
php artisan make:seeder BouncerSeeder
Coloque todos os seus códigos de funções e habilidades de propagação no método run
do semeador. Aqui está um exemplo de como isso pode ser:
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.
}
}
Para realmente executá-lo, passe o nome da classe do semeador para a opção de class
do comando db:seed
:
php artisan db:seed --class=BouncerSeeder
scope
do Bouncer pode ser usado para separar diferentes partes do site, criando um silo para cada uma delas com seu próprio conjunto de funções e habilidades:
Crie um middleware ScopeBouncer
que pegue um $identifier
e o defina como o escopo atual:
use Bouncer , Closure ;
class ScopeBouncer
{
public function handle ( $ request , Closure $ next , $ identifier )
{
Bouncer:: scope ()-> to ( $ identifier );
return $ next ( $ request );
}
}
Registre este novo middleware como um middleware de rota em sua classe HTTP Kernel:
protected $ routeMiddleware = [
// Keep the other route middleware, and add this:
' scope-bouncer ' => App Http Middleware ScopeBouncer::class,
];
No seu provedor de serviços de rota, aplique este middleware com um identificador diferente para as rotas públicas e as rotas do painel, respectivamente:
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 ' ));
É isso. Todas as funções e habilidades agora terão escopo separado para cada seção do seu site. Para ajustar a extensão do escopo, consulte Personalizando o escopo do Bouncer.
A partir do Laravel 5.4, o conjunto de caracteres padrão do banco de dados agora é utf8mb4
. Se você estiver usando versões mais antigas de alguns bancos de dados (MySQL abaixo de 5.7.7 ou MariaDB abaixo de 10.2.2) com Laravel 5.4+, você receberá um erro SQL ao tentar criar um índice em uma coluna de string. Para corrigir isso, altere o comprimento da string padrão do Laravel em seu AppServiceProvider
:
use Illuminate Support Facades Schema ;
public function boot ()
{
Schema:: defaultStringLength ( 191 );
}
Você pode ler mais neste artigo do Laravel News.
As colunas JSON são uma adição relativamente nova ao MySQL (5.7.8) e ao MariaDB (10.2.7). Se você estiver usando uma versão mais antiga desses bancos de dados, não poderá usar colunas JSON.
A melhor solução seria atualizar seu banco de dados. Se isso não for possível no momento, você poderá alterar seu arquivo de migração publicado para usar uma coluna text
:
- $table->json('options')->nullable();
+ $table->text('options')->nullable();
bouncer:clean
O comando bouncer:clean
exclui habilidades não utilizadas. A execução deste comando excluirá 2 tipos de habilidades não utilizadas:
Habilidades não atribuídas - habilidades que não são atribuídas a ninguém. Por exemplo:
Bouncer:: allow ( $ user )-> to ( ' view ' , Plan::class);
Bouncer:: disallow ( $ user )-> to ( ' view ' , Plan::class);
Neste ponto, a capacidade de “visualizar planos” não está atribuída a ninguém, portanto será excluída.
Nota : dependendo do contexto do seu aplicativo, você pode não querer excluí-los. Se você permitir que seus usuários gerenciem habilidades na IU do seu aplicativo, provavelmente não desejará excluir habilidades não atribuídas. Veja abaixo.
Habilidades órfãs - habilidades de modelo cujos modelos foram excluídos:
Bouncer:: allow ( $ user )-> to ( ' delete ' , $ plan );
$ plan -> delete ();
Como o plano não existe mais, a habilidade não terá mais utilidade, então será excluída.
Se você deseja excluir apenas um tipo de habilidade não utilizada, execute-o com um dos seguintes sinalizadores:
php artisan bouncer:clean --unassigned
php artisan bouncer:clean --orphaned
Se você não passar nenhum sinalizador, os dois tipos de habilidades não utilizadas serão excluídos.
Para executar este comando automaticamente e periodicamente, adicione-o à programação do kernel do seu 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 );
Algumas dessas funcionalidades também estão disponíveis diretamente no modelo do usuário:
$ 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 ();
Entre os bilhões de pacotes que Spatie concedeu tão graciosamente à comunidade, você encontrará o excelente pacote laravel-permission. Assim como o Bouncer, ele se integra perfeitamente ao portão integrado e às verificações de permissão do Laravel, mas possui um conjunto diferente de opções de design quando se trata de sintaxe, estrutura e recursos do banco de dados.
Bouncer é um software de código aberto licenciado sob a licença MIT