Skip to content

Commit

Permalink
Merge pull request #421 from owen-it/feat/multi-user
Browse files Browse the repository at this point in the history
[FEAT] V7 - Multi user audits
  • Loading branch information
quetzyg authored May 10, 2018
2 parents 6f427de + 3c70443 commit 50bcb41
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 76 deletions.
12 changes: 8 additions & 4 deletions config/audit.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,18 @@
| User Keys, Model
|--------------------------------------------------------------------------
|
| Define the User primary key, foreign key and Eloquent model.
| Define the User Eloquent model, morph prefix and authentication guards
| to use in the User resolver.
|
*/

'user' => [
'primary_key' => 'id',
'foreign_key' => 'user_id',
'model' => App\User::class,
'model' => App\User::class,
'morph_prefix' => 'user',
'guards' => [
'web',
'api',
],
],

/*
Expand Down
2 changes: 1 addition & 1 deletion database/migrations/audits.stub
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class CreateAuditsTable extends Migration
{
Schema::create('audits', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id')->nullable();
$table->nullableMorphs('user');
$table->string('event');
$table->morphs('auditable');
$table->text('old_values')->nullable();
Expand Down
14 changes: 6 additions & 8 deletions src/Audit.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

use DateTimeInterface;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Facades\Config;

Expand Down Expand Up @@ -70,20 +69,18 @@ public function auditable(): MorphTo
/**
* {@inheritdoc}
*/
public function user(): BelongsTo
public function user(): MorphTo
{
return $this->belongsTo(
Config::get('audit.user.model'),
Config::get('audit.user.foreign_key', 'user_id'),
Config::get('audit.user.primary_key', 'id')
);
return $this->morphTo();
}

/**
* {@inheritdoc}
*/
public function resolveData(): array
{
$morphPrefix = Config::get('audit.user.morph_prefix', 'user');

// Metadata
$this->data = [
'audit_id' => $this->id,
Expand All @@ -94,7 +91,8 @@ public function resolveData(): array
'audit_tags' => $this->tags,
'audit_created_at' => $this->serializeDate($this->created_at),
'audit_updated_at' => $this->serializeDate($this->updated_at),
'user_id' => $this->getAttribute(Config::get('audit.user.foreign_key', 'user_id')),
'user_id' => $this->getAttribute($morphPrefix.'_id'),
'user_type' => $this->getAttribute($morphPrefix.'_type'),
];

if ($this->user) {
Expand Down
25 changes: 14 additions & 11 deletions src/Auditable.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,21 +278,24 @@ public function toAudit(): array
}
}

$userForeignKey = Config::get('audit.user.foreign_key', 'user_id');
$morphPrefix = Config::get('audit.user.morph_prefix', 'user');

$tags = implode(',', $this->generateTags());

$user = $this->resolveUser();

return $this->transformAudit([
'old_values' => $old,
'new_values' => $new,
'event' => $this->auditEvent,
'auditable_id' => $this->getKey(),
'auditable_type' => $this->getMorphClass(),
$userForeignKey => $this->resolveUser(),
'url' => $this->resolveUrl(),
'ip_address' => $this->resolveIpAddress(),
'user_agent' => $this->resolveUserAgent(),
'tags' => empty($tags) ? null : $tags,
'old_values' => $old,
'new_values' => $new,
'event' => $this->auditEvent,
'auditable_id' => $this->getKey(),
'auditable_type' => $this->getMorphClass(),
$morphPrefix.'_id' => $user ? $user->getAuthIdentifier() : null,
$morphPrefix.'_type' => $user ? $user->getMorphClass() : null,
'url' => $this->resolveUrl(),
'ip_address' => $this->resolveIpAddress(),
'user_agent' => $this->resolveUserAgent(),
'tags' => empty($tags) ? null : $tags,
]);
}

Expand Down
5 changes: 2 additions & 3 deletions src/Contracts/Audit.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

namespace OwenIt\Auditing\Contracts;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;

interface Audit
Expand Down Expand Up @@ -43,9 +42,9 @@ public function auditable(): MorphTo;
/**
* User responsible for the changes.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function user(): BelongsTo;
public function user(): MorphTo;

/**
* Audit data resolver.
Expand Down
12 changes: 11 additions & 1 deletion src/Resolvers/UserResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace OwenIt\Auditing\Resolvers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;

class UserResolver implements \OwenIt\Auditing\Contracts\UserResolver
{
Expand All @@ -23,6 +24,15 @@ class UserResolver implements \OwenIt\Auditing\Contracts\UserResolver
*/
public static function resolve()
{
return Auth::check() ? Auth::user()->getAuthIdentifier() : null;
$guards = Config::get('audit.user.guards', [
'web',
'api',
]);

foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return Auth::guard($guard)->user();
}
}
}
}
47 changes: 12 additions & 35 deletions tests/Unit/AuditTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,12 @@

use Carbon\Carbon;
use DateTimeInterface;
use Mockery;
use OwenIt\Auditing\Models\Audit;
use OwenIt\Auditing\Tests\Models\Article;
use OwenIt\Auditing\Tests\Models\User;

