Skip to content

Commit

Permalink
update behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Feb 3, 2024
1 parent 25d16da commit c3ac147
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
21 changes: 17 additions & 4 deletions src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -1328,7 +1328,7 @@ public function fromJson($value, $asObject = false)
*/
public function fromEncryptedString($value)
{
return (static::$encrypter ?? Crypt::getFacadeRoot())->decrypt($value, false);
return static::currentEncrypter()->decrypt($value, false);
}

/**
Expand All @@ -1340,7 +1340,7 @@ public function fromEncryptedString($value)
*/
protected function castAttributeAsEncryptedString($key, $value)
{
return (static::$encrypter ?? Crypt::getFacadeRoot())->encrypt($value, false);
return static::currentEncrypter()->encrypt($value, false);
}

/**
Expand All @@ -1354,6 +1354,16 @@ public static function encryptUsing($encrypter)
static::$encrypter = $encrypter;
}

/**
* Get the current encrypter being used by the model.
*
* @return \Illuminate\Contracts\Encryption\Encrypter
*/
protected static function currentEncrypter()
{
return static::$encrypter ?? Crypt::getFacadeRoot();
}

/**
* Cast the given attribute to a hashed string.
*
Expand Down Expand Up @@ -2145,7 +2155,7 @@ public function originalIsEquivalent($key)
}

return abs($this->castAttribute($key, $attribute) - $this->castAttribute($key, $original)) < PHP_FLOAT_EPSILON * 4;
} elseif ($this->isEncryptedCastable($key)) {
} elseif ($this->isEncryptedCastable($key) && ! empty(static::currentEncrypter()->getPreviousKeys())) {
return false;
} elseif ($this->hasCast($key, static::$primitiveCastTypes)) {
return $this->castAttribute($key, $attribute) ===
Expand All @@ -2155,7 +2165,10 @@ public function originalIsEquivalent($key)
} elseif ($this->isClassCastable($key) && Str::startsWith($this->getCasts()[$key], [AsEnumArrayObject::class, AsEnumCollection::class])) {
return $this->fromJson($attribute) === $this->fromJson($original);
} elseif ($this->isClassCastable($key) && $original !== null && Str::startsWith($this->getCasts()[$key], [AsEncryptedArrayObject::class, AsEncryptedCollection::class])) {
// return $this->fromEncryptedString($attribute) === $this->fromEncryptedString($original);
if (empty(static::currentEncrypter()->getPreviousKeys())) {
return $this->fromEncryptedString($attribute) === $this->fromEncryptedString($original);
}

return false;
}

Expand Down
33 changes: 32 additions & 1 deletion tests/Integration/Database/EloquentModelEncryptedDirtyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

class EloquentModelEncryptedDirtyTest extends TestCase
{
public function testDirtyAttributeBehavior()
public function testDirtyAttributeBehaviorWithNoPreviousKeys()
{
config(['app.key' => str_repeat('a', 32)]);
Model::$encrypter = null;
Expand All @@ -27,6 +27,37 @@ public function testDirtyAttributeBehavior()
$model->secret = 'some-secret';
$model->secret_array_object = [1, 2, 3];

// Encrypted attributes should always be considered dirty if updated in any way because of rotatable encryption keys...
$this->assertFalse($model->isDirty('secret'));
$this->assertFalse($model->isDirty('secret_array_object'));

$model->secret = 'some-other-secret';
$model->secret_array_object = [4, 5, 6];

// Encrypted attributes should always be considered dirty if updated in any way because of rotatable encryption keys...
$this->assertTrue($model->isDirty('secret'));
$this->assertTrue($model->isDirty('secret_array_object'));
}

public function testDirtyAttributeBehaviorWithPreviousKeys()
{
config(['app.key' => str_repeat('a', 32)]);
config(['app.previous_keys' => [str_repeat('b', 32)]]);
Model::$encrypter = null;

$model = new EncryptedDirtyAttributeCast([
'secret' => 'some-secret',
'secret_array_object' => [1, 2, 3],
]);

$model->syncOriginal();

$this->assertFalse($model->isDirty('secret'));
$this->assertFalse($model->isDirty('secret_array_object'));

$model->secret = 'some-secret';
$model->secret_array_object = [1, 2, 3];

// Encrypted attributes should always be considered dirty if updated in any way because of rotatable encryption keys...
$this->assertTrue($model->isDirty('secret'));
$this->assertTrue($model->isDirty('secret_array_object'));
Expand Down

0 comments on commit c3ac147

Please sign in to comment.