laravel-model-access-audit maintained by filipefernandes
Laravel Model Access Audit
Track, store, and visualize access and mutations of sensitive Eloquent models in enterprise applications. This package provides a Telescope-inspired dashboard for auditing with advanced relationship and field-level tracking.
Features
- Comprehensive Event Tracking: Logs
read,create,update,delete, andrestore. - Relation Auditing:
- Automatic: Detects and labels foreign key changes (e.g.,
user_id->Owner). - Reciprocal: Automatically logs the inverse change on related models (e.g., Post changed? Log on User too).
- Manual: Helper for pivot changes (
attach,detach,sync).
- Automatic: Detects and labels foreign key changes (e.g.,
- Field-Level Control: Explicitly
includeorexcludespecific attributes from logs. - Dashboard:
- Dynamic Sidebar: Lists all auditable models automatically.
- Real-time Feel: Quick reload and purge buttons.
- Diff Viewer: Premium side-by-side comparison of changes.
- Masking: Protect sensitive fields (passwords, tokens) with
[MASKED]. - Performance: Optional queued logging for high-traffic apps.
Installation
composer require filipefernandes/laravel-model-access-audit
Publish configuration and assets:
php artisan vendor:publish --provider="FilipeFernandes\ModelAccessAudit\ModelAccessAuditServiceProvider"
php artisan migrate
Usage
1. Basic Setup
Add the Auditable trait and implement the AuditableModel contract.
use FilipeFernandes\ModelAccessAudit\Traits\Auditable;
use FilipeFernandes\ModelAccessAudit\Contracts\AuditableModel;
class Document extends Model implements AuditableModel {
use Auditable;
}
2. Field-Level Auditing
Control exactly what gets logged.
class User extends Model implements AuditableModel {
use Auditable;
// Only log these fields
protected array $auditInclude = ['name', 'role'];
// OR exclude specific fields
protected array $auditExclude = ['remember_token'];
}
3. Relation Auditing
Track foreign key changes with human-readable labels. To enable Reciprocal Auditing (logging on both models), provide the inverse relationship name.
class Post extends Model implements AuditableModel {
use Auditable;
protected array $auditRelations = [
// 'foreign_key' => ['label', 'inverse_relation_on_target']
'user_id' => ['owner', 'posts'],
];
}
For ManyToMany (pivots), use the manual helper. You can pass an optional inverse relation name for reciprocal logging:
// User #12 attaches Role #3 -> Also logs on Role #3 for 'users' relation
$user->auditRelation('roles', 'attach', [3], [], 'users');
4. Masking
Mask sensitive data globally in config/audit.php or per model:
protected array $auditMasked = ['ssn_number'];
Dashboard & Security
Access the dashboard at /audit.
Authorization:
Define the viewAuditDashboard gate in your AuthServiceProvider:
Gate::define('viewAuditDashboard', function ($user) {
return $user->isSystemAdmin();
});
Retrieving Audits
1. Basic Retrieval
// Via relationship
$history = $model->audits;
// Via scopes
$logs = Audit::for($model)->latest()->get();
$logs = Audit::byUser($user)->between($start, $end)->get();
2. Timeline & History
Retrieve a human-readable stream of events or a detailed history collection.
// Returns a collection of formatted strings: "[2026-03-09] Email changed"
$timeline = $user->timeline();
// Returns a collection of Audit instances (stable id-based ordering)
$history = $user->history();
Configuration
Review config/audit.php to customize:
queue: Enable background processing.route_prefix: Change/auditto something else.log_reads: Toggle read access tracking.
License
The MIT License (MIT).