<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\UserBundle\Command;
use FOS\UserBundle\Model\UserManagerInterface;
use Sonata\UserBundle\GoogleAuthenticator\Helper;
use Sonata\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* NEXT_MAJOR: stop extending ContainerAwareCommand.
*/
class TwoStepVerificationCommand extends ContainerAwareCommand
{
/**
* @var ?Helper
*/
private $helper;
/**
* @var ?UserManagerInterface
*/
private $userManager;
/**
* NEXT_MAJOR: make $helper and $userManager mandatory (but still nullable).
*/
public function __construct(
?string $name,
?Helper $helper = null,
?UserManagerInterface $userManager = null
) {
parent::__construct($name);
$this->helper = $helper;
$this->userManager = $userManager;
}
/**
* {@inheritdoc}
*/
public function configure(): void
{
$this->setName('sonata:user:two-step-verification');
$this->addArgument(
'username',
InputArgument::REQUIRED,
'The username to protect with a two step verification process'
);
$this->addOption('reset', null, InputOption::VALUE_NONE, 'Reset the current two step verification token');
$this->setDescription(
'Generate a two step verification process to secure an access (Ideal for super admin protection)'
);
}
/**
* {@inheritdoc}
*/
public function execute(InputInterface $input, OutputInterface $output): void
{
if (null === $this->helper && !$this->getContainer()->has('sonata.user.google.authenticator.provider')) {
throw new \RuntimeException('Two Step Verification process is not enabled');
}
if (null === $this->helper) {
@trigger_error(sprintf(
'Not providing the $helper argument of "%s::__construct()" is deprecated since 4.3.0 and will no longer be possible in 5.0',
__CLASS__
), E_USER_DEPRECATED);
$helper = $this->getContainer()->get('sonata.user.google.authenticator.provider');
\assert($helper instanceof Helper);
$this->helper = $helper;
}
if (null === $this->userManager) {
@trigger_error(sprintf(
'Not providing the $userManager argument of "%s::__construct()" is deprecated since 4.3.0 and will no longer be possible in 5.0',
__CLASS__
), E_USER_DEPRECATED);
$manager = $this->getContainer()->get('fos_user.user_manager');
\assert($manager instanceof UserManagerInterface);
$this->userManager = $manager;
}
$user = $this->userManager->findUserByUsernameOrEmail($input->getArgument('username'));
\assert($user instanceof UserInterface);
if (!$user) {
throw new \RuntimeException(sprintf('Unable to find the username : %s', $input->getArgument('username')));
}
if (!$user->getTwoStepVerificationCode() || $input->getOption('reset')) {
$user->setTwoStepVerificationCode($this->helper->generateSecret());
$this->userManager->updateUser($user);
}
$output->writeln([
sprintf('<info>Username</info> : %s', $input->getArgument('username')),
sprintf('<info>Secret</info> : %s', $user->getTwoStepVerificationCode()),
sprintf('<info>Url</info> : %s', $this->helper->getUrl($user)),
]);
}
}