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($= $username_field_var ?>),
new PasswordCredentials($request->request->get('password', '')),
[
- new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),
+ new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),= $remember_me_badge ? "
+ new RememberMeBadge(),\n" : "" ?>
]
);
}
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
-
-
-
-
- #}
+
+
+
+
+
+
+
+