diff --git a/src/Events/AuditableEvent.php b/src/Events/AuditableEvent.php index 3a53261..606c088 100644 --- a/src/Events/AuditableEvent.php +++ b/src/Events/AuditableEvent.php @@ -2,6 +2,7 @@ namespace SkoreLabs\LaravelAuditable\Events; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -12,6 +13,8 @@ abstract class AuditableEvent use Dispatchable; use SerializesModels; + public const CONTAINER_KEY = 'skorelabs.auditable'; + /** * @var \Illuminate\Database\Eloquent\Model */ @@ -23,8 +26,6 @@ abstract class AuditableEvent public $user; /** - * Can be "creating", "updating" or "deleting". - * * @var string */ public $action; @@ -32,13 +33,26 @@ abstract class AuditableEvent /** * Create a new event instance. * - * @param \Illuminate\Database\Eloquent\Model $model - * * @return void */ public function __construct(Model $model) { $this->model = $model; - $this->user = Auth::user(); + + if (app()->has(static::CONTAINER_KEY)) { + [$user, $action] = app()->get(static::CONTAINER_KEY); + + $this->user = ! $action || $this->action === $action ? $user : null; + } + + $this->user ??= Auth::user(); + } + + /** + * Set user for auditable event when action, all actions if null. + */ + public static function setUser(Authenticatable $user, string $action = null): void + { + app()->bind(static::CONTAINER_KEY, fn () => [$user, $action]); } } diff --git a/tests/AuditableTest.php b/tests/AuditableTest.php index 1b50992..ba256a3 100644 --- a/tests/AuditableTest.php +++ b/tests/AuditableTest.php @@ -2,23 +2,32 @@ namespace SkoreLabs\LaravelAuditable\Tests; -use Illuminate\Foundation\Testing\WithFaker; +use SkoreLabs\LaravelAuditable\Events\AuditableEvent; use SkoreLabs\LaravelAuditable\Tests\Fixtures\Post; use SkoreLabs\LaravelAuditable\Tests\Fixtures\User; class AuditableTest extends TestCase { - use WithFaker; - /** * @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\User */ protected $user; + /** + * @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\User + */ + protected $anotherUser; + protected function setUp(): void { parent::setUp(); + $this->anotherUser = User::create([ + 'email' => 'another_user@localhost.com', + 'name' => 'Another', + 'password' => '1234', + ]); + $this->user = User::create([ 'email' => 'admin@localhost.com', 'name' => 'Admin', @@ -32,8 +41,8 @@ public function test_created_by_assignation_and_relationship() { /** @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\Post $post */ $post = Post::create([ - 'title' => $this->faker->words(3, true), - 'content' => $this->faker->paragraph(), + 'title' => 'hello user', + 'content' => 'lorem ipsum', ]); $this->assertTrue($post->created_by === $this->user->id); @@ -49,8 +58,8 @@ public function test_created_by_assignation_using_replicate_and_relationship() { /** @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\Post $post */ $post = Post::create([ - 'title' => $this->faker->words(3, true), - 'content' => $this->faker->paragraph(), + 'title' => 'hello user', + 'content' => 'lorem ipsum', ]); $duplicatedPost = $post->replicate(); @@ -70,8 +79,8 @@ public function test_updated_by_assignation_and_relationship() { /** @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\Post $post */ $post = Post::create([ - 'title' => $this->faker->words(3, true), - 'content' => $this->faker->paragraph(), + 'title' => 'hello user', + 'content' => 'lorem ipsum', ]); $post->update(['title' => 'new title']); @@ -87,8 +96,8 @@ public function test_deleted_by_assignation_and_relationship() { /** @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\Post $post */ $post = Post::create([ - 'title' => $this->faker->words(3, true), - 'content' => $this->faker->paragraph(), + 'title' => 'hello user', + 'content' => 'lorem ipsum', ]); $post->delete(); @@ -99,4 +108,46 @@ public function test_deleted_by_assignation_and_relationship() $this->assertTrue($post->deletedBy->id === $this->user->id); } + + public function test_created_by_uses_forced_user_even_when_authenticated_exists() + { + AuditableEvent::setUser($this->anotherUser); + + /** @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\Post $post */ + $post = Post::create([ + 'title' => 'hello user', + 'content' => 'lorem ipsum', + ]); + + $this->assertTrue($post->created_by === $this->anotherUser->id); + $this->assertNull($post->updated_by); + $this->assertNull($post->deleted_by); + + // Relationship & alias + $this->assertTrue($post->createdBy->id === $this->anotherUser->id); + $this->assertTrue($post->author->id === $this->anotherUser->id); + } + + public function test_updated_by_uses_forced_user_only_when_action_sent() + { + AuditableEvent::setUser($this->anotherUser, 'updating'); + + /** @var \SkoreLabs\LaravelAuditable\Tests\Fixtures\Post $post */ + $post = Post::create([ + 'title' => 'hello user', + 'content' => 'lorem ipsum', + ]); + + $this->assertTrue($post->created_by === $this->user->id); + $this->assertNull($post->updated_by); + $this->assertNull($post->deleted_by); + + $post->update(['title' => 'hello another']); + + $this->assertTrue($post->updated_by === $this->anotherUser->id); + + // Relationship & alias + $this->assertTrue($post->createdBy->id === $this->user->id); + $this->assertTrue($post->author->id === $this->user->id); + } }