Skip to content

Commit

Permalink
Merge branch '6.4' into 7.0
Browse files Browse the repository at this point in the history
* 6.4: (32 commits)
  [Validator] Fix registering "is_valid()" for `#[Expression]`
  [Scheduler] Trigger unique messages at runtime
  [Scheduler] Fix CHANGELOG
  [Clock] Add `DatePoint`: an immutable DateTime implementation with stricter error handling and return types
  [Scheduler] Allow modifying the schedule at runtime and recalculate heap
  [Cache] Fix Redis6Proxy
  [Finder] Disable failing test about open_basedir
  Fix merge
  Fix merge
  Minor CS fixes
  Deprecate `Kernel::stripComments()`
  Remove setAccessible reflection call in tests
  [Notifier] Telegram Bridge add escaping for \
  [Component][AssertMapper] add type hint of an argument in asset mapper command
  [Translation] [Phrase] Refacto ReadConfig and WriteConfig into arrays
  [Routing] Fix routing collection defaults when adding a new route to a collection
  [Messenger] Fix cloned TraceableStack not unstacking the stack independently
  [Translation] Add `--as-tree` option  to `translation:pull` command
  [Mime] Allow to add some headers as a strings
  [Translation] Give current locale to locale switcher runWithLocale callback
  ...
  • Loading branch information
nicolas-grekas committed Sep 27, 2023
2 parents 02f0f66 + 4a67637 commit 4b0390d
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 18 deletions.
50 changes: 32 additions & 18 deletions Hasher/PasswordHasherFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ public function getPasswordHasher(string|PasswordAuthenticatedUserInterface|Pass
*/
private function createHasher(array $config, bool $isExtra = false): PasswordHasherInterface
{
if (isset($config['instance'])) {
if (!isset($config['migrate_from'])) {
return $config['instance'];
}

$config = $this->getMigratingPasswordConfig($config);
}

if (isset($config['algorithm'])) {
$rawConfig = $config;
$config = $this->getHasherConfigFromAlgorithm($config);
Expand Down Expand Up @@ -126,24 +134,8 @@ private function getHasherConfigFromAlgorithm(array $config): array
];
}

if ($frompasswordHashers = ($config['migrate_from'] ?? false)) {
unset($config['migrate_from']);
$hasherChain = [$this->createHasher($config, true)];

foreach ($frompasswordHashers as $name) {
if ($hasher = $this->passwordHashers[$name] ?? false) {
$hasher = $hasher instanceof PasswordHasherInterface ? $hasher : $this->createHasher($hasher, true);
} else {
$hasher = $this->createHasher(['algorithm' => $name], true);
}

$hasherChain[] = $hasher;
}

return [
'class' => MigratingPasswordHasher::class,
'arguments' => $hasherChain,
];
if ($config['migrate_from'] ?? false) {
return $this->getMigratingPasswordConfig($config);
}

switch ($config['algorithm']) {
Expand Down Expand Up @@ -223,4 +215,26 @@ private function getHasherConfigFromAlgorithm(array $config): array
],
];
}

private function getMigratingPasswordConfig(array $config): array
{
$frompasswordHashers = $config['migrate_from'];
unset($config['migrate_from']);
$hasherChain = [$this->createHasher($config, true)];

foreach ($frompasswordHashers as $name) {
if ($hasher = $this->passwordHashers[$name] ?? false) {
$hasher = $hasher instanceof PasswordHasherInterface ? $hasher : $this->createHasher($hasher, true);
} else {
$hasher = $this->createHasher(['algorithm' => $name], true);
}

$hasherChain[] = $hasher;
}

return [
'class' => MigratingPasswordHasher::class,
'arguments' => $hasherChain,
];
}
}
33 changes: 33 additions & 0 deletions Tests/Hasher/PasswordHasherFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ public function testGetHasherWithService()
$this->assertEquals($expectedHasher->hash('foo', ''), $hasher->hash('foo', ''));
}

public function testGetHasherWithInstance()
{
$factory = new PasswordHasherFactory([
PasswordAuthenticatedUserInterface::class => ['instance' => new MessageDigestPasswordHasher('sha1')],
]);

$hasher = $factory->getPasswordHasher($this->createMock(PasswordAuthenticatedUserInterface::class));
$expectedHasher = new MessageDigestPasswordHasher('sha1');
$this->assertEquals($expectedHasher->hash('foo', ''), $hasher->hash('foo', ''));
}

public function testGetHasherWithClassName()
{
$factory = new PasswordHasherFactory([
Expand Down Expand Up @@ -183,6 +194,28 @@ public function testDefaultMigratingHashers()
(new PasswordHasherFactory([SomeUser::class => ['class' => SodiumPasswordHasher::class, 'arguments' => []]]))->getPasswordHasher(SomeUser::class)
);
}

public function testMigrateFromWithCustomInstance()
{
if (!SodiumPasswordHasher::isSupported()) {
$this->markTestSkipped('Sodium is not available');
}

$sodium = new SodiumPasswordHasher();

$factory = new PasswordHasherFactory([
'digest_hasher' => $digest = new MessageDigestPasswordHasher('sha256'),
SomeUser::class => ['instance' => $sodium, 'migrate_from' => ['bcrypt', 'digest_hasher']],
]);

$hasher = $factory->getPasswordHasher(SomeUser::class);
$this->assertInstanceOf(MigratingPasswordHasher::class, $hasher);

$this->assertTrue($hasher->verify((new SodiumPasswordHasher())->hash('foo', null), 'foo', null));
$this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, null, \PASSWORD_BCRYPT))->hash('foo', null), 'foo', null));
$this->assertTrue($hasher->verify($digest->hash('foo', null), 'foo', null));
$this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null));
}
}

class SomeUser implements PasswordAuthenticatedUserInterface
Expand Down

0 comments on commit 4b0390d

Please sign in to comment.