113 lines
3.9 KiB
PHP
113 lines
3.9 KiB
PHP
<?php
|
|
|
|
namespace App\Base\Framework\Command;
|
|
|
|
use App\User\Framework\Repository\UserRepository;
|
|
use Symfony\Bundle\SecurityBundle\Security;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Question\Question;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
|
use Symfony\Component\Security\Core\User\UserInterface;
|
|
|
|
#[AsCommand(name: 'user:reset-password', description: 'Resets the password for the given user. Requires either the ID or email of the User. You will be asked for the password after running the command.')]
|
|
class UserResetPasswordCommand extends Command
|
|
{
|
|
private readonly Security $security;
|
|
private readonly UserRepository $userRepository;
|
|
private readonly UserPasswordHasherInterface $hasher;
|
|
|
|
public function __construct(
|
|
Security $security,
|
|
UserRepository $userRepository,
|
|
UserPasswordHasherInterface $hasher,
|
|
) {
|
|
parent::__construct();
|
|
$this->security = $security;
|
|
$this->userRepository = $userRepository;
|
|
$this->hasher = $hasher;
|
|
}
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this
|
|
->addOption('id', null, InputOption::VALUE_REQUIRED, 'The ID of the user in the database.')
|
|
->addOption('email', null, InputOption::VALUE_REQUIRED, 'The email of the user.')
|
|
;
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$queryParams = $this->parseInput($input, $io);
|
|
if ([] === $queryParams) {
|
|
$io->error('No ID or Email specified. Please run again and pass the "--id" or "--email" option.');
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$user = $this->userRepository->findOneBy($queryParams);
|
|
if (null === $user) {
|
|
$io->error('No such user exists.');
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
try {
|
|
$newPassword = $this->askForPassword($input, $output);
|
|
$this->updateUsersPassword($user, $newPassword);
|
|
} catch (\Throwable $exception) {
|
|
$io->error($exception->getMessage());
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$io->success('Success. The password has been reset.');
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
private function parseInput(InputInterface $input, SymfonyStyle $io): array
|
|
{
|
|
if ($input->getOption('id')) {
|
|
return ['id' => $input->getOption('id')];
|
|
} elseif ($input->getOption('email')) {
|
|
return ['email' => $input->getOption('email')];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
private function askForPassword(InputInterface $input, OutputInterface $output): ?string
|
|
{
|
|
$questionHelper = new QuestionHelper();
|
|
$question = new Question('New password (input is hidden): ')
|
|
->setHidden(true)
|
|
->setHiddenFallback(false)
|
|
->setNormalizer(function (?string $value): string {
|
|
return $value ?? '';
|
|
})
|
|
->setValidator(function (string $value): string {
|
|
if ('' === trim($value)) {
|
|
throw new \Exception('The password cannot be empty');
|
|
}
|
|
return $value;
|
|
})
|
|
->setMaxAttempts(5)
|
|
;
|
|
|
|
return $questionHelper->ask($input, $output, $question);
|
|
}
|
|
|
|
private function updateUsersPassword(UserInterface $user, string $newPassword): void
|
|
{
|
|
$user->setPassword(
|
|
$this->hasher->hashPassword($user, $newPassword)
|
|
);
|
|
$this->userRepository->getEntityManager()->flush();
|
|
}
|
|
}
|