PHPackages                             laraarabdev/filament-gatekeeper - 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. laraarabdev/filament-gatekeeper

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

laraarabdev/filament-gatekeeper
===============================

Advanced Role and Permission management for Laravel Filament with Spatie Permission integration, multi-guard support, HMVC modules, and performance caching.

v1.1.6(2w ago)14↓50%[5 PRs](https://github.com/LaraArabDev/filament-gatekeeper/pulls)MITPHPPHP ^8.2CI passing

Since May 13Pushed 2w agoCompare

[ Source](https://github.com/LaraArabDev/filament-gatekeeper)[ Packagist](https://packagist.org/packages/laraarabdev/filament-gatekeeper)[ Docs](https://github.com/laraarabdev/filament-gatekeeper)[ GitHub Sponsors](https://github.com/sponsors/laraarabdev)[ RSS](/packages/laraarabdev-filament-gatekeeper/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (10)Versions (14)Used By (0)

[![Filament Gatekeeper](art/banner.png)](art/banner.png)[![Latest Version on Packagist](https://camo.githubusercontent.com/b3726b14d395c4a31b8dd512981d410e50cdf02ab7ccd7594e172191f5909719/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c617261617261626465762f66696c616d656e742d676174656b65657065722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/laraarabdev/filament-gatekeeper)[![Total Downloads](https://camo.githubusercontent.com/6ffc074dbf775f403bc5cc1fa59a475613e7defb333ddbedff0dc6a51e5fa519/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c617261617261626465762f66696c616d656e742d676174656b65657065722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/laraarabdev/filament-gatekeeper)[![License](https://camo.githubusercontent.com/c21db81fa63b36df2b0e7fbfc723ec1970e6e591d2cb1108db551e28da1e4d4b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6c617261617261626465762f66696c616d656e742d676174656b65657065722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/laraarabdev/filament-gatekeeper)[![Tests](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/tests.yml/badge.svg)](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/tests.yml)[![codecov](https://camo.githubusercontent.com/6f9a90db1126e56db49b9a1688428925c8cdb639c35ddc1ef4b0d1b423159c49/68747470733a2f2f636f6465636f762e696f2f67682f6c617261617261626465762f66696c616d656e742d676174656b65657065722f6272616e63682f6d61696e2f67726170682f62616467652e737667)](https://codecov.io/gh/laraarabdev/filament-gatekeeper)[![Static Analysis](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/static-analysis.yml)[![Security Audit](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/security.yml/badge.svg)](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/security.yml)[![Mutation Testing](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/mutation-testing.yml/badge.svg)](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/mutation-testing.yml)[![Code Style](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/code-style.yml/badge.svg)](https://github.com/LaraArabDev/filament-gatekeeper/actions/workflows/code-style.yml)[![PHP](https://camo.githubusercontent.com/822eab8a807ffa96ffab64ee6098a500f2be8aa268335f2632ab4a1425f5316e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e32253230253743253230382e33253230253743253230382e342d626c75653f7374796c653d666c61742d737175617265)](https://php.net)[![Laravel](https://camo.githubusercontent.com/abb9b9598479804fa3095d3df4d6bb83d650c1260c9913956f876ec25ee5697c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31312e7825323025374325323031322e782d7265643f7374796c653d666c61742d737175617265)](https://laravel.com)[![Filament](https://camo.githubusercontent.com/f5bf12ac008f247a96d52951a7f743d34ed90c96a36ada5c9379c03801b29c19/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46696c616d656e742d352e782d6f72616e67653f7374796c653d666c61742d737175617265)](https://filamentphp.com)

**Granular role &amp; permission management for Laravel Filament 5.x — built to give you full control over every layer of your app with minimal setup.**

[![Filament Gatekeeper — Permission Management UI](art/screenshot.png)](art/screenshot.png)

Filament Gatekeeper lets you control and customize **who sees and does what** across your entire application — Filament resources, form fields, table columns, pages, widgets, relation managers, and API responses — all from one place.

```
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
composer require laraarabdev/filament-gatekeeper
php artisan gatekeeper:install
php artisan migrate
php artisan gatekeeper:sync   # auto-discovers all permissions
```

Then assign permissions to roles in the UI — no code changes needed.

**What you can control:**

- Resource access (view, create, edit, delete, restore...)
- Individual form fields — visible or editable per role
- Table columns — hide sensitive data by role
- Custom actions, widgets, pages, and relation managers
- API responses — filter fields and relations per role
- Multi-guard support (web + API)
- Super admin role that bypasses all checks

---

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#-features)
- [Requirements](#-requirements)
- [Installation](#-installation)
- [Quick Start](#-quick-start)
- [Configuration](#-configuration)
- [Default Setup Options](#-default-setup-options)
- [Usage](#-usage)
- [Auto-Discovery (Field &amp; Column Detection)](#-auto-discovery--field--column-detection)
- [Permission Management](#-permission-management)
- [API Permissions](#-api-permissions)
- [Commands](#-commands)
- [Quick Reference](#-quick-reference)
- [Contributing](#-contributing)
- [License](#-license)

---

Features
--------

[](#features)

#### Filament Admin Panel

[](#filament-admin-panel)

**Resource Permissions**Full CRUD + restore, force delete, replicate, reorder**Field Permissions**Control form field visibility and editability**Column Permissions**Control table column visibility**Action Permissions**Control custom action execution**Page Permissions**Control page access**Widget Permissions**Control widget visibility**Relation Permissions**Control relation manager access#### API &amp; Backend

[](#api--backend)

**API Middleware**Route-level permission checking**Controller Traits**Easy permission checks in controllers**API Resource Permissions**Field/relation visibility in JSON responses**Model Permissions**Permissions for models without Filament resources#### System Features

[](#system-features)

**Super Admin Bypass**Configurable super admin role that bypasses all checks**Multi-Guard Support**Web, API, and custom guards with auto-detection**HMVC Module Support**Works with `nwidart/laravel-modules`**Performance Caching**Cached permission matrix for fast lookups**Auto-Discovery**Automatically detect fields &amp; columns from 4 different sources**Localization**18 languages out of the box> **Supported Languages:** English, Arabic, French, Spanish, Portuguese, German, Italian, Dutch, Russian, Chinese, Japanese, Korean, Indonesian, Polish, Hindi, Ukrainian, Turkish, Persian

---

Requirements
------------

[](#requirements)

- **PHP** 8.2, 8.3, or 8.4
- **Laravel** 11.x or 12.x
- **Filament** 5.x (latest: 5.6.3)
- **Spatie Laravel Permission** 6.x *(must be installed and configured)*

### Compatibility Matrix

[](#compatibility-matrix)

FilamentLaravel 11Laravel 12**5.6.x** (latest stable)PHP 8.2, 8.3, 8.4PHP 8.2, 8.3, 8.4**^5.0** (any 5.x)PHP 8.2, 8.3, 8.4PHP 8.2, 8.3, 8.4> All combinations are verified in CI on every push.

---

Installation
------------

[](#installation)

```
# 1. Install & publish Spatie Permission (required dependency)
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

# 2. Install Gatekeeper
composer require laraarabdev/filament-gatekeeper
php artisan gatekeeper:install
php artisan migrate
php artisan gatekeeper:sync
```

The install command publishes the config, migrations, and updates `config/permission.php` automatically.

---

Quick Start
-----------

[](#quick-start)

### 1. Register the Plugin

[](#1-register-the-plugin)

In your Filament Panel Provider (`app/Providers/Filament/AdminPanelProvider.php`):

```
use LaraArabDev\FilamentGatekeeper\GatekeeperPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            GatekeeperPlugin::make()
                ->superAdminRole('super-admin')
                ->bypassForSuperAdmin(true)
                ->enableFieldPermissions()
                ->enableColumnPermissions()
                ->enableActionPermissions()
                ->enableRelationPermissions()
                ->navigationGroup('Access Control'),
        ]);
}
```

### 2. Add HasRoles to User Model

[](#2-add-hasroles-to-user-model)

**Option A: Extend Base Class (Recommended)**

```
use LaraArabDev\FilamentGatekeeper\Base\GatekeeperAuthenticatable;

class User extends GatekeeperAuthenticatable
{
    // HasRoles trait is automatically included!
}
```

**Option B: Use Trait Manually**

```
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}
```

### 3. Apply Permissions to Resources

[](#3-apply-permissions-to-resources)

**Option A: Extend Base Class (Recommended)**

```
use LaraArabDev\FilamentGatekeeper\Base\GatekeeperResource;

class UserResource extends GatekeeperResource
{
    protected static ?string $model = User::class;
    // All permissions work automatically!
}
```

**Option B: Use Traits**

```
use Filament\Resources\Resource;
use LaraArabDev\FilamentGatekeeper\Concerns\HasResourcePermissions;

class UserResource extends Resource
{
    use HasResourcePermissions;

    protected static ?string $model = User::class;
}
```

### 4. Sync Permissions

[](#4-sync-permissions)

```
php artisan gatekeeper:sync
```

Or use the dashboard action in the Role Resource.

### 5. Assign Roles to Users

[](#5-assign-roles-to-users)

Navigate to the **Roles** page in your Filament panel, assign permissions to roles, then assign roles to users.

---

Configuration
-------------

[](#configuration)

The configuration file is located at `config/gatekeeper.php`. Key settings:

```
return [
    'super_admin' => [
        'enabled' => true,
        'role' => 'super-admin',
    ],

    'guards' => [
        'web' => ['enabled' => true],
        'api' => ['enabled' => true],
    ],

    'field_permissions' => [
        'User' => ['email', 'password', 'salary', 'phone'],
    ],

    'column_permissions' => [
        'User' => ['email', 'phone', 'salary', 'created_at'],
    ],

    'custom_actions' => [
        'User' => ['export', 'impersonate', 'suspend'],
    ],

    'relation_permissions' => [
        'User' => ['roles', 'posts', 'orders'],
    ],

    'field_discovery' => [
        'enabled' => true,
        'sources' => ['fillable'],
    ],

    'column_discovery' => [
        'enabled' => true,
        'sources' => ['config', 'database'],
    ],
];
```

---

Default Setup Options
---------------------

[](#default-setup-options)

All options are in `config/gatekeeper.php`. Below is a complete reference of every available setting.

### Super Admin

[](#super-admin)

KeyDefaultDescription`super_admin.enabled``true`Enable super admin bypass for all permission checks`super_admin.role``'super-admin'`Role name that bypasses all checks### Guards

[](#guards)

KeyDefaultOptionsDescription`guard``'web'``'web'`, `'api'`, any guard nameDefault guard used for permission checks`guards.web.enabled``true``true`, `false`Enable web guard`guards.web.provider``'users'`Any auth providerUser provider for web guard`guards.api.enabled``true``true`, `false`Enable API guard`guards.api.provider``'users'`Any auth providerUser provider for API guard### Discovery Paths

[](#discovery-paths)

KeyDefaultDescription`discovery.discover_models``false`Auto-discover API-only models (no Filament resource)`discovery.models``['app/Models']`Paths to scan for models`discovery.resources``['app/Filament/Resources', 'app/Filament/*/Resources']`Paths to scan for Filament resources`discovery.pages``['app/Filament/Pages', 'app/Filament/*/Pages']`Paths to scan for Filament pages`discovery.widgets``['app/Filament/Widgets', 'app/Filament/*/Widgets']`Paths to scan for Filament widgets### HMVC Modules (nwidart/laravel-modules)

[](#hmvc-modules-nwidartlaravel-modules)

KeyDefaultDescription`modules.enabled``false`Enable module discovery`modules.namespace``'Modules'`Root namespace for modules`modules.path``base_path('Modules')`Root path for modules`modules.discovery_paths.models``'{module}/Models'`Model path pattern inside each module`modules.discovery_paths.resources``'{module}/Filament/Resources'`Resource path pattern`modules.discovery_paths.pages``'{module}/Filament/Pages'`Page path pattern`modules.discovery_paths.widgets``'{module}/Filament/Widgets'`Widget path pattern### Navigation

[](#navigation)

KeyDefaultDescription`navigation.group``'Access Control'`Sidebar group for Gatekeeper resources`navigation.icon``'heroicon-o-shield-check'`Icon for navigation items`navigation.sort``1`Sort order within the navigation group### Cache

[](#cache)

KeyDefaultDescription`cache.enabled``true`Enable permission caching`cache.driver``null`Cache driver (`null` = default app driver)`cache.prefix``'gatekeeper'`Cache key prefix`cache.ttl``3600`Cache TTL in seconds (1 hour)`cache.tags``['gatekeeper']`Cache tags (requires tagged driver like Redis)### Permission Generator

[](#permission-generator)

KeyDefaultOptionsDescription`generator.snake_case``true``true`, `false`Use snake\_case names (`view_any_user` vs `viewAnyUser`)`generator.separator``'_'`Any stringSeparator between permission parts`generator.include_guard``false``true`, `false`Append guard name to permission (e.g. `view_any_user_web`)### Exclusion Lists

[](#exclusion-lists)

KeyDefaultDescription`excluded_models``[]`Models to skip during permission discovery`excluded_resources``[]`Filament resources to skip`excluded_pages``[]`Filament pages to skip`excluded_widgets``[]`Filament widgets to skip---

Usage
-----

[](#usage)

### Resource Permissions

[](#resource-permissions)

When using `HasResourcePermissions` trait or extending `GatekeeperResource`, these methods are automatically implemented:

MethodDescription`canViewAny()`Check if user can view any records`canView($record)`Check if user can view a specific record`canCreate()`Check if user can create records`canEdit($record)`Check if user can edit a record`canDelete($record)`Check if user can delete a record`canRestore($record)`Check if user can restore a record`canForceDelete($record)`Check if user can force delete a record`canReplicate($record)`Check if user can replicate a record`canReorder()`Check if user can reorder records**Generated permissions:** `view_any_user`, `view_user`, `create_user`, `update_user`, `delete_user`, `restore_user`, `force_delete_user`, `replicate_user`, `reorder_user`

### Field Permissions

[](#field-permissions)

Control visibility and editability of form fields:

```
use LaraArabDev\FilamentGatekeeper\Concerns\HasFieldPermissions;

class UserResource extends Resource
{
    use HasFieldPermissions;

    public static function form(Schema $schema): Schema
    {
        return $schema->schema([
            TextInput::make('name'),

            TextInput::make('email')
                ->visible(fn () => static::canViewField('email'))
                ->disabled(fn () => !static::canUpdateField('email')),

            TextInput::make('salary')
                ->visible(fn () => static::canViewField('salary'))
                ->disabled(fn () => !static::canUpdateField('salary')),
        ]);
    }
}
```

**Generated permissions:** `view_field_user_email`, `update_field_user_email`, `view_field_user_salary`, `update_field_user_salary`

### Column Permissions

[](#column-permissions)

Control table column visibility:

```
use LaraArabDev\FilamentGatekeeper\Concerns\HasColumnPermissions;

class UserResource extends Resource
{
    use HasColumnPermissions;

    public static function table(Table $table): Table
    {
        return $table->columns([
            TextColumn::make('name'),

            TextColumn::make('email')
                ->visible(fn () => static::canViewColumn('email')),

            TextColumn::make('salary')
                ->visible(fn () => static::canViewColumn('salary')),
        ]);
    }
}
```

**Generated permissions:** `view_column_user_email`, `view_column_user_salary`

### Action Permissions

[](#action-permissions)

Control custom action execution:

```
use LaraArabDev\FilamentGatekeeper\Concerns\HasActionPermissions;

class UserResource extends Resource
{
    use HasActionPermissions;

    public static function table(Table $table): Table
    {
        return $table->actions([
            Action::make('export')
                ->visible(fn () => static::canExecuteAction('export')),
        ]);
    }
}
```

**Generated permissions:** `execute_user_export_action`

### Page Permissions

[](#page-permissions)

Control access to custom Filament pages:

```
use LaraArabDev\FilamentGatekeeper\Base\GatekeeperPage;

class SettingsPage extends GatekeeperPage
{
    protected static string $view = 'filament.pages.settings';
    // canAccess() works automatically
}
```

**Generated permissions:** `view_settings_page`

### Widget Permissions

[](#widget-permissions)

Control widget visibility:

```
use LaraArabDev\FilamentGatekeeper\Base\GatekeeperWidget;

class StatsOverview extends GatekeeperWidget
{
    // canView() works automatically
}
```

**Generated permissions:** `view_stats_overview_widget`

### Relation Permissions

[](#relation-permissions)

Control access to relation managers:

```
use LaraArabDev\FilamentGatekeeper\Concerns\HasRelationPermissions;

class UserResource extends Resource
{
    use HasRelationPermissions;

    public static function getRelations(): array
    {
        return static::getPermittedRelations([
            RolesRelationManager::class,
            PostsRelationManager::class,
        ]);
    }
}
```

**Generated permissions:** `view_relation_user_roles`, `view_relation_user_posts`

---

Auto-Discovery — Field &amp; Column Detection
---------------------------------------------

[](#auto-discovery--field--column-detection)

Filament Gatekeeper can **automatically discover** which fields and columns need permissions, so you don't have to list them manually. Discovery is configured separately for **fields** (form inputs) and **columns** (table display).

> **Key concept:** When you enable discovery, Gatekeeper scans your application using one or more **sources** and generates permissions for every discovered field/column. You control *which* sources are used, *what order* they're checked, and *which* fields/columns to exclude.

### How It Works

[](#how-it-works)

```
1. You enable discovery in config/gatekeeper.php
2. You choose one or more sources (e.g., fillable, database, resource)
3. Run `php artisan gatekeeper:sync`
4. Gatekeeper scans each source, merges results, removes duplicates & exclusions
5. Permissions are created in the database

```

When **multiple sources** are configured, results from all sources are **merged and deduplicated** — you will never get duplicate permissions even if the same field appears in multiple sources.

### Field Discovery

[](#field-discovery)

Field discovery detects form fields that should have `view` and `update` permissions.

```
// config/gatekeeper.php

'field_discovery' => [
    'enabled' => true,           // Set to true to activate
    'sources' => ['fillable'],   // One or more sources (see below)
],
```

#### Available Sources

[](#available-sources)

SourceHow It WorksBest For`fillable`Reads the model's `$fillable` property via reflection — no database connection or model instantiation needed.

**Recommended default.** Fast, predictable, and only includes fields you've explicitly marked as fillable in your model.

`database`Queries the database schema using `Schema::getColumnListing()` to get every column from the model's table.

Full coverage of all database columns. Use when you want permissions for every column, not just fillable ones. Pair with exclusions to filter out system columns.

`resource`Parses the PHP source code of the Filament Resource's `form()` method. Detects field names from calls like `TextInput::make('name')`, `Select::make('role')`, `DatePicker::make('birth_date')`, etc.

Matches permissions exactly to your Filament form definition. Only fields that actually appear in the UI get permissions.

`config`Reads from the `field_permissions` array in `config/gatekeeper.php`. Supports a global `'*'` key that applies to all models.

Full manual control. Use when you want to explicitly list every field per model. Useful as an override alongside other sources.

#### Source Combinations

[](#source-combinations)

You can combine multiple sources. Results are **merged and deduplicated** automatically.

```
// Only fillable fields (recommended for most apps)
'sources' => ['fillable'],

// Fillable + anything listed in config
'sources' => ['fillable', 'config'],

// Everything in the database (minus exclusions)
'sources' => ['database'],

// Only fields that appear in your Filament forms
'sources' => ['resource'],

// All sources — maximum coverage
'sources' => ['fillable', 'database', 'resource', 'config'],
```

> **Deduplication:** If `email` appears in both `$fillable` and `field_permissions` config, it only generates one set of permissions — never duplicates.

#### Excluding Fields

[](#excluding-fields)

Control which fields are **excluded** from discovery at three levels:

```
'field_discovery' => [
    // 1. Default exclusions — always removed from ALL models
    'default_excluded' => [
        'id', 'uuid', 'created_at', 'updated_at', 'deleted_at',
        'remember_token', 'email_verified_at',
        'two_factor_secret', 'two_factor_recovery_codes',
        'two_factor_confirmed_at',
    ],

    // 2. Per-model exclusions
    'excluded' => [
        '*' => ['password'],           // Excluded from EVERY model
        'User' => ['api_token'],       // Excluded from User only
        'Employee' => ['ssn'],         // Excluded from Employee only
    ],
],
```

LevelKeyScopeDefault`default_excluded`Removed from all models — system fields like `id`, `created_at`Global`excluded.*`Removed from all models — sensitive fields like `password`Per-model`excluded.ModelName`Removed from a specific model onlyAll three levels are **combined** before filtering. A field excluded at any level will not get permissions.

#### Sensitive Field Detection

[](#sensitive-field-detection)

Gatekeeper can flag fields as **sensitive** based on name patterns. This is used for reporting and UI indicators, not for blocking discovery.

```
'field_discovery' => [
    'sensitive_patterns' => [
        'password', 'secret', 'token', 'ssn',
        'social_security', 'credit_card', 'cvv', 'pin',
        'api_key', 'private_key',
    ],
],
```

A field is considered sensitive if its name **contains** any of these patterns (case-insensitive). For example, `user_password_hash` matches `password`.

#### Manual Field Permissions (No Discovery)

[](#manual-field-permissions-no-discovery)

If you prefer full manual control, keep discovery disabled and list fields explicitly:

```
'field_discovery' => [
    'enabled' => false,   // Discovery off
],

'field_permissions' => [
    '*' => ['status'],                           // All models get 'status' permissions
    'User' => ['email', 'salary', 'phone'],      // User-specific fields
    'Product' => ['price', 'cost', 'sku'],       // Product-specific fields
],
```

> **Global `*` key:** Fields listed under `'*'` are merged into every model's field list. Duplicates are automatically removed.

#### Generated Permission Names

[](#generated-permission-names)

For each discovered field, Gatekeeper generates permissions using these prefixes:

PrefixPermission NamePurpose`view``view_{model}_{field}_field`Can the user **see** this field?`update``update_{model}_{field}_field`Can the user **edit** this field?**Example:** For `User` model with field `salary`:

- `view_user_salary_field`
- `update_user_salary_field`

---

### Column Discovery

[](#column-discovery)

Column discovery detects table columns that should have `view` permissions.

```
// config/gatekeeper.php

'column_discovery' => [
    'enabled' => true,                    // Set to true to activate
    'sources' => ['config', 'database'],  // One or more sources (see below)
],
```

#### Available Sources

[](#available-sources-1)

SourceHow It WorksBest For`database`Queries the database schema using `Schema::getColumnListing()` to get every column from the model's table.

**Recommended default.** Full coverage of all displayable columns. Pair with exclusions to filter out sensitive data.

`resource`Parses the PHP source code of the Filament Resource's `table()` method. Detects column names from calls like `TextColumn::make('name')`, `BadgeColumn::make('status')`, `BooleanColumn::make('is_active')`, etc. Handles dot-notation like `user.name` (extracts `user`).

Matches permissions exactly to your Filament table definition. Only columns that actually appear in the UI get permissions.

`config`Reads from the `column_permissions` array in `config/gatekeeper.php`. Supports a global `'*'` key that applies to all models.

Full manual control. Use when you want to explicitly list every column per model.

> **Note:** Column discovery does **not** have a `fillable` source, because table columns are read-only and `$fillable` only applies to writable attributes.

#### Source Combinations

[](#source-combinations-1)

```
// Config + database (recommended)
'sources' => ['config', 'database'],

// Only columns that appear in your Filament tables
'sources' => ['resource'],

// Everything in the database (minus exclusions)
'sources' => ['database'],

// All sources — maximum coverage
'sources' => ['database', 'resource', 'config'],
```

> **Deduplication:** Same as fields — if a column appears in multiple sources, it only generates one permission.

#### Excluding Columns

[](#excluding-columns)

Control which columns are **excluded** from discovery at three levels:

```
'column_discovery' => [
    // 1. Default exclusions — always removed from ALL models
    'default_excluded' => [
        'password',
        'remember_token',
        'two_factor_secret',
        'two_factor_recovery_codes',
    ],

    // 2. Per-model exclusions
    'excluded' => [
        '*' => [],                     // Excluded from EVERY model
        'User' => ['api_token'],       // Excluded from User only
        'Employee' => ['salary'],      // Excluded from Employee only
    ],
],
```

LevelKeyScopeDefault`default_excluded`Removed from all models — sensitive columns like `password`Global`excluded.*`Removed from all models — your custom global exclusionsPer-model`excluded.ModelName`Removed from a specific model only
#### Sensitive Column Detection

[](#sensitive-column-detection)

```
'column_discovery' => [
    'sensitive_patterns' => [
        'password', 'secret', 'token', 'ssn', 'salary',
        'income', 'credit_card', 'bank_account',
        'api_key', 'private_key',
    ],
],
```

#### Manual Column Permissions (No Discovery)

[](#manual-column-permissions-no-discovery)

```
'column_discovery' => [
    'enabled' => false,   // Discovery off
],

'column_permissions' => [
    '*' => ['status'],                            // All models get 'status' column permission
    'User' => ['email', 'salary', 'created_at'],  // User-specific columns
    'Employee' => ['salary', 'performance'],       // Employee-specific columns
],
```

#### Generated Permission Names

[](#generated-permission-names-1)

For each discovered column, Gatekeeper generates permissions using this prefix:

PrefixPermission NamePurpose`view``view_{model}_{column}_column`Can the user **see** this column?**Example:** For `User` model with column `salary`:

- `view_user_salary_column`

---

### Field vs Column Discovery Comparison

[](#field-vs-column-discovery-comparison)

FeatureField DiscoveryColumn Discovery**Available sources**`fillable`, `database`, `resource`, `config``database`, `resource`, `config`**Default sources**`['fillable']``['config', 'database']`**Permission prefixes**`view`, `update``view`**Permission suffix**`_field``_column`**Supports `fillable` source**YesNo**Supports `*` global key**YesYes**Deduplication**YesYes**Exclusions**3 levels3 levels**Sensitive detection**YesYes
### Sync Commands for Discovery

[](#sync-commands-for-discovery)

```
# Sync everything (including discovered fields & columns)
php artisan gatekeeper:sync

# Sync only field permissions
php artisan gatekeeper:sync --only=fields

# Sync only column permissions
php artisan gatekeeper:sync --only=columns

# Preview what would be synced (no database writes)
php artisan gatekeeper:sync --only=fields --dry-run
php artisan gatekeeper:sync --only=columns --dry-run

# Sync for a specific guard
php artisan gatekeeper:sync --only=fields --guard=api
```

---

Permission Management
---------------------

[](#permission-management)

### Delete Permissions

[](#delete-permissions)

```
# Delete field permissions
php artisan gatekeeper:delete --type=field --model=User --force

# Delete column permissions
php artisan gatekeeper:delete --type=column --model=User --force

# Delete all model permissions
php artisan gatekeeper:delete --type=model --model=User --force

# Delete orphaned permissions
php artisan gatekeeper:delete --type=orphaned --force
```

### Sync Permissions

[](#sync-permissions)

```
# Sync all permissions
php artisan gatekeeper:sync

# Sync specific type only
php artisan gatekeeper:sync --only=resources
php artisan gatekeeper:sync --only=fields
php artisan gatekeeper:sync --only=columns
```

---

API Permissions
---------------

[](#api-permissions)

### Middleware

[](#middleware)

**Single permission check:**

```
Route::middleware(['auth:sanctum', 'gatekeeper.api:view_any_user'])->group(function () {
    Route::get('/users', [UserController::class, 'index']);
});
```

**Auto CRUD permissions:**

```
Route::middleware(['auth:sanctum', 'gatekeeper.resource:user'])->group(function () {
    Route::apiResource('users', UserController::class);
});
// Automatically checks: view_any_user, create_user, view_user, update_user, delete_user
```

Register middleware in `bootstrap/app.php` (Laravel 11+):

```
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'gatekeeper.api'      => \LaraArabDev\FilamentGatekeeper\Http\Middleware\GatekeeperApiMiddleware::class,
        'gatekeeper.resource' => \LaraArabDev\FilamentGatekeeper\Http\Middleware\GatekeeperResourceMiddleware::class,
    ]);
})
```

### Controller Permissions

[](#controller-permissions)

There are four ways to handle permissions in controllers — choose the approach that fits your needs.

---

#### Option 1: Route-Level Middleware (Recommended)

[](#option-1-route-level-middleware-recommended)

Zero controller code — apply `gatekeeper.resource:ModelName` on your `apiResource` route:

```
Route::apiResource('users', UserController::class)
    ->middleware(['auth:sanctum', 'gatekeeper.resource:User']);
```

**Auto-mapping:**

HTTP MethodURLPermission Checked`GET``/users``view_any_user``GET``/users/{id}``view_user``POST``/users``create_user``PUT` / `PATCH``/users/{id}``update_user``DELETE``/users/{id}``delete_user`Your controller stays completely clean:

```
class UserController extends Controller
{
    public function index()  { return User::paginate(); }
    public function store(Request $request) { return User::create($request->validated()); }
    public function show(User $user) { return $user; }
    public function update(Request $request, User $user) { $user->update($request->validated()); return $user; }
    public function destroy(User $user) { $user->delete(); return response()->noContent(); }
}
```

---

#### Option 2: Constructor-Level Middleware

[](#option-2-constructor-level-middleware)

Use `$this->middleware()` in the constructor to apply permissions once for the whole controller:

```
class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('gatekeeper.resource:User');

        // Or map specific methods manually
        $this->middleware('gatekeeper.api:view_any_user')->only('index');
        $this->middleware('gatekeeper.api:create_user')->only('store');
    }
}
```

---

#### Option 3: Per-Route Middleware

[](#option-3-per-route-middleware)

Use `gatekeeper.api:permission` directly on individual routes for custom or non-standard routes:

```
Route::get('/users/export', [UserController::class, 'export'])
    ->middleware(['auth:sanctum', 'gatekeeper.api:execute_user_export_action']);

Route::post('/users/bulk-delete', [UserController::class, 'bulkDelete'])
    ->middleware(['auth:sanctum', 'gatekeeper.api:delete_user']);
```

---

#### Option 4: Per-Method (Manual Trait)

[](#option-4-per-method-manual-trait)

Use `HasApiPermissions` trait for full control inside each method:

```
use LaraArabDev\FilamentGatekeeper\Concerns\HasApiPermissions;

class UserController extends Controller
{
    use HasApiPermissions;

    protected string $permissionModel = 'user';

    public function index()
    {
        $this->authorizeIndex();        // view_any_user
        return User::paginate();
    }

    public function store(Request $request)
    {
        $this->authorizeStore();        // create_user
        return User::create($request->validated());
    }

    public function show(User $user)
    {
        $this->authorizeShow($user);    // view_user
        return $user;
    }

    public function update(Request $request, User $user)
    {
        $this->authorizeUpdate($user);  // update_user
        $user->update($request->validated());
        return $user;
    }

    public function destroy(User $user)
    {
        $this->authorizeDestroy($user); // delete_user
        $user->delete();
        return response()->noContent();
    }
}
```

**Available trait methods:**

MethodPermission Checked`$this->authorizeIndex()``view_any_{model}``$this->authorizeShow($model)``view_{model}``$this->authorizeStore()``create_{model}``$this->authorizeUpdate($model)``update_{model}``$this->authorizeDestroy($model)``delete_{model}``$this->authorizeRestore($model)``restore_{model}``$this->authorizeForceDelete($model)``force_delete_{model}``$this->authorizePermission('custom_perm')`Any custom permission`$this->canIndex()`Returns `bool` for `view_any_{model}``$this->canStore()`Returns `bool` for `create_{model}``$this->canPerform('action', $model)`Returns `bool` for any action`$this->canViewField('field')`Returns `bool` for field visibility`$this->canUpdateField('field')`Returns `bool` for field editability`$this->canViewColumn('column')`Returns `bool` for column visibility`$this->canExecuteAction('action')`Returns `bool` for custom action`$this->getVisibleFields()`Returns `array` of allowed fields`$this->getVisibleColumns()`Returns `array` of allowed columns`$this->filterByPermissions($model)`Returns model data filtered by field permissions**Choosing an approach:**

ApproachWhen to useRoute middleware (`gatekeeper.resource`)Standard `apiResource` routes — cleanest, no controller codeConstructor middlewareNon-resourceful controllers or explicit per-method mapping in one placePer-route middleware (`gatekeeper.api`)Custom/non-standard routes with specific permissionsTrait per-methodWhen you need conditional logic, model-instance checks, or field/column filtering### API Resources

[](#api-resources)

```
use LaraArabDev\FilamentGatekeeper\Concerns\HasResourcePermissions;

class UserResource extends JsonResource
{
    use HasResourcePermissions;

    protected static string $permissionModel = 'user';

    public function toArray($request): array
    {
        return [
            'id'     => $this->id,
            'name'   => $this->name,
            'email'  => $this->whenCanViewColumn('email', $this->email),
            'salary' => $this->whenCanViewColumn('salary', $this->salary),
            'roles'  => $this->whenCanLoadRelation('roles', fn () => $this->roles),
        ];
    }
}
```

### Gatekeeper Facade

[](#gatekeeper-facade)

```
use LaraArabDev\FilamentGatekeeper\Facades\Gatekeeper;

// Check permission
if (Gatekeeper::can('view_user')) {
    // User has permission
}

// Authorize (throws exception if denied)
Gatekeeper::authorize('create_user');

// Check with specific guard
Gatekeeper::guard('api')->can('view_user');

// Get visible fields/columns
$fields  = Gatekeeper::getVisibleFields('User');
$columns = Gatekeeper::getVisibleColumns('User');
```

---

Commands
--------

[](#commands)

CommandDescription`gatekeeper:install`Run complete installation`gatekeeper:sync`Synchronize all permissions`gatekeeper:delete`Delete field/column/model permissions`gatekeeper:clear-cache`Clear permission cache### Creating Resources, Pages &amp; Widgets

[](#creating-resources-pages--widgets)

Filament Gatekeeper does not ship its own make commands. Use Filament's built-in commands after publishing Gatekeeper's stubs so generated classes include Gatekeeper permissions:

**1. Publish stubs (once):**

```
php artisan vendor:publish --tag=gatekeeper-stubs
```

**2. Create with Filament / Laravel:**

CommandStub UsedResult`php artisan make:filament-resource ModelName``stubs/filament/Resource.stub`Extends `GatekeeperResource``php artisan make:filament-page YourPage``stubs/filament/Page.stub`Adds `HasPagePermissions``php artisan make:filament-widget WidgetName``stubs/filament/Widget.stub`Adds `HasWidgetPermissions`---

Quick Reference
---------------

[](#quick-reference)

### Permission Types

[](#permission-types)

TypeDescriptionExample`resource`Filament resource CRUD`view_any_user``page`Filament custom pages`view_settings_page``widget`Filament widgets`view_stats_overview_widget``field`Form field access`view_field_user_email``column`Table column access`view_column_user_salary``action`Custom actions`execute_user_export_action``relation`Relation managers`view_relation_user_roles``model`API-only models`view_product`### Traits Reference

[](#traits-reference)

TraitPurpose`HasResourcePermissions`Resource CRUD permissions`HasFieldPermissions`Form field permissions`HasColumnPermissions`Table column permissions`HasActionPermissions`Custom action permissions`HasRelationPermissions`Relation manager permissions`HasPagePermissions`Page access permissions`HasWidgetPermissions`Widget visibility permissions`HasApiPermissions`Controller permission helpers### Base Classes

[](#base-classes)

ClassExtendsPurpose`GatekeeperResource``Filament\Resources\Resource`Resources with permissions`GatekeeperPage``Filament\Pages\Page`Pages with permissions`GatekeeperWidget``Filament\Widgets\Widget`Widgets with permissions`GatekeeperAuthenticatable``Authenticatable`User model with HasRoles`GatekeeperApiResource``JsonResource`API resources with permissions### Middleware

[](#middleware-1)

MiddlewareAliasPurpose`GatekeeperApiMiddleware``gatekeeper.api`Single permission check`GatekeeperResourceMiddleware``gatekeeper.resource`Auto CRUD permissions---

Contributing
------------

[](#contributing)

Please see [DEVELOPMENT.md](DEVELOPMENT.md) for details on package architecture, development setup, and contribution guidelines.

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [LaraArabDev](https://github.com/laraarabdev)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see the [License File](LICENSE) for more information.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance97

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 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

Every ~1 days

Total

8

Last Release

15d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/507841728fa3dcf4858a5231ffccfcf63ed5d687075bbec58958e59e35206f56?d=identicon)[salemB88](/maintainers/salemB88)

---

Top Contributors

[![salemB88](https://avatars.githubusercontent.com/u/61316418?v=4)](https://github.com/salemB88 "salemB88 (85 commits)")

---

Tags

filamentfilament-pluginlaravelpermissionsrbacspatiespatielaravelrolespermissionsrbacgatekeeperfilamentaccess-controlshield

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/laraarabdev-filament-gatekeeper/health.svg)

```
[![Health](https://phpackages.com/badges/laraarabdev-filament-gatekeeper/health.svg)](https://phpackages.com/packages/laraarabdev-filament-gatekeeper)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k98.0M1.3k](/packages/spatie-laravel-permission)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k3.5M115](/packages/bezhansalleh-filament-shield)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3913.7k](/packages/rawilk-profile-filament-plugin)[chiiya/filament-access-control

Admin user, role and permission management for Laravel Filament

21851.1k](/packages/chiiya-filament-access-control)[stephenjude/filament-jetstream

A Laravel starter kit built with Filament inspired by Jetstream.

17758.9k2](/packages/stephenjude-filament-jetstream)[binary-cats/laravel-rbac

Laravel enum-backed RBAC extension of spatie/laravel-permission

7835.6k](/packages/binary-cats-laravel-rbac)

PHPackages © 2026

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