Skip to content

Commit 71dbf22

Browse files
authored
[8.x] Model::encryptUsing() (#35080)
* implementation * tests
1 parent f802e81 commit 71dbf22

File tree

2 files changed

+76
-24
lines changed

2 files changed

+76
-24
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ trait HasAttributes
123123
*/
124124
protected static $mutatorCache = [];
125125

126+
/**
127+
* The encrypter instance that is used to encrypt attributes.
128+
*
129+
* @var \Illuminate\Contracts\Encryption\Encrypter
130+
*/
131+
public static $encrypter;
132+
126133
/**
127134
* Convert the model's attributes to an array.
128135
*
@@ -883,15 +890,14 @@ public function fromJson($value, $asObject = false)
883890
}
884891

885892
/**
886-
* Decode the given encrypted string.
893+
* Decrypt the given encrypted string.
887894
*
888895
* @param string $value
889-
* @param bool $asObject
890896
* @return mixed
891897
*/
892898
public function fromEncryptedString($value)
893899
{
894-
return Crypt::decryptString($value);
900+
return (static::$encrypter ?? Crypt::getFacadeRoot())->decrypt($value, false);
895901
}
896902

897903
/**
@@ -903,7 +909,18 @@ public function fromEncryptedString($value)
903909
*/
904910
protected function castAttributeAsEncryptedString($key, $value)
905911
{
906-
return Crypt::encryptString($value);
912+
return (static::$encrypter ?? Crypt::getFacadeRoot())->encrypt($value, false);
913+
}
914+
915+
/**
916+
* Set the encrypter instance that will be used to encrypt attributes.
917+
*
918+
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
919+
* @return void
920+
*/
921+
public static function encryptUsing($encrypter)
922+
{
923+
static::$encrypter = $encrypter;
907924
}
908925

909926
/**

tests/Integration/Database/EloquentModelEncryptedCastingTest.php

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ protected function setUp(): void
3131
$table->text('secret_object')->nullable();
3232
$table->text('secret_collection')->nullable();
3333
});
34+
35+
Model::$encrypter = null;
3436
}
3537

3638
public function testStringsAreCastable()
3739
{
38-
$this->encrypter->expects('encryptString')
39-
->with('this is a secret string')
40+
$this->encrypter->expects('encrypt')
41+
->with('this is a secret string', false)
4042
->andReturn('encrypted-secret-string');
41-
$this->encrypter->expects('decryptString')
42-
->with('encrypted-secret-string')
43+
$this->encrypter->expects('decrypt')
44+
->with('encrypted-secret-string', false)
4345
->andReturn('this is a secret string');
4446

4547
/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $subject */
@@ -56,11 +58,11 @@ public function testStringsAreCastable()
5658

5759
public function testArraysAreCastable()
5860
{
59-
$this->encrypter->expects('encryptString')
60-
->with('{"key1":"value1"}')
61+
$this->encrypter->expects('encrypt')
62+
->with('{"key1":"value1"}', false)
6163
->andReturn('encrypted-secret-array-string');
62-
$this->encrypter->expects('decryptString')
63-
->with('encrypted-secret-array-string')
64+
$this->encrypter->expects('decrypt')
65+
->with('encrypted-secret-array-string', false)
6466
->andReturn('{"key1":"value1"}');
6567

6668
/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $subject */
@@ -77,11 +79,11 @@ public function testArraysAreCastable()
7779

7880
public function testJsonIsCastable()
7981
{
80-
$this->encrypter->expects('encryptString')
81-
->with('{"key1":"value1"}')
82+
$this->encrypter->expects('encrypt')
83+
->with('{"key1":"value1"}', false)
8284
->andReturn('encrypted-secret-json-string');
83-
$this->encrypter->expects('decryptString')
84-
->with('encrypted-secret-json-string')
85+
$this->encrypter->expects('decrypt')
86+
->with('encrypted-secret-json-string', false)
8587
->andReturn('{"key1":"value1"}');
8688

8789
/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $subject */
@@ -101,12 +103,12 @@ public function testObjectIsCastable()
101103
$object = new \stdClass();
102104
$object->key1 = 'value1';
103105

104-
$this->encrypter->expects('encryptString')
105-
->with('{"key1":"value1"}')
106+
$this->encrypter->expects('encrypt')
107+
->with('{"key1":"value1"}', false)
106108
->andReturn('encrypted-secret-object-string');
107-
$this->encrypter->expects('decryptString')
109+
$this->encrypter->expects('decrypt')
108110
->twice()
109-
->with('encrypted-secret-object-string')
111+
->with('encrypted-secret-object-string', false)
110112
->andReturn('{"key1":"value1"}');
111113

112114
/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $object */
@@ -124,12 +126,12 @@ public function testObjectIsCastable()
124126

125127
public function testCollectionIsCastable()
126128
{
127-
$this->encrypter->expects('encryptString')
128-
->with('{"key1":"value1"}')
129+
$this->encrypter->expects('encrypt')
130+
->with('{"key1":"value1"}', false)
129131
->andReturn('encrypted-secret-collection-string');
130-
$this->encrypter->expects('decryptString')
132+
$this->encrypter->expects('decrypt')
131133
->twice()
132-
->with('encrypted-secret-collection-string')
134+
->with('encrypted-secret-collection-string', false)
133135
->andReturn('{"key1":"value1"}');
134136

135137
/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $subject */
@@ -144,6 +146,39 @@ public function testCollectionIsCastable()
144146
'secret_collection' => 'encrypted-secret-collection-string',
145147
]);
146148
}
149+
150+
public function testCustomEncrypterCanBeSpecified()
151+
{
152+
$customEncrypter = $this->mock(Encrypter::class);
153+
154+
$this->assertNull(Model::$encrypter);
155+
156+
Model::encryptUsing($customEncrypter);
157+
158+
$this->assertSame($customEncrypter, Model::$encrypter);
159+
160+
$this->encrypter->expects('encrypt')
161+
->never();
162+
$this->encrypter->expects('decrypt')
163+
->never();
164+
$customEncrypter->expects('encrypt')
165+
->with('this is a secret string', false)
166+
->andReturn('encrypted-secret-string');
167+
$customEncrypter->expects('decrypt')
168+
->with('encrypted-secret-string', false)
169+
->andReturn('this is a secret string');
170+
171+
/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $subject */
172+
$subject = EncryptedCast::create([
173+
'secret' => 'this is a secret string',
174+
]);
175+
176+
$this->assertSame('this is a secret string', $subject->secret);
177+
$this->assertDatabaseHas('encrypted_casts', [
178+
'id' => $subject->id,
179+
'secret' => 'encrypted-secret-string',
180+
]);
181+
}
147182
}
148183

149184
/**

0 commit comments

Comments
 (0)