From 5ef335a5be554a07f9034a5677891b15b48e2f15 Mon Sep 17 00:00:00 2001
From: Fabrice Gangler <fabrice.gangler@adullact.org>
Date: Fri, 19 Jul 2024 12:24:18 +0200
Subject: [PATCH] feat(user): add Form/user/*Type.php

---
 .../src/Form/User/ChangePasswordFormType.php  | 112 ++++++++++++++++++
 .../src/Form/User/ResetPasswordFormType.php   |  98 +++++++++++++++
 .../User/ResetPasswordRequestFormType.php     |  65 ++++++++++
 3 files changed, 275 insertions(+)
 create mode 100644 webapp/src/Form/User/ChangePasswordFormType.php
 create mode 100644 webapp/src/Form/User/ResetPasswordFormType.php
 create mode 100644 webapp/src/Form/User/ResetPasswordRequestFormType.php

diff --git a/webapp/src/Form/User/ChangePasswordFormType.php b/webapp/src/Form/User/ChangePasswordFormType.php
new file mode 100644
index 0000000..630166f
--- /dev/null
+++ b/webapp/src/Form/User/ChangePasswordFormType.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Comptoir-du-Libre software.
+ * <https://gitlab.adullact.net/Comptoir/comptoir-du-libre>
+ *
+ * Copyright (c) ADULLACT   <https://adullact.org>
+ *               Association des Développeurs et Utilisateurs de Logiciels Libres
+ *               pour les Administrations et les Collectivités Territoriales
+ *
+ * Comptoir-du-Libre is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this software. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>.
+ */
+
+declare(strict_types=1);
+
+namespace App\Form\User;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\PasswordType;
+use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Translation\TranslatableMessage;
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Validator\Constraints\NotBlank;
+
+class ChangePasswordFormType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options): void
+    {
+        $builder
+            ->add('currentPlainPassword', PasswordType::class, [
+                // instead of being set onto the object directly,
+                // this is read and encoded in the controller
+                'mapped' => false,
+                'attr' => ['autocomplete' => 'new-password'],
+                'label' => 'user.change_password.form.label.current-password',
+                'help' => 'user.change_password.form.label.current-password.help',
+                'constraints' => [
+                    new NotBlank([
+                        'message' => 'common.validator.help.field.error.required',
+                    ]),
+                    new Length([
+                        // max length allowed by Symfony for security reasons
+                        'max' => 4096,
+                    ]),
+                ],
+            ])
+            ->add('newPlainPassword', RepeatedType::class, [
+                'type' => PasswordType::class,
+                'options' => [
+                    'attr' => [
+                        'autocomplete' => 'new-password',
+                        'minlength' => $options['min_password_length'],
+                        'maxlength' => 4096, // max length allowed by Symfony for security reasons
+                    ],
+                ],
+                'first_options' => [
+                    'constraints' => [
+                        new NotBlank([
+                            'message' => 'common.validator.help.field.error.required',
+                        ]),
+                        new Length([
+                            'min' => $options['min_password_length'],
+//                          'minMessage' => 'Password should be at least {{ limit }} characters',
+                            'minMessage' => new TranslatableMessage(
+                                message: 'common.validator.help.password.error.too-short',
+                            ),
+                            'max' => 4096, // max length allowed by Symfony for security reasons
+                        ]),
+                    ],
+                    'label' => 'user.change_password.form.label.new-password',
+                    'help_html' => true,
+                    'help' => new TranslatableMessage(
+                        message: 'user.change_password.form.label.new-password.help',
+                        parameters: ['%min_password_length%' => $options['min_password_length']],
+                        domain: 'messages'
+                    ),
+                ],
+                'second_options' => [
+                    'label' => 'user.change_password.form.label.new-password-repeat',
+                    'help' => 'user.change_password.form.label.new-password-repeat.help',
+                ],
+                'invalid_message' => 'common.validator.help.password.error.new-password-must-match',
+                // Instead of being set onto the object directly,
+                // this is read and encoded in the controller
+                'mapped' => false,
+            ])
+        ;
+    }
+
+    public function configureOptions(OptionsResolver $resolver): void
+    {
+        $resolver->setDefaults([
+            'min_password_length' => 16,
+            // enable/disable CSRF protection for this form
+            'csrf_protection' => true,
+            // the name of the hidden HTML field that stores the token
+            'csrf_field_name' => 'csrf_token_ChangePassword',
+            // an arbitrary string used to generate the value of the token
+            // using a different string for each form improves its security
+            'csrf_token_id'   => 'task_ChangePasswordFormType',
+        ]);
+        $resolver->setAllowedTypes('min_password_length', 'int');
+    }
+}
diff --git a/webapp/src/Form/User/ResetPasswordFormType.php b/webapp/src/Form/User/ResetPasswordFormType.php
new file mode 100644
index 0000000..aea5b5e
--- /dev/null
+++ b/webapp/src/Form/User/ResetPasswordFormType.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Comptoir-du-Libre software.
+ * <https://gitlab.adullact.net/Comptoir/comptoir-du-libre>
+ *
+ * Copyright (c) ADULLACT   <https://adullact.org>
+ *               Association des Développeurs et Utilisateurs de Logiciels Libres
+ *               pour les Administrations et les Collectivités Territoriales
+ *
+ * Comptoir-du-Libre is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this software. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>.
+ */
+
+declare(strict_types=1);
+
+namespace App\Form\User;
+
+use App\Entity\User;
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\EmailType;
+use Symfony\Component\Form\Extension\Core\Type\PasswordType;
+use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Translation\TranslatableMessage;
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Validator\Constraints\NotBlank;
+use Symfony\Component\Validator\Constraints\Email;
+
+class ResetPasswordFormType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options): void
+    {
+        $builder
+            ->add('newPlainPassword', RepeatedType::class, [
+                'type' => PasswordType::class,
+                'options' => [
+                    'attr' => [
+                        'autocomplete' => 'new-password',
+                        'minlength' => $options['min_password_length'],
+                        'maxlength' => 4096, // max length allowed by Symfony for security reasons
+                    ],
+                ],
+                'first_options' => [
+                    'constraints' => [
+                        new NotBlank([
+                            'message' => 'common.validator.help.field.error.required',
+                        ]),
+                        new Length([
+                            'min' => $options['min_password_length'],
+//                          'minMessage' => 'Password should be at least {{ limit }} characters',
+                            'minMessage' => new TranslatableMessage(
+                                message: 'common.validator.help.password.error.too-short',
+                            ),
+                            'max' => 4096, // max length allowed by Symfony for security reasons
+                        ]),
+                    ],
+                    'label' => 'forgot_password.form.label.new-password',
+                    'help_html' => true,
+                    'help' => new TranslatableMessage(
+                        message: 'forgot_password.form.label.new-password.help',
+                        parameters: ['%min_password_length%' => $options['min_password_length']],
+                        domain: 'messages'
+                    ),
+                ],
+                'second_options' => [
+                    'label' => 'forgot_password.form.label.new-password-repeat',
+                    'help' => 'forgot_password.form.label.new-password-repeat.help',
+                ],
+                'invalid_message' => 'common.validator.help.password.error.new-password-must-match',
+                // Instead of being set onto the object directly,
+                // this is read and encoded in the controller
+                'mapped' => false,
+            ])
+        ;
+    }
+
+    public function configureOptions(OptionsResolver $resolver): void
+    {
+        $resolver->setDefaults([
+            'min_password_length' => 16,
+            // enable/disable CSRF protection for this form
+            'csrf_protection' => true,
+            // the name of the hidden HTML field that stores the token
+            'csrf_field_name' => 'csrf_token_ResetPassword',
+            // an arbitrary string used to generate the value of the token
+            // using a different string for each form improves its security
+            'csrf_token_id'   => 'task_ResetPasswordFormType',
+        ]);
+        $resolver->setAllowedTypes('min_password_length', 'int');
+    }
+}
diff --git a/webapp/src/Form/User/ResetPasswordRequestFormType.php b/webapp/src/Form/User/ResetPasswordRequestFormType.php
new file mode 100644
index 0000000..7332e69
--- /dev/null
+++ b/webapp/src/Form/User/ResetPasswordRequestFormType.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Comptoir-du-Libre software.
+ * <https://gitlab.adullact.net/Comptoir/comptoir-du-libre>
+ *
+ * Copyright (c) ADULLACT   <https://adullact.org>
+ *               Association des Développeurs et Utilisateurs de Logiciels Libres
+ *               pour les Administrations et les Collectivités Territoriales
+ *
+ * Comptoir-du-Libre is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this software. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>.
+ */
+
+declare(strict_types=1);
+
+namespace App\Form\User;
+
+use App\Entity\User;
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\EmailType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Validator\Constraints\NotBlank;
+use Symfony\Component\Validator\Constraints\Email;
+
+class ResetPasswordRequestFormType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options): void
+    {
+        $builder
+            ->add('email', EmailType::class, [
+                'label' => 'forgot_password.request.form.label.email',
+                'help' => 'forgot_password.request.form.label.email.help',
+                'constraints' => [
+                    new NotBlank([
+                        'message' => 'common.validator.help.field.error.required',
+                    ]),
+                    new Email([
+                        'mode' => 'html5',
+                        'message' => 'common.validator.help.email.error.not-valid',
+                    ]),
+                ],
+            ])
+        ;
+    }
+
+    public function configureOptions(OptionsResolver $resolver): void
+    {
+        $resolver->setDefaults([
+            // enable/disable CSRF protection for this form
+            'csrf_protection' => true,
+            // the name of the hidden HTML field that stores the token
+            'csrf_field_name' => 'csrf_token_ResetPasswordRequest',
+            // an arbitrary string used to generate the value of the token
+            // using a different string for each form improves its security
+            'csrf_token_id'   => 'task_ResetPasswordRequestFormType',
+        ]);
+    }
+}
-- 
GitLab