class AuditTest extends AuditingTestCase
{
/**
* @group Audit::user
* @test
*/
public function itRelatesToUserWithCustomKeys()
{
$audit = Mockery::mock(Audit::class)
->makePartial();

$this->app['config']->set('audit.user.model', User::class);
$this->app['config']->set('audit.user.primary_key', 'pk_id');
$this->app['config']->set('audit.user.foreign_key', 'fk_id');

$this->assertInstanceOf(User::class, $audit->user()->getRelated());

// Up to Laravel 5.3, the ownerKey attribute was called otherKey
if (method_exists($audit->user(), 'getOtherKey')) {
$this->assertSame('pk_id', $audit->user()->getOtherKey());
}

// From Laravel 5.4 onward, the otherKey attribute was renamed to ownerKey
if (method_exists($audit->user(), 'getOwnerKey')) {
$this->assertSame('pk_id', $audit->user()->getOwnerKey());
}

$this->assertSame('fk_id', $audit->user()->getForeignKey());
}

/**
* @group Audit::resolveData
* @test
Expand All @@ -68,7 +39,7 @@ public function itResolvesAuditData()

$audit = $article->audits()->first();

$this->assertCount(14, $resolvedData = $audit->resolveData());
$this->assertCount(15, $resolvedData = $audit->resolveData());

$this->assertArraySubset([
'audit_id' => 1,
Expand All @@ -80,6 +51,7 @@ public function itResolvesAuditData()
'audit_created_at' => $audit->created_at->toDateTimeString(),
'audit_updated_at' => $audit->updated_at->toDateTimeString(),
'user_id' => null,
'user_type' => null,
'new_title' => 'How To Audit Eloquent Models',
'new_content' => 'First step: install the laravel-auditing package.',
'new_published_at' => $now->toDateTimeString(),
Expand Down Expand Up @@ -114,7 +86,7 @@ public function itResolvesAuditDataIncludingUserAttributes()

$audit = $article->audits()->first();

$this->assertCount(20, $resolvedData = $audit->resolveData());
$this->assertCount(21, $resolvedData = $audit->resolveData());

$this->assertArraySubset([
'audit_id' => 2,
Expand All @@ -126,6 +98,7 @@ public function itResolvesAuditDataIncludingUserAttributes()
'audit_created_at' => $audit->created_at->toDateTimeString(),
'audit_updated_at' => $audit->updated_at->toDateTimeString(),
'user_id' => '1',
'user_type' => User::class,
'user_is_admin' => '1',
'user_first_name' => 'rick',
'user_last_name' => 'Sanchez',
Expand Down Expand Up @@ -164,7 +137,7 @@ public function itReturnsTheAppropriateAuditableDataValues()
])->audits()->first();

// Resolve data, making it available to the getDataValue() method
$this->assertCount(20, $audit->resolveData());
$this->assertCount(21, $audit->resolveData());

// Mutate value
$this->assertSame('HOW TO AUDIT ELOQUENT MODELS', $audit->getDataValue('new_title'));
Expand Down Expand Up @@ -194,7 +167,7 @@ public function itReturnsAuditMetadataAsArray()
{
$audit = factory(Article::class)->create()->audits()->first();

$this->assertCount(9, $metadata = $audit->getMetadata());
$this->assertCount(10, $metadata = $audit->getMetadata());

$this->assertArraySubset([
'audit_id' => 1,
Expand All @@ -206,6 +179,7 @@ public function itReturnsAuditMetadataAsArray()
'audit_created_at' => $audit->created_at->toDateTimeString(),
'audit_updated_at' => $audit->updated_at->toDateTimeString(),
'user_id' => null,
'user_type' => null,
], $metadata, true);
}

Expand All @@ -226,7 +200,7 @@ public function itReturnsAuditMetadataIncludingUserAttributesAsArray()

$audit = factory(Article::class)->create()->audits()->first();

$this->assertCount(15, $metadata = $audit->getMetadata());
$this->assertCount(16, $metadata = $audit->getMetadata());

$this->assertArraySubset([
'audit_id' => 2,
Expand All @@ -238,6 +212,7 @@ public function itReturnsAuditMetadataIncludingUserAttributesAsArray()
'audit_created_at' => $audit->created_at->toDateTimeString(),
'audit_updated_at' => $audit->updated_at->toDateTimeString(),
'user_id' => 1,
'user_type' => User::class,
'user_is_admin' => true,
'user_first_name' => 'Rick',
'user_last_name' => 'Sanchez',
Expand Down Expand Up @@ -267,7 +242,8 @@ public function itReturnsAuditMetadataAsJsonString()
"audit_tags": null,
"audit_created_at": "$audit->created_at",
"audit_updated_at": "$audit->updated_at",
"user_id": null
"user_id": null,
"user_type": null
}
EOF;

Expand Down Expand Up @@ -304,6 +280,7 @@ public function itReturnsAuditMetadataIncludingUserAttributesAsJsonString()
"audit_created_at": "$audit->created_at",
"audit_updated_at": "$audit->updated_at",
"user_id": 1,
"user_type": "OwenIt\\\Auditing\\\Tests\\\Models\\\User",
"user_is_admin": true,
"user_first_name": "Rick",
"user_last_name": "Sanchez",
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/AuditableObserverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ public function itExecutesTheAuditorSuccessfully(string $eventMethod, bool $expe

$this->assertSame($expectedBefore, $observer::$restoring);

call_user_func([$observer, $eventMethod], $model);
$observer->$eventMethod($model);

$this->assertSame($expectedAfter, $observer::$restoring);
}

/**
* @return array
*/
public function auditableObserverTestProvider()
public function auditableObserverTestProvider(): array
{
return [
[
Expand Down
Loading

0 comments on commit 50bcb41

Please sign in to comment.