From 7e89801956f4ab6269b7ae1bbf78114770349e2d Mon Sep 17 00:00:00 2001 From: Bechir Ba <13308700+bechir@users.noreply.github.com> Date: Thu, 22 Jun 2023 20:35:22 +0000 Subject: [PATCH] [make:auth] Add `RememberMeBadge` --- src/Maker/MakeAuthenticator.php | 67 ++++++++++++++--- .../LoginFormAuthenticator.tpl.php | 3 +- .../skeleton/authenticator/login_form.tpl.php | 21 +++--- src/Security/SecurityConfigUpdater.php | 37 +++++++++- tests/Maker/MakeAuthenticatorTest.php | 72 +++++++++++++++++++ tests/Security/SecurityConfigUpdaterTest.php | 40 +++++++++-- ...with_firewalls_and_always_remember_me.yaml | 18 +++++ ...th_firewalls_and_remember_me_checkbox.yaml | 20 ++++++ 8 files changed, 253 insertions(+), 25 deletions(-) create mode 100644 tests/Security/yaml_fixtures/expected_authenticator/simple_security_with_firewalls_and_always_remember_me.yaml create mode 100644 tests/Security/yaml_fixtures/expected_authenticator/simple_security_with_firewalls_and_remember_me_checkbox.yaml diff --git a/src/Maker/MakeAuthenticator.php b/src/Maker/MakeAuthenticator.php index 0e2c69715..ba9402907 100644 --- a/src/Maker/MakeAuthenticator.php +++ b/src/Maker/MakeAuthenticator.php @@ -49,6 +49,7 @@ use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator; use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge; +use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; @@ -66,6 +67,9 @@ final class MakeAuthenticator extends AbstractMaker private const AUTH_TYPE_EMPTY_AUTHENTICATOR = 'empty-authenticator'; private const AUTH_TYPE_FORM_LOGIN = 'form-login'; + private const REMEMBER_ME_TYPE_ALWAYS = 'always'; + private const REMEMBER_ME_TYPE_CHECKBOX = 'checkbox'; + public function __construct( private FileManager $fileManager, private SecurityConfigUpdater $configUpdater, @@ -184,6 +188,34 @@ function ($answer) { true ) ); + + $command->addArgument('support-remember-me', InputArgument::REQUIRED); + $input->setArgument( + 'support-remember-me', + $io->confirm( + 'Do you want to support remember me?', + true + ) + ); + + if ($input->getArgument('support-remember-me')) { + $supportRememberMeValues = [ + 'Activate when the user checks a box' => self::REMEMBER_ME_TYPE_CHECKBOX, + 'Always activate remember me' => self::REMEMBER_ME_TYPE_ALWAYS, + ]; + $command->addArgument('always-remember-me', InputArgument::REQUIRED); + + $supportRememberMeType = $io->choice( + 'When activate the remember me?', + array_keys($supportRememberMeValues), + key($supportRememberMeValues) + ); + + $input->setArgument( + 'always-remember-me', + $supportRememberMeValues[$supportRememberMeType] + ); + } } } @@ -192,12 +224,16 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $manipulator = new YamlSourceManipulator($this->fileManager->getFileContents('config/packages/security.yaml')); $securityData = $manipulator->getData(); + $supportRememberMe = $input->hasArgument('support-remember-me') ? $input->getArgument('support-remember-me') : false; + $alwaysRememberMe = $input->hasArgument('always-remember-me') ? $input->getArgument('always-remember-me') : false; + $this->generateAuthenticatorClass( $securityData, $input->getArgument('authenticator-type'), $input->getArgument('authenticator-class'), $input->hasArgument('user-class') ? $input->getArgument('user-class') : null, - $input->hasArgument('username-field') ? $input->getArgument('username-field') : null + $input->hasArgument('username-field') ? $input->getArgument('username-field') : null, + $supportRememberMe, ); // update security.yaml with guard config @@ -215,7 +251,9 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $input->getOption('firewall-name'), $entryPoint, $input->getArgument('authenticator-class'), - $input->hasArgument('logout-setup') ? $input->getArgument('logout-setup') : false + $input->hasArgument('logout-setup') ? $input->getArgument('logout-setup') : false, + $supportRememberMe, + $alwaysRememberMe ); $generator->dumpFile($path, $newYaml); $securityYamlUpdated = true; @@ -226,7 +264,9 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $this->generateFormLoginFiles( $input->getArgument('controller-class'), $input->getArgument('username-field'), - $input->getArgument('logout-setup') + $input->getArgument('logout-setup'), + $supportRememberMe, + $alwaysRememberMe, ); } @@ -241,12 +281,14 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $input->getArgument('authenticator-class'), $securityData, $input->hasArgument('user-class') ? $input->getArgument('user-class') : null, - $input->hasArgument('logout-setup') ? $input->getArgument('logout-setup') : false + $input->hasArgument('logout-setup') ? $input->getArgument('logout-setup') : false, + $supportRememberMe, + $alwaysRememberMe ) ); } - private function generateAuthenticatorClass(array $securityData, string $authenticatorType, string $authenticatorClass, $userClass, $userNameField): void + private function generateAuthenticatorClass(array $securityData, string $authenticatorType, string $authenticatorClass, $userClass, $userNameField, bool $supportRememberMe): void { $useStatements = new UseStatementGenerator([ Request::class, @@ -288,6 +330,10 @@ private function generateAuthenticatorClass(array $securityData, string $authent $useStatements->addUseStatement(LegacySecurity::class); } + if ($supportRememberMe) { + $useStatements->addUseStatement(RememberMeBadge::class); + } + $userClassNameDetails = $this->generator->createClassNameDetails( '\\'.$userClass, 'Entity\\' @@ -305,11 +351,12 @@ private function generateAuthenticatorClass(array $securityData, string $authent 'username_field_var' => Str::asLowerCamelCase($userNameField), 'user_needs_encoder' => $this->userClassHasEncoder($securityData, $userClass), 'user_is_entity' => $this->doctrineHelper->isClassAMappedEntity($userClass), + 'remember_me_badge' => $supportRememberMe, ] ); } - private function generateFormLoginFiles(string $controllerClass, string $userNameField, bool $logoutSetup): void + private function generateFormLoginFiles(string $controllerClass, string $userNameField, bool $logoutSetup, bool $supportRememberMe, bool $alwaysRememberMe): void { $controllerClassNameDetails = $this->generator->createClassNameDetails( $controllerClass, @@ -362,11 +409,13 @@ private function generateFormLoginFiles(string $controllerClass, string $userNam 'username_is_email' => false !== stripos($userNameField, 'email'), 'username_label' => ucfirst(Str::asHumanWords($userNameField)), 'logout_setup' => $logoutSetup, + 'support_remember_me' => $supportRememberMe, + 'always_remember_me' => $alwaysRememberMe, ] ); } - private function generateNextMessage(bool $securityYamlUpdated, string $authenticatorType, string $authenticatorClass, array $securityData, $userClass, bool $logoutSetup): array + private function generateNextMessage(bool $securityYamlUpdated, string $authenticatorType, string $authenticatorClass, array $securityData, $userClass, bool $logoutSetup, bool $supportRememberMe, bool $alwaysRememberMe): array { $nextTexts = ['Next:']; $nextTexts[] = '- Customize your new authenticator.'; @@ -377,7 +426,9 @@ private function generateNextMessage(bool $securityYamlUpdated, string $authenti 'main', null, $authenticatorClass, - $logoutSetup + $logoutSetup, + $supportRememberMe, + $alwaysRememberMe ); $nextTexts[] = "- Your security.yaml could not be updated automatically. You'll need to add the following config manually:\n\n".$yamlExample; } diff --git a/src/Resources/skeleton/authenticator/LoginFormAuthenticator.tpl.php b/src/Resources/skeleton/authenticator/LoginFormAuthenticator.tpl.php index a7d6ba04f..eb0f17219 100644 --- a/src/Resources/skeleton/authenticator/LoginFormAuthenticator.tpl.php +++ b/src/Resources/skeleton/authenticator/LoginFormAuthenticator.tpl.php @@ -24,7 +24,8 @@ public function authenticate(Request $request): Passport new UserBadge($), new PasswordCredentials($request->request->get('password', '')), [ - new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')), + new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')), ] ); } diff --git a/src/Resources/skeleton/authenticator/login_form.tpl.php b/src/Resources/skeleton/authenticator/login_form.tpl.php index 95bc79a3f..4124397ac 100644 --- a/src/Resources/skeleton/authenticator/login_form.tpl.php +++ b/src/Resources/skeleton/authenticator/login_form.tpl.php @@ -25,17 +25,16 @@ - - {# - Uncomment this section and add a remember_me option below your firewall to activate remember me functionality. - See https://symfony.com/doc/current/security/remember_me.html - -
- -
- #} + + + +
+ +
+ +