PHPackages                             callcocam/inertia-rbac - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. callcocam/inertia-rbac

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

callcocam/inertia-rbac
======================

RBAC (roles &amp; permissions) para Laravel + Inertia + Vue, com ULID, catálogo de permissões como fonte única e Wayfinder para o frontend.

v0.1.0(1mo ago)00MITPHPPHP ^8.3

Since Jul 9Pushed 1mo agoCompare

[ Source](https://github.com/callcocam/inertia-rbac)[ Packagist](https://packagist.org/packages/callcocam/inertia-rbac)[ Docs](https://github.com/callcocam/inertia-rbac)[ RSS](/packages/callcocam-inertia-rbac/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (6)Versions (2)Used By (0)

callcocam/inertia-rbac
======================

[](#callcocaminertia-rbac)

RBAC (roles &amp; permissions) para **Laravel + Inertia + Vue**, construído sobre o [`spatie/laravel-permission`](https://github.com/spatie/laravel-permission) com:

- **ULID** em roles, permissions, pivots e morph keys.
- **Catálogo de permissões como fonte única** (`PermissionName`), com metadata PT-BR.
- **Controllers no pacote** (CRUD + `sync`) — o app **não** copia controller.
- **Páginas Vue no projeto** — o pacote **não traz `.vue`**; você cria os componentes no visual do seu app e as ações usam os controllers do pacote via **Wayfinder**.
- **Teams (multi-tenant) opcional**, reaproveitando a config de teams do Spatie.
- **Rollout gradual** (`rbac.enabled`) e **super-admin** por `system_name`.

> Filosofia: **visual do projeto, ações do pacote.** O HTML/estilo é 100% seu; o endpoint que processa cada ação é o controller do pacote.

Requisitos
----------

[](#requisitos)

- PHP **8.3+**
- Laravel **12+/13+**
- Inertia **v2+** (`@inertiajs/vue3`)
- `spatie/laravel-permission` **^8.0** (instalado como dependência)

---

Instalação
----------

[](#instalação)

```
composer require callcocam/inertia-rbac

# Config do pacote (só o específico do RBAC — o resto reusa o config do Spatie)
php artisan vendor:publish --tag=rbac-config

# Migrations com ULID (config-driven)
php artisan vendor:publish --tag=rbac-migrations

# (opcional) publicar o config do Spatie, se quiser editá-lo à mão
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag=permission-config

php artisan migrate

php artisan rbac:sync   # popula as permissões do catálogo

# roles de sistema (super-admin, admin) — publique o seeder e rode:
php artisan vendor:publish --tag=rbac-seeders
php artisan db:seed --class="Database\Seeders\RbacSeeder"
```

### Reaproveitando a config do Spatie

[](#reaproveitando-a-config-do-spatie)

O pacote alinha automaticamente o `config/permission.php` do Spatie no boot:

- `permission.models.role` → `Callcocam\InertiaRbac\Models\Role`
- `permission.models.permission` → `Callcocam\InertiaRbac\Models\Permission`
- quando `rbac.teams.enabled = true`: liga `permission.teams` e define `permission.column_names.team_foreign_key` a partir de `rbac.teams.foreign_key`.

Ou seja: **tabelas, colunas, cache, guards e teams core continuam no Spatie**; o `config/rbac.php` só cobre views Vue, rollout, roles protegidas, redirects e rotas.

---

Preparar o model User
---------------------

[](#preparar-o-model-user)

```
use Callcocam\InertiaRbac\Concerns\HasRbac;

class User extends Authenticatable
{
    use HasRbac; // HasRoles (Spatie) + HasUlids + isSuperAdmin()
}
```

> O `id` do User deve ser **ULID** (as morph keys do RBAC são ULID).

---

Declarar as permissões do seu app
---------------------------------

[](#declarar-as-permissões-do-seu-app)

O catálogo do pacote traz só as permissões de gestão (`roles.*`, `permissions.*`). As suas você declara em `config/rbac.php` — `PermissionName::all()` mescla as duas:

```
// config/rbac.php
'permissions' => [
    'products.viewAny', 'products.view', 'products.create', 'products.update', 'products.delete',
    'orders.viewAny', 'orders.view',
],

// opcional: classificar recursos por tipo/contexto
'type_map' => ['products' => 'catalog', 'orders' => 'sales'],
```

Depois rode `php artisan rbac:sync` (ou o botão de sync na tela de permissões).

---

Policies dos recursos do seu app
--------------------------------

[](#policies-dos-recursos-do-seu-app)

Use o trait do pacote, que já respeita o rollout (`rbac.enabled`) e o super-admin:

```
use Callcocam\InertiaRbac\Concerns\ChecksRbacPermission;

class ProductPolicy
{
    use ChecksRbacPermission;

    public function viewAny($user): bool { return $this->allowByContext($user, 'products.viewAny'); }
    public function create($user): bool  { return $this->allowByContext($user, 'products.create'); }
    // ...
}
```

O `Gate::before` de super-admin (por `system_name`) já é registrado pelo pacote.

---

Páginas Vue (criadas no seu projeto)
------------------------------------

[](#páginas-vue-criadas-no-seu-projeto)

O pacote **não traz `.vue`**. Crie os componentes nos caminhos de `config('rbac.views.*')` (default abaixo) em `resources/js/pages/`:

ConfigComponente default`rbac.views.roles.index``rbac/roles/Index``rbac.views.roles.form``rbac/roles/Form``rbac.views.permissions.index``rbac/permissions/Index``rbac.views.permissions.form``rbac/permissions/Form`Publique os stubs de referência e adapte ao visual do seu app:

```
php artisan vendor:publish --tag=rbac-stubs
# copia para base_path('stubs/inertia-rbac/...') — use como ponto de partida
```

Pontos-chave dos stubs:

- **Index**: paginator chega como **prop deferida** (`` + skeleton). Botão "Novo" com `v-if="can.create"`. Excluir por linha só com `v-if="!row.is_protected"`.
- **Form**: um único componente para create e edit; `system_name`/`name` imutáveis no edit; picker de permissões por `type`.

---

Wayfinder — ligando a UI às rotas do pacote
-------------------------------------------

[](#wayfinder--ligando-a-ui-às-rotas-do-pacote)

As ações **nunca** montam URL na mão: usam helpers gerados pelo [`laravel/wayfinder`](https://github.com/laravel/wayfinder) a partir das rotas nomeadas do pacote (`rbac.roles.*`, `rbac.permissions.*`).

```
composer require laravel/wayfinder --dev
npm install -D @laravel/vite-plugin-wayfinder
```

```
// vite.config.ts
import { wayfinder } from '@laravel/vite-plugin-wayfinder'

export default defineConfig({
  plugins: [/* laravel(), vue(), */ wayfinder({ formVariants: true })],
})
```

```
php artisan wayfinder:generate --with-form
```

```
import RoleController from '@/actions/Callcocam/InertiaRbac/Http/Controllers/RoleController'

RoleController.index.url()          // GET  index
RoleController.edit.url(role.id)    // GET  edit
//           (create)
//   (edit)
```

> Se o gerador não rastrear os controllers do vendor, veja o fallback na seção "Wayfinder" do arquivo `PROMPT.md`.

---

Mostrar/esconder (server-driven)
--------------------------------

[](#mostraresconder-server-driven)

1. **Botões por página**: cada `index` já envia `can: { create: boolean }`. Use `v-if="can.create"`. Ações de linha: `v-if="!row.is_protected"`.
2. **Menu**: decida os itens no servidor com o `PermissionResolver`:

```
use Callcocam\InertiaRbac\Support\PermissionResolver;
use Callcocam\InertiaRbac\Models\Role;

$resolver = app(PermissionResolver::class);

$menu = array_values(array_filter([
    $resolver->allows($user, 'viewAny', Role::class)
        ? ['label' => 'Papéis', 'href' => RoleController::index()] : null,
]));
```

Assim os itens não autorizados nem chegam ao cliente.

---

Configuração (`config/rbac.php`)
--------------------------------

[](#configuração-configrbacphp)

ChavePara quê`enabled`Liga/desliga a checagem (rollout gradual).`guard`Guard das roles/permissions.`connection`Conexão isolada (ex.: `landlord`), ou `null`.`teams.enabled` / `teams.foreign_key`Multi-tenant (espelha para o Spatie).`protected_roles` / `protected_permissions`Não podem ser apagadas/renomeadas.`super_admin_role``system_name` da role com `Gate::before`.`permissions` / `type_map`Catálogo do app + classificação por tipo.`views.*`Caminhos dos componentes Vue.`routes.*` / `redirect.*`Prefixo, nome, middleware e redirects.`per_page`Paginação das telas.---

Teams / multi-tenant (escopo de permissões por tenant)
------------------------------------------------------

[](#teams--multi-tenant-escopo-de-permissões-por-tenant)

> O nome "teams" vem do Spatie e pode confundir: **não** é um recurso de "grupos de usuários", e o Laravel não tem teams nativo. `rbac.teams` liga a *teams feature do Spatie* = **escopo de permissões por tenant**: adiciona uma coluna `team_foreign_key`em `roles`/`model_has_*` para você ter roles/permissões diferentes por tenant. **Não**cria tabela `teams` nem model `Team`. Por isso não conflita com nada do framework.

Está **desligado por padrão** (single-tenant). Para ligar:

```
// config/rbac.php
'teams' => [
    'enabled' => true,
    'foreign_key' => 'tenant_id',                             // coluna de tenant nas tabelas do Spatie
    'resolver' => fn ($request) => $request->user()?->tenant_id, // null = lê a foreign_key do usuário
],
```

Isso liga o middleware `SetPermissionTeamContext` no grupo de rotas e espelha `permission.teams` / `permission.column_names.team_foreign_key`. A **resolução do tenant atual é do app** (por padrão o middleware lê a `foreign_key` do usuário autenticado; use `resolver` para buscar de outro lugar).

> O Spatie suporta **um** `team_foreign_key` global. Se o app já usa a teams feature do Spatie para outra coisa, os dois precisam concordar no mesmo nome de coluna.

---

Testes
------

[](#testes)

```
composer test        # Pest + Orchestra Testbench (SQLite em memória)
composer format      # Laravel Pint
```

Licença
-------

[](#licença)

MIT. Veja [LICENSE.md](LICENSE.md).

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

47d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7425411?v=4)[Claudio Campos](/maintainers/callcocam)[@callcocam](https://github.com/callcocam)

---

Top Contributors

[![webcall](https://avatars.githubusercontent.com/u/7212238?v=4)](https://github.com/webcall "webcall (5 commits)")

---

Tags

spatielaravelulidrolespermissionsrbacinertiavuewayfinder

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/callcocam-inertia-rbac/health.svg)

```
[![Health](https://phpackages.com/badges/callcocam-inertia-rbac/health.svg)](https://phpackages.com/packages/callcocam-inertia-rbac)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

13.0k107.5M1.6k](/packages/spatie-laravel-permission)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k4.3M166](/packages/bezhansalleh-filament-shield)[wnikk/laravel-access-rules

Simple system of ACR (access control rules) for Laravel, with roles, groups, unlimited inheritance and possibility of multiplayer use.

103.8k1](/packages/wnikk-laravel-access-rules)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
