jeylabs/laravel-audit-log

A very simple audit logger to monitor the users of your website or application

1.0.5 2020-02-06 04:54 UTC

README

The jeylabs/laravel-audit-log package provides easy to use functions to log the activities of the users of your app. It can also automatically log model events. All activity will be stored in the audit_logs table.

auditLog()->log('Look, I logged something');

You can retrieve all activity using the Jeylabs\Auditlog\Models\AuditLog model.

AuditLog::all();

Here's a more advanced example:

auditLog()
   ->performedOn($anEloquentModel)
   ->causedBy($user)
   ->withProperties(['customProperty' => 'customValue'])
   ->log('Look, I logged something');
   
$lastLoggedAudit = AuditLog::all()->last();

$lastLoggedAudit->subject; //returns an instance of an eloquent model
$lastLoggedAudit->causer; //returns an instance of your user model
$lastLoggedAudit->getExtraProperty('customProperty'); //returns 'customValue'
$lastLoggedAudit->description; //returns 'Look, I logged something'
$newsItem->name = 'updated name';
$newsItem->save();

//updating the newsItem will cause an activity being logged
$auditLog = AuditLog::all()->last();

$auditLog->description; //returns 'updated'
$auditLog->subject; //returns the instance of NewsItem that was created

Calling $auditLog->changes will return this array:

[
   'attributes' => [
        'name' => 'updated name',
        'text' => 'New Text',
    ],
    'old' => [
        'name' => 'original name',
        'text' => 'Old text',
    ],
];

Installation

You can install the package via composer:

composer require jeylabs/laravel-audit-log

Next, you must install the service provider:

// config/app.php
'providers' => [
    ...
    Jeylabs\AuditLog\AuditLogServiceProvider::class,
];

You can publish the migration with:

php artisan vendor:publish --provider="Jeylabs\AuditLog\AuditLogServiceProvider" --tag="migrations"

Note: The default migration assumes you are using integers for your model IDs. If you are using UUIDs, or some other format, adjust the format of the subject_id and causer_id fields in the published migration before continuing.

After the migration has been published you can create the audit-logs table by running the migrations:

php artisan migrate

You can optionally publish the config file with:

php artisan vendor:publish --provider="Jeylabs\AuditLog\AuditLogServiceProvider" --tag="config"

This is the contents of the published config file:

return [
    /**
     * You can specify the route prefix
     */
    'route_prefix' => 'audit-log',
    /**
     * When user visit every url update audit log
     */
    'record_visiting' => false,

    /*
     * If set to false, no audits will be saved to the database.
     */
    'enabled' => env('AUDIT_LOGGER_ENABLED', true),

    /*
     * When the clean-command is executed, all recording audits older than
     * the number of days specified here will be deleted.
     */
    'delete_records_older_than_days' => 365,

    /*
     * If no log name is passed to the audit() helper
     * we use this default log name.
     */
    'default_log_name' => 'default',

    /*
     * You can specify an auth driver here that gets user models.
     * If this is null we'll use the default Laravel auth driver.
     */
    'default_auth_driver' => null,

    /*
     * If set to true, the subject returns soft deleted models.
     */
    'subject_returns_soft_deleted_models' => false,

    /*
     * This model will be used to log audit. The only requirement is that
     * it should be or extend the \Jeylabs\AuditLog\Models\AuditLog model.
     */
    'audit_log_model' => \Jeylabs\AuditLog\Models\AuditLog::class,
    
    /*
     * If set to true, it will store lat/long to the database
     */
    'track_location' => true,

    /*
     * If set to true, it will store ip address to the database
     */
    'track_ip' => true,
];

Logging model events

A neat feature of this package is that it can automatically log events such as when a model is created, updated and deleted. To make this work all you need to do is let your model use the Jeylabs\AuditLog\Traits\LogsAudit-trait.

As a bonus the package will also log the changed attributes for all these events when setting $logAttributes property on the model.

Here's an example:

use Illuminate\Database\Eloquent\Model;
use Jeylabs\AuditLog\Traits\LogsAudit

