Looking to hire Laravel developers? Try LaraJobs

laravel-permission-audit maintained by tamas1979

Description
Professional grant/revoke audit trail and capability blocks for spatie/laravel-permission
Author
Last update
2026/08/13 03:59 (dev-master)
License
Links
Downloads
2

Comments
comments powered by Disqus

Laravel Permission Audit

A simple and reusable Laravel package for Spatie permission/role audit trails and capability blocks.

This package records who granted or revoked a permission or role, when, and why, and can block re-apply of a revoked capability until an admin lifts the block. It works alongside spatie/laravel-permission — it does not replace it.

It is not a general activity log. Use it when you need audit + block semantics for Spatie abilities.


Features

  • Audit trail: append-only history of grant / revoke / assign / remove / block / unblock
  • Capability blocks: prevent re-grant via the Auditor API while a block is active
  • Spatie event logging: optional listeners write audits for direct Spatie calls
  • Facade + service: PermissionAudit facade or inject PermissionAuditor
  • Lightweight: minimal setup, depends only on Laravel + Spatie Permission

Installation

Require the package via Composer (and Spatie Permission if you do not have it yet):

composer require tamas1979/laravel-permission-audit

Configuration

Publish the config file:

php artisan vendor:publish --provider="Tamas1979\PermissionAudit\PermissionAuditServiceProvider" --tag=permission-audit-config

The default config:

return [
    'tables' => [
        'audits' => 'permission_audits',
        'blocks' => 'permission_blocks',
    ],

    // Log direct Spatie givePermissionTo / assignRole / etc.
    'listen_spatie_events' => true,

    // Callable that returns the actor model (or null). Default: auth()->user()
    'actor_resolver' => null,

    // PermissionAuditor::grant* refuses when an active block exists
    'enforce_blocks_on_grant' => true,
];

Setup

  1. Run migrations

The package ships migrations for permission_audits and permission_blocks. Just run:

php artisan migrate
  • Migrations load automatically from the package
  • Publish them only if you need to customize:
php artisan vendor:publish --provider="Tamas1979\PermissionAudit\PermissionAuditServiceProvider" --tag=permission-audit-migrations
  1. Spatie Permission

Your user (or other subject) model must already use Spatie’s HasRoles (or equivalent). This package calls Spatie’s grant/revoke APIs under the hood.

For automatic event logging of direct Spatie calls (givePermissionTo, assignRole, …), Spatie 8+ also needs events turned on in config/permission.php:

'events_enabled' => true,

Without this, listen_spatie_events has nothing to listen to — Spatie does not dispatch attach/detach events by default.


Usage

Grant / revoke (preferred API)

use Tamas1979\PermissionAudit\Facades\PermissionAudit;
use Tamas1979\PermissionAudit\AbilityType;

// Grant with reason (audited; refuses if an active block exists)
PermissionAudit::grantPermission($user, 'products.create', reason: 'Accepted creator terms');

// Revoke and block automatic re-apply
PermissionAudit::revokePermission(
    $user,
    'products.create',
    reason: 'Repeated bad product data',
    blockReapply: true,
);

// Check before your own onboarding / self-service flow
if (PermissionAudit::isPermissionBlocked($user, 'products.create')) {
    // show “suspended — contact support”
}

// Admin lifts the block
PermissionAudit::unblock(
    $user,
    AbilityType::PERMISSION,
    'products.create',
    reason: 'Appeal accepted',
);

Roles work the same way:

PermissionAudit::assignRole($user, 'moderator', reason: 'Promoted by admin');
PermissionAudit::removeRole($user, 'moderator', reason: 'Demoted', blockReapply: false);

Automatic Spatie event logging

When listen_spatie_events is true (default) and Spatie’s permission.events_enabled is true, direct calls such as $user->givePermissionTo(...) / assignRole(...) are also written to permission_audits with source = spatie_event.

Spatie 8+ ships with events_enabled => false. Set it to true or the listener will never run.

Auditor methods silence that listener so you do not get duplicate rows.

Important: blocks vs direct Spatie

Path Audited? Block enforced?
PermissionAudit::grantPermission(...) yes (source = auditor) yes (if enforce_blocks_on_grant)
$user->givePermissionTo(...) yes (if listeners on) no — bypasses Auditor

Use the Auditor API for any flow where blocks must stick. Gate or wrap direct Spatie calls yourself if you need hard enforcement everywhere.

Tables

Table Purpose
permission_audits Append-only history
permission_blocks Active / lifted blocks

Contribution

  • Open for ideas, bug fixes, and feature requests
  • Supports Laravel 11, 12, and 13
  • Requires PHP 8.2+ and spatie/laravel-permission 6+

License

MIT