From e0cc53450dd29a48d1998f0ad59d717984ad56ee Mon Sep 17 00:00:00 2001 From: Rizky Puji Raharja Date: Mon, 29 Apr 2024 21:13:58 +0700 Subject: [PATCH] Add config to allow records array values (#915) * Add config to allow records array values * test: test config allowed_array_values --- config/audit.php | 13 +++ src/Auditable.php | 18 ++-- tests/Unit/AuditableTest.php | 89 ++++++++++++++++++- ...0_00_000003_create_articles_test_table.php | 1 + 4 files changed, 110 insertions(+), 11 deletions(-) diff --git a/config/audit.php b/config/audit.php index 3008c92a..d6cee429 100644 --- a/config/audit.php +++ b/config/audit.php @@ -106,6 +106,19 @@ 'retrieved' ], + /* + |-------------------------------------------------------------------------- + | Allowed Array Values + |-------------------------------------------------------------------------- + | + | Should the array values be audited? + | + | By default, array values are not allowed. This is to prevent performance + | issues when storing large amounts of data. You can override this by + | setting allow_array_values to true. + */ + 'allowed_array_values' => false, + /* |-------------------------------------------------------------------------- | Audit Timestamps diff --git a/src/Auditable.php b/src/Auditable.php index 51aeda76..ab72e0a7 100644 --- a/src/Auditable.php +++ b/src/Auditable.php @@ -125,7 +125,7 @@ protected function resolveAuditExclusions() foreach ($attributes as $attribute => $value) { // Apart from null, non scalar values will be excluded if ( - is_array($value) || + (is_array($value) && !Config::get('audit.allowed_array_values', false)) || (is_object($value) && !method_exists($value, '__toString') && !($value instanceof \UnitEnum)) @@ -365,8 +365,8 @@ public function transformAudit(array $data): array * */ protected function resolveUser() - { - if (! empty($this->preloadedResolverData['user'] ?? null)) { + { + if (!empty($this->preloadedResolverData['user'] ?? null)) { return $this->preloadedResolverData['user']; } @@ -417,7 +417,7 @@ public function preloadResolverData() $this->preloadedResolverData = $this->runResolvers(); $user = $this->resolveUser(); - if (!empty ($user)) { + if (!empty($user)) { $this->preloadedResolverData['user'] = $user; } @@ -509,11 +509,11 @@ public function getAuditEvent() public function getAuditEvents(): array { return $this->auditEvents ?? Config::get('audit.events', [ - 'created', - 'updated', - 'deleted', - 'restored', - ]); + 'created', + 'updated', + 'deleted', + 'restored', + ]); } /** diff --git a/tests/Unit/AuditableTest.php b/tests/Unit/AuditableTest.php index b8e9c1f9..218427a1 100644 --- a/tests/Unit/AuditableTest.php +++ b/tests/Unit/AuditableTest.php @@ -968,12 +968,11 @@ public function itWorksOnTimesRestoredCorrectly() ]); $model = Article::first(); - + $this->assertEquals($model->published_at, $originalStart); $model->published_at = new Carbon('2022-01-01 12:30:00'); $model->save(); - $audit = $model->audits->last(); $audit->auditable_id = $model->id; @@ -1310,4 +1309,90 @@ public static function auditableTransitionTestProvider(): array ], ]; } + + /** + * @test + */ + public function itWorksWhenConfigAllowedArrayValueIsTrue() + { + $this->app['config']->set('audit.allowed_array_values', true); + + $model = factory(Article::class)->make([ + 'title' => 'How To Audit Eloquent Models', + 'content' => 'First step: install the laravel-auditing package.', + 'reviewed' => 1, + 'images' => [ + 'https://example.com/image1.jpg', + 'https://example.com/image2.jpg', + ] + ]); + + $model->setAuditEvent('created'); + + $auditData = $model->toAudit(); + + $morphPrefix = config('audit.user.morph_prefix', 'user'); + self::Assert()::assertArraySubset([ + 'old_values' => [], + 'new_values' => [ + 'title' => 'How To Audit Eloquent Models', + 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), + 'reviewed' => 1, + 'images' => [ + 'https://example.com/image1.jpg', + 'https://example.com/image2.jpg', + ], + ], + 'event' => 'created', + 'auditable_id' => null, + 'auditable_type' => Article::class, + $morphPrefix . '_id' => null, + $morphPrefix . '_type' => null, + 'url' => UrlResolver::resolveCommandLine(), + 'ip_address' => '127.0.0.1', + 'user_agent' => 'Symfony', + 'tags' => null, + ], $auditData, true); + } + + /** + * @test + */ + public function itWorksWhenConfigAllowedArrayValueIsFalse() + { + $this->app['config']->set('audit.allowed_array_values', false); + + $model = factory(Article::class)->make([ + 'title' => 'How To Audit Eloquent Models', + 'content' => 'First step: install the laravel-auditing package.', + 'reviewed' => 1, + 'images' => [ + 'https://example.com/image1.jpg', + 'https://example.com/image2.jpg', + ] + ]); + + $model->setAuditEvent('created'); + + $auditData = $model->toAudit(); + + $morphPrefix = config('audit.user.morph_prefix', 'user'); + self::Assert()::assertArraySubset([ + 'old_values' => [], + 'new_values' => [ + 'title' => 'How To Audit Eloquent Models', + 'content' => Article::contentMutate('First step: install the laravel-auditing package.'), + 'reviewed' => 1, + ], + 'event' => 'created', + 'auditable_id' => null, + 'auditable_type' => Article::class, + $morphPrefix . '_id' => null, + $morphPrefix . '_type' => null, + 'url' => UrlResolver::resolveCommandLine(), + 'ip_address' => '127.0.0.1', + 'user_agent' => 'Symfony', + 'tags' => null, + ], $auditData, true); + } } diff --git a/tests/database/migrations/0000_00_00_000003_create_articles_test_table.php b/tests/database/migrations/0000_00_00_000003_create_articles_test_table.php index 4e0107af..35d29cc8 100644 --- a/tests/database/migrations/0000_00_00_000003_create_articles_test_table.php +++ b/tests/database/migrations/0000_00_00_000003_create_articles_test_table.php @@ -21,6 +21,7 @@ public function up() $table->timestamp('published_at')->nullable(); $table->json('config')->nullable(); $table->string('price')->nullable(); + $table->json('images')->nullable(); $table->timestamps(); $table->softDeletes(); });