Skip to content

Commit 1c783fe

Browse files
authored
[10.x] Add 'hashed' cast (#46947)
* Add 'hashed' cast * Fix linting issues
1 parent 51251d4 commit 1c783fe

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Illuminate\Support\Exceptions\MathException;
3333
use Illuminate\Support\Facades\Crypt;
3434
use Illuminate\Support\Facades\Date;
35+
use Illuminate\Support\Facades\Hash;
3536
use Illuminate\Support\Str;
3637
use InvalidArgumentException;
3738
use LogicException;
@@ -104,6 +105,7 @@ trait HasAttributes
104105
'encrypted:json',
105106
'encrypted:object',
106107
'float',
108+
'hashed',
107109
'immutable_date',
108110
'immutable_datetime',
109111
'immutable_custom_datetime',
@@ -985,6 +987,10 @@ public function setAttribute($key, $value)
985987
$value = $this->castAttributeAsEncryptedString($key, $value);
986988
}
987989

990+
if (! is_null($value) && $this->hasCast($key, 'hashed')) {
991+
$value = $this->castAttributeAsHashedString($key, $value);
992+
}
993+
988994
$this->attributes[$key] = $value;
989995

990996
return $this;
@@ -1293,6 +1299,18 @@ public static function encryptUsing($encrypter)
12931299
static::$encrypter = $encrypter;
12941300
}
12951301

1302+
/**
1303+
* Cast the given attribute to a hashed string.
1304+
*
1305+
* @param string $key
1306+
* @param mixed $value
1307+
* @return string
1308+
*/
1309+
protected function castAttributeAsHashedString($key, $value)
1310+
{
1311+
return Hash::needsRehash($value) ? Hash::make($value) : $value;
1312+
}
1313+
12961314
/**
12971315
* Decode the given float.
12981316
*
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Database;
4+
5+
use Illuminate\Contracts\Hashing\Hasher;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Schema\Blueprint;
8+
use Illuminate\Support\Facades\Hash;
9+
use Illuminate\Support\Facades\Schema;
10+
11+
class EloquentModelHashedCastingTest extends DatabaseTestCase
12+
{
13+
protected $hasher;
14+
15+
protected function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
$this->hasher = $this->mock(Hasher::class);
20+
Hash::swap($this->hasher);
21+
}
22+
23+
protected function defineDatabaseMigrationsAfterDatabaseRefreshed()
24+
{
25+
Schema::create('hashed_casts', function (Blueprint $table) {
26+
$table->increments('id');
27+
$table->string('password')->nullable();
28+
});
29+
}
30+
31+
public function testHashed()
32+
{
33+
$this->hasher->expects('needsRehash')
34+
->with('this is a password')
35+
->andReturnTrue();
36+
37+
$this->hasher->expects('make')
38+
->with('this is a password')
39+
->andReturn('hashed-password');
40+
41+
$subject = HashedCast::create([
42+
'password' => 'this is a password',
43+
]);
44+
45+
$this->assertSame('hashed-password', $subject->password);
46+
$this->assertDatabaseHas('hashed_casts', [
47+
'id' => $subject->id,
48+
'password' => 'hashed-password',
49+
]);
50+
}
51+
52+
public function testNotHashedIfAlreadyHashed()
53+
{
54+
$this->hasher->expects('needsRehash')
55+
->with('already-hashed-password')
56+
->andReturnFalse();
57+
58+
$subject = HashedCast::create([
59+
'password' => 'already-hashed-password',
60+
]);
61+
62+
$this->assertSame('already-hashed-password', $subject->password);
63+
$this->assertDatabaseHas('hashed_casts', [
64+
'id' => $subject->id,
65+
'password' => 'already-hashed-password',
66+
]);
67+
}
68+
69+
public function testNotHashedIfNull()
70+
{
71+
$subject = HashedCast::create([
72+
'password' => null,
73+
]);
74+
75+
$this->assertNull($subject->password);
76+
$this->assertDatabaseHas('hashed_casts', [
77+
'id' => $subject->id,
78+
'password' => null,
79+
]);
80+
}
81+
}
82+
83+
class HashedCast extends Model
84+
{
85+
public $timestamps = false;
86+
protected $guarded = [];
87+
88+
public $casts = [
89+
'password' => 'hashed',
90+
];
91+
}

0 commit comments

Comments
 (0)