Skip to content

Commit

Permalink
Merge pull request #2 from ensi-platform/dev-1
Browse files Browse the repository at this point in the history
Separate User
  • Loading branch information
zix2 authored Dec 1, 2021
2 parents 3bc4134 + 5e7821f commit 1cd5aa0
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 23 deletions.
2 changes: 1 addition & 1 deletion config/laravel-auditing.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
|
*/
'resolver' => [
'user' => Ensi\LaravelAuditing\Facades\Subject::class,
'user' => Ensi\LaravelAuditing\Resolvers\UserResolver::class,
'ip_address' => Ensi\LaravelAuditing\Resolvers\IpAddressResolver::class,
'user_agent' => Ensi\LaravelAuditing\Resolvers\UserAgentResolver::class,
'url' => Ensi\LaravelAuditing\Resolvers\UrlResolver::class,
Expand Down
2 changes: 2 additions & 0 deletions database/migrations/audits.stub
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ class CreateAuditsTable extends Migration

$table->uuid('transaction_uid')->nullable();
$table->timestamp('transaction_time', 6)->nullable();
$table->string('user_id')->nullable();

$table->index(['subject_id', 'subject_type']);
$table->index(['transaction_uid', 'created_at']);
$table->index(['user_id']);
});
}

Expand Down
6 changes: 2 additions & 4 deletions src/Contracts/Principal.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ public function getName(): string;

/**
* Возвращает идентификатор пользователя, если есть.
* Для самого пользователя getAuthIdentifier и getUserIdentifier должны вернуть
* одно и то же значение.
*
* @return int|null
* @return mixed
*/
public function getUserIdentifier(): ?int;
public function getUserIdentifier();
}
2 changes: 1 addition & 1 deletion src/Contracts/UserResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface UserResolver
/**
* Resolve the User.
*
* @return mixed|null
* @return string|null
*/
public static function resolve();
}
7 changes: 3 additions & 4 deletions src/Facades/Subject.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@

namespace Ensi\LaravelAuditing\Facades;

use Ensi\LaravelAuditing\Resolvers\SubjectManager;
use Ensi\LaravelAuditing\Contracts\Principal;
use Illuminate\Support\Optional;
use Ensi\LaravelAuditing\Resolvers\SubjectManager;
use Illuminate\Support\Facades\Facade;
use Ensi\LaravelAuditing\Contracts\UserResolver;
use Illuminate\Support\Optional;

/**
* @method static void attach(\Ensi\LaravelAuditing\Contracts\Principal $subject)
* @method static void detach()
*/
class Subject extends Facade implements UserResolver
class Subject extends Facade
{
protected static function getFacadeAccessor(): string
{
Expand Down
1 change: 1 addition & 0 deletions src/Models/Audit.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @property int $root_entity_id Корневая сущность
* @property string $subject_type
* @property int $subject_id Субъект доступа
* @property string|null $user_id Идентификатор пользователя
*
* @property \Carbon\CarbonInterface $created_at
* @property \Carbon\CarbonInterface $updated_at
Expand Down
5 changes: 4 additions & 1 deletion src/Resolvers/UserResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

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

class UserResolver implements \Ensi\LaravelAuditing\Contracts\UserResolver
{
Expand All @@ -19,8 +20,10 @@ public static function resolve()

foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return Auth::guard($guard)->user();
return (string)Auth::guard($guard)->user()->getAuthIdentifier();
}
}

return null;
}
}
25 changes: 19 additions & 6 deletions src/SupportsAudit.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Ensi\LaravelAuditing;

use Ensi\LaravelAuditing\Contracts\Principal;
use Ensi\LaravelAuditing\Facades\Subject;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Arr;
Expand Down Expand Up @@ -290,7 +292,7 @@ public function toAudit(): array

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

$user = $this->resolveUser();
$subject = $this->resolveSubject();

