Laravel Auditing

website·Indexed 33 days ago

https://laravel-auditing.com/

A robust auditing package for Laravel that allows developers to maintain control over application data by tracking changes to Eloquent models. It features customizable audit drivers, attribute modifiers, audit resolvers, and support for custom audit models and events.

Tokens
11.8K
Snippets
69
Records
84
Agent score
65%

What's inside Laravel Auditing

  1. Overview of Laravel Auditing for Eloquent models

    Laravel Auditing is a package designed to provide detailed auditing capabilities for Eloquent models. It allows developers to track changes made to records and their attributes, helping detect discrepancies, anomalies, or suspect activities within an application. The package is implemented by adding a trait to the models that need to be tracked, enabling the retrieval and display of audited data and metadata.
  2. Overview of Laravel Auditing for Eloquent models

    Laravel Auditing is a tool for Laravel developers to track every change occurring in Eloquent models, including the creation, modification, and deletion of records, as well as attribute changes. It provides a robust way to ensure data security and maintain a detailed audit trail of application data.
  3. Overview of Laravel Auditing Drivers

    Audit drivers contain the logic for handling audits of Auditable models. They are responsible for storing model attribute changes and handling the pruning of old audits when an audit threshold is configured. The package includes a Database driver by default.
  4. Retrieve audit metadata

    Audit metadata contains information about the audit event, such as the user, IP address, URL, and timestamps. You can retrieve this data as an array using getMetadata(). Passing true as the first argument returns a JSON string, and the second argument allows for json_encode() bitmask options (e.g., JSON_PRETTY_PRINT). Alternatively, metadata attributes can be accessed directly as properties on the Audit model.
    // Get as array
    var_dump($audit->getMetadata());
    
    // Get as JSON
    echo $audit->getMetadata(true, JSON_PRETTY_PRINT);
    
    // Direct property access
    echo $audit->id;
    echo $audit->event;
    echo $audit->url;
    echo $audit->ip_address;
    echo $audit->user_agent;
    echo $audit->tags;
    echo $audit->created_at->toDateTimeString();
    echo $audit->user_id;
  5. Setup the Audits database table

    Publish the migration for the audits table to the database/ directory and then run the migration command to create the table where audit records will be stored.
    php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"
    php artisan migrate
  6. Create and register a custom Audit Resolver

    Audit resolvers are classes used to add metadata to specific columns in the audit table. To create a custom resolver, implement the OwenIt\Auditing\Contracts\Resolver interface and define a public static resolve() method. You can generate a resolver using the CLI command php artisan auditing:audit-resolver.

    The resolve() method receives the auditable Eloquent model as an argument, allowing you to extract data from the model itself or the environment. To register the resolver, add it to the resolvers array in config/audit.php, where the array key corresponds to the target column name in the database.

    // 1. Create the Resolver class
    namespace App
    
    use OwenIt
    Auditing
    Contracts
    Auditable;
    use OwenIt
    Auditing
    Contracts
    Resolver;
    
    class TenantIdResolver implements Resolver
    {
        public static function resolve(Auditable $auditable = null)
        {
            if(method_exists($auditable, 'tenant')) {
                return $auditable->tenant_id;
            }
            return null;
        }
    }
    
    // 2. Register in config/audit.php
    'resolvers' => [
        'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class,
        'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class,
        'url'        => OwenIt\Auditing\Resolvers\UrlResolver::class,
        'tenant_id'  => App\AuditResolvers\TenantIdResolver::class,
    ],
  7. Cancel an audit using the Auditing event

    The OwenIt\Auditing\Events\Auditing event is fired while the auditing process is being handled. You can cancel the creation of an audit record by returning false from the handle() method of the event listener.
    namespace App\Listeners;
    
    use OwenIt\Auditing\Events\Auditing;
    
    class AuditingListener
    {
        public function handle(Auditing $event)
        {
            // Return false to cancel the audit
            if ($someCondition)
            {
                return false;
            }
        }
    }
  8. Configure Audit migrations to use UUIDs instead of auto-incrementing IDs

    If your application uses UUIDs, you must manually define the user and auditable columns in the migration instead of using the morphs() helper to ensure the ID columns are typed as UUIDs. Ensure these types match the primary keys of the referenced tables.
    // For the User
    $table->string('user_type')->nullable();
    $table->uuid('user_id')->nullable();
    $table->index([
        'user_type',
        'user_id', 
    ]);
    
    // For the Auditable model
    $table->string('auditable_type');
    $table->uuid('auditable_id');
    $table->index([
        'auditable_type',
        'auditable_id', 
    ]);
  9. Manually trigger and prune audit records using the Auditor

    The Auditor class is used to manually create and clear Audit records. While the AuditableObserver typically handles this automatically, you can manually invoke auditing using the execute() method and remove old records using the prune() method.

    Warning: If you manually call the Auditor while the model's $auditEvents property is still configured (not set to an empty array), you will create duplicate Audit records because the observer will also trigger.

    use OwenIt�Auditing�Facades�Auditor;
    
    // Manually execute an audit and then prune
    if ($audit = Auditor::execute($article)) {
        Auditor::prune($article);
    }
  10. Dispatch a custom audit event for an Auditable model

    To log custom values that do not originate from standard Eloquent events ('created', 'updated', 'deleted', 'restored', 'retrieved'), you can manually dispatch the \OwenIt\Auditing\Events\AuditCustom event. You must set the auditEvent, isCustomEvent, auditCustomOld, and auditCustomNew properties on the Auditable model before dispatching the event.
    use OwenIt\Auditing\Events\AuditCustom;
    use Illuminate\Support\Facades\Event;
    
    $article = Article::find(1);
    $article->auditEvent = 'whateverYouWant';
    $article->isCustomEvent = true;
    $article->auditCustomOld = [
        'customExample' => 'Anakin Skywalker'
    ];
    $article->auditCustomNew = [
        'customExample' => 'Darth Vader'
    ];
    
    Event::dispatch(new AuditCustom($article));
  11. Implement a custom Audit model

    Starting from version 4.1.0, you can use a custom Audit model instead of the default Illuminate\Database\Eloquent\Model. Any custom Audit model must implement the OwenIt\Auditing\Contracts\Audit interface. Most of the core auditing logic is provided by the OwenIt\Auditing\Audit trait, which should be used within the model.
  12. Upgrade Laravel Auditing from version 12.x to 13

    Version 13 introduces breaking changes to the configuration file and resolvers.

    1. Config Key Change: The resolver key has been replaced by resolvers (plural).
    2. User Resolver: The user resolver has moved from the top-level config to the user config key.
    3. Resolver Contract: Custom implementations of UrlResolver, UserAgentResolver, or IpAddressResolver must now implement the OwenIt\Auditing\Contracts\Resolver contract.
    // Custom Resolver Implementation
    class UrlResolver implements \OwenIt\Auditing\Contracts\Resolver {}
    
    // config/audit.php
    return [
        'resolvers' => [
            'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class,
            'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class,
            'url'        => OwenIt\Auditing\Resolvers\UrlResolver::class,
        ],
        'user' => [
            'morph_prefix' => 'user',
            'guards'       => ['web', 'api'],
            'resolver' => OwenIt\Auditing\Resolvers\UserResolver::class
        ],
    ];