class NewsItem extends Model
{
    use LogsAudit;

    protected $fillable = ['name', 'text'];
    
    protected static $logAttributes = ['name', 'text'];
}

Let's see what gets logged when creating an instance of that model.

$newsItem = NewsItem::create([
   'name' => 'original name',
   'text' => 'New Text'
]);

//creating the newsItem will cause an activity being logged
$auditLog = AuditLog::all()->last();

$auditLog->description; //returns 'created'
$auditLog->subject; //returns the instance of NewsItem that was created
$auditLog->changes; //returns ['attributes' => ['name' => 'original name', 'text' => 'Text']];

Now let's update some that $newsItem.

$newsItem->name = 'updated name'
$newsItem->save();

//updating the newsItem will cause an activity being logged
$auditLog = AuditLog::all()->last();

$auditLog->description; //returns 'updated'
$auditLog->subject; //returns the instance of NewsItem that was created

Calling $auditLog->changes will return this array:

[
   'attributes' => [
        'name' => 'updated name',
        'text' => 'New text',
    ],
    'old' => [
        'name' => 'original name',
        'text' => 'Old text',
    ],
];

Now, what happens when you call delete?

$newsItem->delete();

//deleting the newsItem will cause an activity being logged
$auditLog = AuditLog::all()->last();

$auditLog->description; //returns 'deleted'
$auditLog->changes; //returns ['attributes' => ['name' => 'updated name', 'text' => 'Text']];

Customizing the events being logged

By default the package will log the created, updated, deleted events. You can modify this behaviour by setting the $recordEvents property on a model.

use Illuminate\Database\Eloquent\Model;
use Jeylabs\AuditLog\Traits\CausesAudit;

class NewsItem extends Model
{
    use CausesAudit;

    //only the `deleted` event will get logged automatically
    protected static $recordEvents = ['deleted'];
}

Customizing the description

By default the package will log created, updated, deleted in the description of the activity. You can modify this text by overriding the getDescriptionForEvent function.

use Illuminate\Database\Eloquent\Model;
use Jeylabs\AuditLog\Traits\CausesAudit;

class NewsItem extends Model
{
    use CausesAudit;

    protected $fillable = ['name', 'text'];

    public function getDescriptionForEvent(string $eventName): string
    {
        return "This model has been {$eventName}";
    }

}

Let's see what happens now:

$newsItem = NewsItem::create([
   'name' => 'original name',
   'text' => 'original Text'
]);

//creating the newsItem will cause an activity being logged
$auditLog = AuditLog::all()->last();

$auditLog->description; //returns 'This model has been created'

Ignoring changes to certain attributes

If your model contains attributes whose change don't need to trigger an activity being logged you can use $ignoreChangedAttributes

use Illuminate\Database\Eloquent\Model;
use Jeylabs\AuditLog\Traits\LogsAudit;

class NewsItem extends Model
{
    use LogsAudit;
    
    protected static $ignoreChangedAttributes = ['text'];

    protected $fillable = ['name', 'text'];
    
    protected static $logAttributes = ['name', 'text'];
}

Changing text will not trigger an audit being logged.

By default the updated_at attribute is not ignored and will trigger an activity being logged. You can simply add the updated_at attribute to the $ignoreChangedAttributes array to override this behaviour.

Logging only the changed attributes

If you do not want to log every attribute in your $logAttributes variable, but only those that has actually changed after the update, you can use $logOnlyDirty

use Illuminate\Database\Eloquent\Model;
use Jeylabs\AuditLog\Traits\LogsAudit;

class NewsItem extends Model
{
    use LogsAudit;

    protected $fillable = ['name', 'text'];
    
    protected static $logAttributes = ['name', 'text'];
    
    protected static $logOnlyDirty = true;
}

Changing only name means only the name attribute will be logged in the activity, and text will be left out.

Using the CausesAudit trait

The package ships with a CausesAudit trait which can be added to any model that you use as a causer. It provides an auditLog relationship which returns all activities that are caused by the model.

If you include it in the User model you can simply retrieve all the current users activities like this:

\Auth::user()->auditLog;