return $this->transformAudit([
'old_values' => $old,
Expand All @@ -299,11 +301,12 @@ public function toAudit(): array
'event' => $this->auditEvent,
'auditable_id' => $this->getKey(),
'auditable_type' => $this->getMorphClass(),
'subject_id' => $user ? $user->getAuthIdentifier() : null,
'subject_type' => $user ? $user->getMorphClass() : null,
'subject_id' => $subject?->getAuthIdentifier(),
'subject_type' => $subject?->getMorphClass(),
'url' => $this->resolveUrl(),
'ip_address' => $this->resolveIpAddress(),
'user_agent' => $this->resolveUserAgent(),
'user_id' => $this->resolveUser(),
'tags' => empty($tags) ? null : $tags,
]);
}
Expand All @@ -325,6 +328,16 @@ public function transformAudit(array $data): array
return $data;
}

/**
* Resolve the Subject.
*
* @return Principal|null
*/
protected function resolveSubject()
{
return Subject::resolve();
}

/**
* Resolve the User.
*
Expand All @@ -336,11 +349,11 @@ protected function resolveUser()
{
$userResolver = Config::get('laravel-auditing.resolver.user');

if (is_subclass_of($userResolver, UserResolver::class)) {
return call_user_func([$userResolver, 'resolve']);
if (!is_subclass_of($userResolver, UserResolver::class)) {
throw new AuditingException('Invalid UserResolver implementation');
}

throw new AuditingException('Invalid UserResolver implementation');
return call_user_func([$userResolver, 'resolve']);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion tests/AuditingTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Ensi\LaravelAuditing\Resolvers\IpAddressResolver;
use Ensi\LaravelAuditing\Resolvers\UrlResolver;
use Ensi\LaravelAuditing\Resolvers\UserAgentResolver;
use Ensi\LaravelAuditing\Resolvers\UserResolver;
use Orchestra\Testbench\TestCase;

class AuditingTestCase extends TestCase
Expand All @@ -23,6 +24,10 @@ protected function getEnvironmentSetUp($app)
'database' => ':memory:',
'prefix' => '',
]);
$app['config']->set('auth.guards.api', [
'driver' => 'session',
'provider' => 'users',
]);

// Audit
$app['config']->set('laravel-auditing.drivers.database.connection', 'testing');
Expand All @@ -31,7 +36,7 @@ protected function getEnvironmentSetUp($app)
'web',
'api',
]);
$app['config']->set('laravel-auditing.resolver.user', Subject::class);
$app['config']->set('laravel-auditing.resolver.user', UserResolver::class);
$app['config']->set('laravel-auditing.resolver.url', UrlResolver::class);
$app['config']->set('laravel-auditing.resolver.ip_address', IpAddressResolver::class);
$app['config']->set('laravel-auditing.resolver.user_agent', UserAgentResolver::class);
Expand Down
4 changes: 3 additions & 1 deletion tests/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
use Ensi\LaravelAuditing\Contracts\Principal;
use Ensi\LaravelAuditing\Database\Factories\UserFactory;
use Ensi\LaravelAuditing\SupportsAudit;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;

class User extends Model implements Auditable, Principal
class User extends Model implements Auditable, Principal, Authenticatable
{
use SupportsAudit;
use \Illuminate\Auth\Authenticatable;

/**
* {@inheritdoc}
Expand Down
36 changes: 36 additions & 0 deletions tests/Models/VirtualUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Ensi\LaravelAuditing\Tests\Models;

use Illuminate\Contracts\Auth\Authenticatable;

class VirtualUser implements Authenticatable
{
public const ID = 'admin:12345';

public function getAuthIdentifierName()
{
}

public function getAuthIdentifier()
{
return self::ID;
}

public function getAuthPassword()
{
}

public function getRememberToken()
{
}

public function setRememberToken($value)
{
}

public function getRememberTokenName()
{
}

}
110 changes: 106 additions & 4 deletions tests/Unit/AuditableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Ensi\LaravelAuditing\Tests\Models\ApiModel;
use Ensi\LaravelAuditing\Tests\Models\Article;
use Ensi\LaravelAuditing\Tests\Models\User;
use Ensi\LaravelAuditing\Tests\Models\VirtualUser;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Testing\Assert;
use Illuminate\Support\Facades\App;
Expand All @@ -24,6 +25,8 @@

class AuditableTest extends AuditingTestCase
{
private const AUDIT_FIELDS_COUNT = 13;

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -401,7 +404,7 @@ public function itReturnsTheAuditData()

$model->setAuditEvent('created');

$this->assertCount(12, $auditData = $model->toAudit());
$this->assertCount(self::AUDIT_FIELDS_COUNT, $auditData = $model->toAudit());

Assert::assertArraySubset([
'old_values' => [],
Expand Down Expand Up @@ -442,7 +445,7 @@ public function itReturnsTheAuditDataIncludingSubjectAttributes() {

$model->setAuditEvent('created');

$this->assertCount(12, $auditData = $model->toAudit());
$this->assertCount(self::AUDIT_FIELDS_COUNT, $auditData = $model->toAudit());

Assert::assertArraySubset([
'old_values' => [],
Expand All @@ -460,6 +463,105 @@ public function itReturnsTheAuditDataIncludingSubjectAttributes() {
'url' => 'console',
'ip_address' => '127.0.0.1',
'user_agent' => 'Symfony',
'user_id' => null,
'tags' => null,
], $auditData, true);
}

/**
* @dataProvider userResolverProvider
* @test
*/
public function itReturnsTheAuditDataIncludingUserId(
string $guard,
string $driver,
?string $id
) {
$this->app['config']->set('laravel-auditing.user.guards', [$guard]);

$user = User::factory()->create();
$this->actingAs($user, $driver);
$now = Carbon::now();

$model = Article::factory()->make([
'title' => 'How To Audit Eloquent Models',
'content' => 'First step: install the laravel-auditing package.',
'reviewed' => 1,
'published_at' => $now,
]);

$model->setAuditEvent('created');

$this->assertCount(self::AUDIT_FIELDS_COUNT, $auditData = $model->toAudit());

Assert::assertArraySubset([
'old_values' => [],
'new_values' => [
'title' => 'How To Audit Eloquent Models',
'content' => 'First step: install the laravel-auditing package.',
'reviewed' => 1,
'published_at' => $now->toDateTimeString(),
],
'event' => 'created',
'auditable_id' => null,
'auditable_type' => Article::class,
'subject_id' => null,
'subject_type' => null,
'url' => 'console',
'ip_address' => '127.0.0.1',
'user_agent' => 'Symfony',
'user_id' => $id,
'tags' => null,
], $auditData, true);
}

