From ee1b1a01e02a9305488620d6c17312d448ae628d Mon Sep 17 00:00:00 2001 From: Ruben Van Assche Date: Wed, 7 Sep 2022 17:08:55 +0200 Subject: [PATCH] use encryption in cached settings --- src/Settings.php | 26 +++++++++++++++++++++++++- tests/SettingsTest.php | 28 +++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/Settings.php b/src/Settings.php index adc6527..dfa9781 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -13,6 +13,7 @@ use Spatie\LaravelSettings\Events\SettingsLoaded; use Spatie\LaravelSettings\Events\SettingsSaved; use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository; +use Spatie\LaravelSettings\Support\Crypto; abstract class Settings implements Arrayable, Jsonable, Responsable { @@ -120,12 +121,35 @@ public function __isset($name) public function __serialize(): array { - return $this->toCollection()->all(); + /** @var Collection $encrypted */ + /** @var Collection $nonEncrypted */ + [$encrypted, $nonEncrypted] = $this->toCollection()->partition( + fn($value, string $name) => $this->config->isEncrypted($name) + ); + + return array_merge( + $encrypted->map(fn($value) => Crypto::encrypt($value))->all(), + $nonEncrypted->all() + ); } public function __unserialize(array $data): void { $this->loaded = false; + + $this->ensureConfigIsLoaded(); + + /** @var Collection $encrypted */ + /** @var Collection $nonEncrypted */ + [$encrypted, $nonEncrypted] = collect($data)->partition( + fn($value, string $name) => $this->config->isEncrypted($name) + ); + + $data = array_merge( + $encrypted->map(fn($value) => Crypto::decrypt($value))->all(), + $nonEncrypted->all() + ); + $this->loadValues($data); } diff --git a/tests/SettingsTest.php b/tests/SettingsTest.php index 92be818..9748a19 100644 --- a/tests/SettingsTest.php +++ b/tests/SettingsTest.php @@ -435,7 +435,7 @@ assertDatabaseMissing('migrations', ['migration' => '2018_11_21_091111_create_fake_settings']); assertDatabaseHas('migrations', ['migration' => '2018_11_21_091111_create_fake_table']); -})->skip(fn () => Str::startsWith(app()->version(), '7'), 'No support for dumping migrations in Laravel 7'); +})->skip(fn() => Str::startsWith(app()->version(), '7'), 'No support for dumping migrations in Laravel 7'); it('will not contact the repository when loading cached settings', function () { useEnabledCache($this->app); @@ -458,6 +458,32 @@ expect($log)->toHaveCount(0); }); +it('will cache encrypted setting', function () { + useEnabledCache($this->app); + + $data = [ + 'string' => 'Hello', + 'nullable' => null, + 'cast' => new DateTime('2020-05-16'), + ]; + + $cache = resolve(SettingsCache::class); + + $cache->put(new DummyEncryptedSettings($data)); + + $serialized = Cache::get('settings.'.DummyEncryptedSettings::class); + + expect($serialized)->not()->toContain($data['string']); + + $this->setRegisteredSettings([ + DummyEncryptedSettings::class, + ]); + + $decrypted = resolve(DummyEncryptedSettings::class); + + expect($decrypted->string)->toEqual($data['string']); +}); + it('can clear a settings cache', function () { useEnabledCache($this->app);