Files
shell-leaderboard/docs/audit-trail.md
2026-03-24 17:01:12 +00:00

5.8 KiB

Audit Trail

This template includes a comprehensive audit trail system using owen-it/laravel-auditing with Filament UI integration.

What Gets Tracked

For every audited model:

  • Who - User who made the change
  • What - Model and record ID
  • When - Timestamp
  • Changes - Old values → New values
  • Where - IP address, user agent
  • Module - Which module the change belongs to

Quick Start

Audit trail is set up during make setup-laravel. To add auditing to a model:

use App\Traits\ModuleAuditable;
use OwenIt\Auditing\Contracts\Auditable;

class Product extends Model implements Auditable
{
    use ModuleAuditable;
    
    // Your model code...
}

That's it! All create, update, and delete operations are now logged.

Viewing Audit Logs

Each module has an Audit Log page in its admin section:

📦 Stock Management
   ├── Dashboard
   ├── Products
   └── Audit Log  ← Click here

The audit log shows:

  • Date/Time
  • User
  • Event type (created/updated/deleted)
  • Model
  • Old → New values

Click any entry to see full details including IP address and all changed fields.

Configuration

Per-Module Configuration

Each module has audit settings in its config file:

// Config/stock_management.php
'audit' => [
    'enabled' => true,        // Enable/disable for entire module
    'strategy' => 'all',      // 'all', 'include', 'exclude', 'none'
    'exclude' => [            // Fields to never audit
        'password',
        'remember_token',
    ],
],

Strategies

Strategy Description
all Audit all fields (default)
include Only audit fields in $auditInclude
exclude Audit all except fields in $auditExclude
none Disable auditing

Per-Model Configuration

Override in your model:

class Product extends Model implements Auditable
{
    use ModuleAuditable;

    // Only audit these fields
    protected $auditInclude = [
        'name',
        'price',
        'quantity',
    ];

    // Or exclude specific fields
    protected $auditExclude = [
        'internal_notes',
        'cache_data',
    ];
}

Audit Events

By default, these events are tracked:

  • created - New record created
  • updated - Record modified
  • deleted - Record deleted

Custom Events

Log custom events:

// In your model or service
$product->auditEvent = 'approved';
$product->isCustomEvent = true;
$product->auditCustomOld = ['status' => 'pending'];
$product->auditCustomNew = ['status' => 'approved'];
$product->save();

Querying Audits

Get audits for a record

$product = Product::find(1);
$audits = $product->audits;

// With user info
$audits = $product->audits()->with('user')->get();

Get audits by user

use OwenIt\Auditing\Models\Audit;

$userAudits = Audit::where('user_id', $userId)->get();

Get audits by module

$moduleAudits = Audit::where('tags', 'like', '%module:StockManagement%')->get();

Get recent changes

$recentChanges = Audit::latest()->take(50)->get();

UI Customization

Modify Audit Log Table

Edit Filament/Resources/AuditLogResource.php in your module:

public static function table(Table $table): Table
{
    return $table
        ->columns([
            // Add or modify columns
            Tables\Columns\TextColumn::make('custom_field'),
        ])
        ->filters([
            // Add custom filters
            Tables\Filters\Filter::make('today')
                ->query(fn ($query) => $query->whereDate('created_at', today())),
        ]);
}

Add Audit Tab to Resource

Add audit history tab to any Filament resource:

use Tapp\FilamentAuditing\RelationManagers\AuditsRelationManager;

class ProductResource extends Resource
{
    public static function getRelations(): array
    {
        return [
            AuditsRelationManager::class,
        ];
    }
}

Data Retention

Pruning Old Audits

Add to app/Console/Kernel.php:

protected function schedule(Schedule $schedule)
{
    // Delete audits older than 90 days
    $schedule->command('audit:prune --days=90')->daily();
}

Or run manually:

php artisan audit:prune --days=90

Archive Before Delete

// Export to CSV before pruning
Audit::where('created_at', '<', now()->subDays(90))
    ->each(function ($audit) {
        // Write to archive file
        Storage::append('audits/archive.csv', $audit->toJson());
    });

Disabling Auditing

Temporarily

// Disable for a single operation
$product->disableAuditing();
$product->update(['price' => 99.99]);
$product->enableAuditing();

// Or use without auditing
Product::withoutAuditing(function () {
    Product::where('category', 'sale')->update(['on_sale' => true]);
});

For Specific Model

class CacheModel extends Model implements Auditable
{
    use ModuleAuditable;

    // Disable auditing for this model
    public $auditEvents = [];
}

For Entire Module

// Config/module_name.php
'audit' => [
    'enabled' => false,
],

Troubleshooting

Audits not being created

  1. Model implements Auditable interface
  2. Model uses ModuleAuditable trait
  3. Check module config audit.enabled is true
  4. Run php artisan config:clear

User not being recorded

  1. Ensure user is authenticated when changes are made
  2. Check config/audit.php for user resolver settings

Performance concerns

  1. Use $auditInclude to limit tracked fields
  2. Set up audit pruning for old records
  3. Consider async audit processing for high-volume apps

Security

  • Audit records are read-only in the admin panel
  • No create/edit/delete actions available
  • Access controlled by module permissions
  • Sensitive fields (password, tokens) excluded by default