public function userResolverProvider(): array
{
return [
['api', 'web', null],
['web', 'api', null],
['api', 'api', '1'],
['web', 'web', '1'],
];
}

/**
* @test
*/
public function itReturnsTheAuditDataIncludingVirtualUserId()
{
$this->actingAs(new VirtualUser(), 'api');

$now = Carbon::now();

$model = Article::factory()->make([
'title' => 'How To Audit Eloquent Models',
'content' => 'First step: install the laravel-auditing package.',
'reviewed' => 1,
'published_at' => $now,
]);

$model->setAuditEvent('created');

$this->assertCount(self::AUDIT_FIELDS_COUNT, $auditData = $model->toAudit());

Assert::assertArraySubset([
'old_values' => [],
'new_values' => [
'title' => 'How To Audit Eloquent Models',
'content' => 'First step: install the laravel-auditing package.',
'reviewed' => 1,
'published_at' => $now->toDateTimeString(),
],
'event' => 'created',
'auditable_id' => null,
'auditable_type' => Article::class,
'subject_id' => null,
'subject_type' => null,
'url' => 'console',
'ip_address' => '127.0.0.1',
'user_agent' => 'Symfony',
'user_id' => VirtualUser::ID,
'tags' => null,
], $auditData, true);
}
Expand Down Expand Up @@ -491,7 +593,7 @@ public function itExcludesAttributesFromTheAuditDataWhenInStrictMode()

$model->setAuditEvent('created');

$this->assertCount(12, $auditData = $model->toAudit());
$this->assertCount(self::AUDIT_FIELDS_COUNT, $auditData = $model->toAudit());

Assert::assertArraySubset([
'old_values' => [],
Expand Down Expand Up @@ -605,7 +707,7 @@ public function transformAudit(array $data): array

$model->setAuditEvent('created');

$this->assertCount(12, $auditData = $model->toAudit());
$this->assertCount(self::AUDIT_FIELDS_COUNT, $auditData = $model->toAudit());

Assert::assertArraySubset([
'new_values' => [
Expand Down
Loading

0 comments on commit 1cd5aa0

Please sign in to comment.