Audit Resolvers

A resolver is a class that implements the \OwenIt\Auditing\Contracts\Resolver contract, except the UserResolver, which implements OwenIt\Auditing\Contracts\UserResolver.

Each resolver must have a public static resolve() method with the appropriate logic.

The resolvers add (meta-)data to the corresponding column in the audit table. Laravel-audit ships with 4 resolvers by default which adds data to the 'url', 'ip_address', 'user_agent' and user morph columns.

Custom resolvers

Since version 13.0, you may add or remove resolvers as relevant. For example:

To create a custom resolver, create a class that implements the OwenIt\Auditing\Contracts\Resolver interface, and give it a resolve method. artisan auditing:audit-resolver will create one for you.

The auditable eloquent model is passed to the resolver so that you can set values from not only the laravel environment, but also from the specific Auditable.

Here we check if the auditable has a tenant method, which signals to us that it has a tenant_id.

<?php

namespace App\AuditResolvers;

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;
    }
} 

Now records in audit table can be filtered by tenant.

IP Address Resolver

By default, this resolver uses the Request::ip() method to get the current IP address.

Most of the times, this will get the correct value, but for applications running behind a proxy or a load balancer, IP addresses must be obtained differently.

Usually, the real IP address will be passed via an X-Forwarded-For HTTP header.

<?php
namespace App\Resolvers;

use Illuminate\Support\Facades\Request;

class IpAddressResolver implements \OwenIt\Auditing\Contracts\Resolver
{
    /**
     * {@inheritdoc}
     */
    public static function resolve(): string
    {
        return Request::header('HTTP_X_FORWARDED_FOR', '0.0.0.0');
    }
}

Set the custom IP Address resolver in the config/audit.php configuration file:

return [
    // ...

    'resolvers' = [
        // ...
        'ip_address' => App\Resolvers\IpAddressResolver::class,
        // ...
    ],

    // ...
];

URL Resolver

This resolver uses the Request::fullUrl() method to get the current URL (including any query strings).

Here's a resolver example where query strings are not included.

<?php
namespace App\Resolvers;

use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Request;

class UrlResolver implements \OwenIt\Auditing\Contracts\Resolver
{
    /**
     * {@inheritdoc}
     */
    public static function resolve(): string
    {
        if (App::runningInConsole()) {
            return 'console';
        }

        // Just the full URL without query strings
        return Request::url();
    }
}

Set the custom URL resolver in the config/audit.php configuration file:

return [
    // ...

    'resolvers' = [
        // ...
        'url' => App\Resolvers\UrlResolver::class,
        // ...
    ],

    // ...
];

User Agent Resolver

This resolver uses the Request::userAgent() method, which might return null if a User Agent isn't available.

The following example will return a default string when the User-Agent HTTP header is empty/unavailable.

<?php
namespace App\Resolvers;

use Illuminate\Support\Facades\Request;

class UserAgentResolver implements \OwenIt\Auditing\Contracts\Resolver
{
    /**
     * {@inheritdoc}
     */
    public static function resolve()
    {
        // Default to "N/A" if the User Agent isn't available
        return Request::header('User-Agent', 'N/A');
    }
}

Set the custom User Agent resolver in the config/audit.php configuration file:

return [
    // ...

    'resolvers' = [
        // ...
        'user_agent' => App\Resolvers\UserAgentResolver::class,
        // ...
    ],

    // ...
];

User Resolver

Out of the box, this resolver uses the Laravel Auth facade.

The resolve() method must return the Model instance of the currently logged user, or null if the user cannot be resolved.

When using other authentication mechanisms like Sentinel, a different resolver must be implemented.

<?php
namespace App\Resolvers;

use Cartalyst\Sentinel\Laravel\Facades\Sentinel;

class UserResolver implements \OwenIt\Auditing\Contracts\UserResolver
{
    /**
     * {@inheritdoc}
     */
    public static function resolve()
    {
        return Sentinel::check() ? Sentinel::getUser() : null;
    }
}

Set the custom User resolver in the config/audit.php configuration file:

return [
    // ...

    'user' = [
        // ...
        'resolver' => App\Resolvers\UserResolver::class,
        // ...
    ],

    // ...
];

{tip} The resolved User should implement the Illuminate\Contracts\Auth\Authenticatable interface, or at least have a getAuthIdentifier() method that returns the id.