generated from theradcoza/Laravel-Docker-Dev-Template
Initial commit
This commit is contained in:
286
docs/audit-trail.md
Normal file
286
docs/audit-trail.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# Audit Trail
|
||||
|
||||
This template includes a comprehensive audit trail system using [owen-it/laravel-auditing](https://github.com/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:
|
||||
|
||||
```php
|
||||
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:
|
||||
|
||||
```php
|
||||
// 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:
|
||||
|
||||
```php
|
||||
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:
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
$product = Product::find(1);
|
||||
$audits = $product->audits;
|
||||
|
||||
// With user info
|
||||
$audits = $product->audits()->with('user')->get();
|
||||
```
|
||||
|
||||
### Get audits by user
|
||||
|
||||
```php
|
||||
use OwenIt\Auditing\Models\Audit;
|
||||
|
||||
$userAudits = Audit::where('user_id', $userId)->get();
|
||||
```
|
||||
|
||||
### Get audits by module
|
||||
|
||||
```php
|
||||
$moduleAudits = Audit::where('tags', 'like', '%module:StockManagement%')->get();
|
||||
```
|
||||
|
||||
### Get recent changes
|
||||
|
||||
```php
|
||||
$recentChanges = Audit::latest()->take(50)->get();
|
||||
```
|
||||
|
||||
## UI Customization
|
||||
|
||||
### Modify Audit Log Table
|
||||
|
||||
Edit `Filament/Resources/AuditLogResource.php` in your module:
|
||||
|
||||
```php
|
||||
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:
|
||||
|
||||
```php
|
||||
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`:
|
||||
|
||||
```php
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// Delete audits older than 90 days
|
||||
$schedule->command('audit:prune --days=90')->daily();
|
||||
}
|
||||
```
|
||||
|
||||
Or run manually:
|
||||
|
||||
```bash
|
||||
php artisan audit:prune --days=90
|
||||
```
|
||||
|
||||
### Archive Before Delete
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
class CacheModel extends Model implements Auditable
|
||||
{
|
||||
use ModuleAuditable;
|
||||
|
||||
// Disable auditing for this model
|
||||
public $auditEvents = [];
|
||||
}
|
||||
```
|
||||
|
||||
### For Entire Module
|
||||
|
||||
```php
|
||||
// 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
|
||||
Reference in New Issue
Block a user