Laravel Policies: Controle de Acesso com Permissões Personalizadas

Laravel Policies: Controle de Acesso com Permissões Personalizadas

Quando seu sistema começa a crescer, ter apenas verificações básicas como “usuário pode editar este post?” pode não ser suficiente. Imagine cenários com múltiplas empresas (tenants), vários papéis (admin, editor, cliente) e permissões personalizadas. É aí que o uso avançado de Laravel Policies se torna essencial.

Neste post, você vai aprender a aplicar Policies levando em conta o papel do usuário, permissões específicas e até o tenant da empresa. Vamos criar um controle de acesso poderoso e reutilizável para qualquer tipo de sistema.


Por que usar Policies com múltiplos papéis?

Sistemas complexos exigem regras de acesso mais refinadas. Exemplo:

  • Um admin global pode editar qualquer conteúdo.
  • Um editor pode editar apenas seus próprios registros.
  • Um cliente comum pode apenas visualizar.

Ao invés de criar centenas de ifs espalhados no código, podemos centralizar tudo em Policies com regras claras e testáveis.


Preparando o ambiente (estrutura de exemplo)

Modelos:

  • User com colunas: id, role, company_id
  • Post com colunas: id, user_id, company_id, title

Exemplo de roles:

const ROLES = [
    'admin',
    'editor',
    'cliente',
];

🔨 Criando a Policy com lógica de múltiplos papéis

php artisan make:policy PostPolicy --model=Post

No método update, podemos tratar o controle assim:

public function update(User $user, Post $post)
{
    if ($user->role === 'admin') {
        return true; // Admin pode tudo
    }

    if ($user->role === 'editor' && $user->company_id === $post->company_id) {
        return $user->id === $post->user_id; // Só edita os próprios
    }

    return false; // Cliente não pode
}

Tornando isso mais escalável: usando Permissions

Se estiver usando uma tabela de permissões (ex: permissions e role_user), você pode verificar assim:

public function delete(User $user, Post $post)
{
    if ($user->hasPermission('delete_any_post')) {
        return true;
    }

    if ($user->hasPermission('delete_own_post')) {
        return $user->id === $post->user_id;
    }

    return false;
}

Dica: use pacotes como spatie/laravel-permission para controlar papéis e permissões de forma robusta.


Usando a Policy no Controller

public function destroy(Post $post)
{
    $this->authorize('delete', $post);

    $post->delete();
}

Testando suas Policies

Você pode criar testes para garantir que tudo funcione como esperado:

public function test_editor_cannot_delete_other_user_post()
{
    $editor = User::factory()->create(['role' => 'editor']);
    $post = Post::factory()->create(); // outro usuário

    $this->actingAs($editor)
        ->delete(route('posts.destroy', $post))
        ->assertForbidden();
}

Boas práticas

  • Nunca confie em verificações somente no front-end. Use sempre Policies no back-end.
  • Centralize a lógica por Model (uma Policy para cada).
  • Evite duplicar código — use Traits ou helpers para regras comuns.
  • Use middleware como can:update,post nas rotas para segurança extra.

Está pronto para levar o controle de acesso do seu sistema a outro nível? Implemente essas técnicas com Policies e deixe sua aplicação mais segura e escalável! Curtiu o conteúdo? Compartilhe com sua equipe ou deixe um comentário com dúvidas!


Show 1 Comment

1 Comment

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *