Skip to content

Commit 15a0e37

Browse files
authored
Merge pull request #52 from tonysm/tm/encrypt-as-string
Allow configuring the encryption handlers
2 parents 9a89b33 + 8036b37 commit 15a0e37

File tree

5 files changed

+97
-4
lines changed

5 files changed

+97
-4
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,25 @@ class Post extends Model
192192
}
193193
```
194194

195-
This uses [Laravel's Encryption](https://laravel.com/docs/10.x/encryption#introduction) feature.
195+
This uses [Laravel's Encryption](https://laravel.com/docs/encryption#introduction) feature. By default, it will encrypt using the default encryption handler in Laravel, which serializes the value before encrypting it. However you can opt-in skip the serialization step and only encrypt as string by calling the following method in the `AppServiceProvider`:
196+
197+
```php
198+
namespace App\Providers;
199+
200+
use Illuminate\Support\ServiceProvider;
201+
use Tonysm\RichTextLaravel\RichTextLaravel;
202+
203+
class AppServiceProvider extends ServiceProvider
204+
{
205+
// ...
206+
public function boot(): void
207+
{
208+
RichTextLaravel::encryptAsString();
209+
}
210+
}
211+
```
212+
213+
In the next major version of the package, this will be the default, so it's recommended that you do that.
196214

197215
#### Key Rotation
198216

src/Casts/AsEncryptedRichTextContent.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
66
use Tonysm\RichTextLaravel\Content;
7+
use Tonysm\RichTextLaravel\RichTextLaravel;
78

89
class AsEncryptedRichTextContent implements CastsAttributes
910
{
@@ -18,7 +19,7 @@ class AsEncryptedRichTextContent implements CastsAttributes
1819
*/
1920
public function set($model, $key, $value, $attributes)
2021
{
21-
return encrypt(Content::toStorage($value));
22+
return RichTextLaravel::encrypt(Content::toStorage($value), $model, $key);
2223
}
2324

2425
/**
@@ -32,6 +33,6 @@ public function set($model, $key, $value, $attributes)
3233
*/
3334
public function get($model, $key, $value, $attributes)
3435
{
35-
return Content::fromStorage($value ? decrypt($value) : null);
36+
return Content::fromStorage(RichTextLaravel::decrypt($value, $model, $key));
3637
}
3738
}

src/RichTextLaravel.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace Tonysm\RichTextLaravel;
4+
5+
use Illuminate\Support\Facades\Crypt;
6+
7+
class RichTextLaravel
8+
{
9+
/**
10+
* The handler responsible for encrypting the rich text attributes.
11+
*
12+
* @var callable
13+
*/
14+
protected static $encryptHandler;
15+
16+
/**
17+
* The handle responsible for decrypting the rich text attributes.
18+
*
19+
* @var callable
20+
*/
21+
protected static $decryptHandler;
22+
23+
/**
24+
* Override the way the package handles encryption.
25+
*/
26+
public static function encryptUsing($encryption, $decryption): void
27+
{
28+
static::$encryptHandler = $encryption;
29+
static::$decryptHandler = $decryption;
30+
}
31+
32+
/**
33+
* Configures the Rich Text Laravel package to store encrypted data as string,
34+
* instead of using Laravel's default encryption mode, which serializes the
35+
* content before encrypting it.
36+
*/
37+
public static function encryptAsString(): void
38+
{
39+
static::$encryptHandler = fn ($value) => Crypt::encryptString($value);
40+
static::$decryptHandler = fn ($value) => ($value ? Crypt::decryptString($value) : $value);
41+
}
42+
43+
public static function clearEncryptionHandlers(): void
44+
{
45+
static::encryptUsing(null, null);
46+
}
47+
48+
public static function encrypt($value, $model, $key): string
49+
{
50+
$encrypt = static::$encryptHandler ??= fn ($value) => Crypt::encrypt($value);
51+
52+
return call_user_func($encrypt, $value, $model, $key);
53+
}
54+
55+
public static function decrypt($value, $model, $key): ?string
56+
{
57+
$decrypt = static::$decryptHandler ??= fn ($value) => Crypt::decrypt($value);
58+
59+
return $value ? call_user_func($decrypt, $value, $model, $key) : $value;
60+
}
61+
}

tests/EncryptedModelTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Tonysm\RichTextLaravel\Tests;
44

55
use Illuminate\Support\Facades\DB;
6+
use Tonysm\RichTextLaravel\RichTextLaravel;
67
use Workbench\App\Models\EncryptedMessage;
78
use Workbench\App\Models\Message;
89

@@ -18,10 +19,19 @@ public function encrypt_content_based_on_encrypted_option_at_declaration_time()
1819
$this->assertNotEncryptedRichTextAttribute($clearMessage, 'content', 'Hello World');
1920
}
2021

22+
/** @test */
23+
public function encrypts_as_string()
24+
{
25+
RichTextLaravel::encryptAsString();
26+
27+
$encryptedMessage = EncryptedMessage::create(['content' => 'Hello World']);
28+
$this->assertEncryptedRichTextAttribute($encryptedMessage, 'content', 'Hello World');
29+
}
30+
2131
private function assertEncryptedRichTextAttribute($model, $field, $expectedValue)
2232
{
2333
$this->assertStringNotContainsString($expectedValue, $encrypted = DB::table('rich_texts')->where('record_id', $model->id)->value('body'));
24-
$this->assertEquals($expectedValue, decrypt($encrypted));
34+
$this->assertEquals($expectedValue, RichTextLaravel::decrypt($encrypted, $model, $field));
2535
$this->assertStringContainsString($expectedValue, $model->refresh()->{$field}->body->toHtml());
2636
}
2737

tests/TestCase.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Foundation\Testing\RefreshDatabase;
77
use Orchestra\Testbench\Concerns\WithWorkbench;
88
use Orchestra\Testbench\TestCase as Orchestra;
9+
use Tonysm\RichTextLaravel\RichTextLaravel;
910

1011
class TestCase extends Orchestra
1112
{
@@ -19,6 +20,8 @@ public function setUp(): void
1920
Factory::guessFactoryNamesUsing(
2021
fn (string $modelName) => 'Tonysm\\RichTextLaravel\\Database\\Factories\\'.class_basename($modelName).'Factory'
2122
);
23+
24+
RichTextLaravel::clearEncryptionHandlers();
2225
}
2326

2427
public function getEnvironmentSetUp($app)

0 commit comments

Comments
 (0)