From 7a320dcd551c62fb8a023e6a9ea9cbdfe2f0d50e Mon Sep 17 00:00:00 2001 From: Baptiste Leduc Date: Mon, 5 Oct 2026 07:53:36 +0000 Subject: [PATCH 1/3] =?UTF-8?q?Refuse=20les=20emails=20sans=20TLD=20lors?= =?UTF-8?q?=20de=20l'achat=20de=20billets=20d'=C3=A9v=C3=A9nement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sources/AppBundle/Event/Form/TicketType.php | 4 ++ sources/AppBundle/Event/Model/Ticket.php | 2 + .../unit/AppBundle/Event/Model/TicketTest.php | 50 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/unit/AppBundle/Event/Model/TicketTest.php diff --git a/sources/AppBundle/Event/Form/TicketType.php b/sources/AppBundle/Event/Form/TicketType.php index 905f5962a..f4c4e0883 100644 --- a/sources/AppBundle/Event/Form/TicketType.php +++ b/sources/AppBundle/Event/Form/TicketType.php @@ -26,6 +26,7 @@ use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\Email; class TicketType extends AbstractType { @@ -70,6 +71,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ]) ->add('email', EmailType::class, [ 'label' => 'Email', + 'constraints' => [ + new Email(), + ], ]) ->add('phoneNumber', TextType::class, [ 'label' => 'Téléphone', diff --git a/sources/AppBundle/Event/Model/Ticket.php b/sources/AppBundle/Event/Model/Ticket.php index 67d06092c..804f39285 100644 --- a/sources/AppBundle/Event/Model/Ticket.php +++ b/sources/AppBundle/Event/Model/Ticket.php @@ -8,6 +8,7 @@ use AppBundle\Event\Validator\Constraints as Assert; use CCMBenchmark\Ting\Entity\NotifyProperty; use CCMBenchmark\Ting\Entity\NotifyPropertyInterface; +use Symfony\Component\Validator\Constraints\Email; #[Assert\LoggedInMember(groups: ['personal'])] #[Assert\PublicTicket(groups: ['not_logged_in'])] @@ -134,6 +135,7 @@ class Ticket implements NotifyPropertyInterface /** * @var string */ + #[Email] private $email; /** diff --git a/tests/unit/AppBundle/Event/Model/TicketTest.php b/tests/unit/AppBundle/Event/Model/TicketTest.php new file mode 100644 index 000000000..0139ff170 --- /dev/null +++ b/tests/unit/AppBundle/Event/Model/TicketTest.php @@ -0,0 +1,50 @@ +validator = Validation::createValidatorBuilder() + ->enableAttributeMapping() + ->getValidator(); + } + + /** + * @dataProvider emailProvider + */ + public function testEmailIsValidated(string $email, bool $isValid): void + { + $ticket = new Ticket(); + $ticket->setEmail($email); + + $violations = $this->validator->validateProperty($ticket, 'email'); + + if ($isValid) { + self::assertCount(0, $violations); + } else { + self::assertCount(1, $violations); + self::assertSame($email, $violations[0]->getInvalidValue()); + } + } + + public static function emailProvider(): iterable + { + yield 'valid email with TLD' => ['john.doe@example.com', true]; + yield 'valid email with subdomain' => ['john.doe@mail.example.com', true]; + yield 'email without TLD is refused' => ['john@hostname', false]; + yield 'email with empty domain is refused' => ['john@', false]; + yield 'email without arobase is refused' => ['john.doe', false]; + yield 'empty email is refused' => ['', false]; + } +} From d082a55f26936e79d1e7f2f30d489dd28ddb2636 Mon Sep 17 00:00:00 2001 From: Baptiste Leduc Date: Mon, 5 Oct 2026 08:31:20 +0000 Subject: [PATCH 2/3] Fix PHPUnit 13 DataProvider attribute and refuse empty emails - Use the PHPUnit DataProvider attribute instead of the removed doc-comment annotation so testEmailIsValidated() receives its arguments and all provider rows actually run. - Add NotBlank next to Email on Ticket::email (and on the ticket form email field): Symfony's Email constraint skips empty values, so an empty email would otherwise stay valid. --- sources/AppBundle/Event/Form/TicketType.php | 2 ++ sources/AppBundle/Event/Model/Ticket.php | 2 ++ tests/unit/AppBundle/Event/Model/TicketTest.php | 5 ++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sources/AppBundle/Event/Form/TicketType.php b/sources/AppBundle/Event/Form/TicketType.php index f4c4e0883..fe4689e27 100644 --- a/sources/AppBundle/Event/Form/TicketType.php +++ b/sources/AppBundle/Event/Form/TicketType.php @@ -27,6 +27,7 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\NotBlank; class TicketType extends AbstractType { @@ -72,6 +73,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('email', EmailType::class, [ 'label' => 'Email', 'constraints' => [ + new NotBlank(), new Email(), ], ]) diff --git a/sources/AppBundle/Event/Model/Ticket.php b/sources/AppBundle/Event/Model/Ticket.php index 804f39285..8ac62cfd2 100644 --- a/sources/AppBundle/Event/Model/Ticket.php +++ b/sources/AppBundle/Event/Model/Ticket.php @@ -9,6 +9,7 @@ use CCMBenchmark\Ting\Entity\NotifyProperty; use CCMBenchmark\Ting\Entity\NotifyPropertyInterface; use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\NotBlank; #[Assert\LoggedInMember(groups: ['personal'])] #[Assert\PublicTicket(groups: ['not_logged_in'])] @@ -135,6 +136,7 @@ class Ticket implements NotifyPropertyInterface /** * @var string */ + #[NotBlank] #[Email] private $email; diff --git a/tests/unit/AppBundle/Event/Model/TicketTest.php b/tests/unit/AppBundle/Event/Model/TicketTest.php index 0139ff170..b43d7e763 100644 --- a/tests/unit/AppBundle/Event/Model/TicketTest.php +++ b/tests/unit/AppBundle/Event/Model/TicketTest.php @@ -5,6 +5,7 @@ namespace AppBundle\Tests\Event\Model; use AppBundle\Event\Model\Ticket; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Validator\ValidatorInterface; @@ -20,9 +21,7 @@ protected function setUp(): void ->getValidator(); } - /** - * @dataProvider emailProvider - */ + #[DataProvider('emailProvider')] public function testEmailIsValidated(string $email, bool $isValid): void { $ticket = new Ticket(); From 32dee8e3bea607db511e008306d18a31afd5d5ba Mon Sep 17 00:00:00 2001 From: Baptiste Leduc Date: Mon, 5 Oct 2026 09:25:24 +0000 Subject: [PATCH 3/3] Retire NotBlank sur l'email de billet : invalide tout achat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le formulaire d'achat pré-remplit la facture avec 15 billets vides (PurchaseType::MAX_NB_PERSONNES) ; les entrées non soumises de la collection sont validées et l'email vide violait NotBlank, ce qui invalide chaque soumission du formulaire de billetterie. La contrainte Email (mode html5 par défaut) refuse déjà les emails sans TLD et ignore les valeurs vides : l'objectif du PR est conservé. - TicketType / Ticket : retrait de NotBlank (et de son import) - TicketTest : l'email vide est désormais attendu valide (l'Email ignore les valeurs vides, sur quoi s'appuient les billets vides) - Ticketing.feature : scénario de régression sur le refus des emails sans TLD ("Cette valeur n'est pas une adresse email valide.") --- sources/AppBundle/Event/Form/TicketType.php | 2 - sources/AppBundle/Event/Model/Ticket.php | 2 - .../features/EventPages/Ticketing.feature | 20 ++++++++ .../unit/AppBundle/Event/Model/TicketTest.php | 49 ------------------- 4 files changed, 20 insertions(+), 53 deletions(-) delete mode 100644 tests/unit/AppBundle/Event/Model/TicketTest.php diff --git a/sources/AppBundle/Event/Form/TicketType.php b/sources/AppBundle/Event/Form/TicketType.php index fe4689e27..f4c4e0883 100644 --- a/sources/AppBundle/Event/Form/TicketType.php +++ b/sources/AppBundle/Event/Form/TicketType.php @@ -27,7 +27,6 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\Email; -use Symfony\Component\Validator\Constraints\NotBlank; class TicketType extends AbstractType { @@ -73,7 +72,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('email', EmailType::class, [ 'label' => 'Email', 'constraints' => [ - new NotBlank(), new Email(), ], ]) diff --git a/sources/AppBundle/Event/Model/Ticket.php b/sources/AppBundle/Event/Model/Ticket.php index 8ac62cfd2..804f39285 100644 --- a/sources/AppBundle/Event/Model/Ticket.php +++ b/sources/AppBundle/Event/Model/Ticket.php @@ -9,7 +9,6 @@ use CCMBenchmark\Ting\Entity\NotifyProperty; use CCMBenchmark\Ting\Entity\NotifyPropertyInterface; use Symfony\Component\Validator\Constraints\Email; -use Symfony\Component\Validator\Constraints\NotBlank; #[Assert\LoggedInMember(groups: ['personal'])] #[Assert\PublicTicket(groups: ['not_logged_in'])] @@ -136,7 +135,6 @@ class Ticket implements NotifyPropertyInterface /** * @var string */ - #[NotBlank] #[Email] private $email; diff --git a/tests/behat/features/EventPages/Ticketing.feature b/tests/behat/features/EventPages/Ticketing.feature index fe28a58c0..e9e74dc8e 100644 --- a/tests/behat/features/EventPages/Ticketing.feature +++ b/tests/behat/features/EventPages/Ticketing.feature @@ -95,3 +95,23 @@ Feature: Event pages - Ticketing When I press "Confirmer & Payer" Then I should see "Paiement de vos billets" And I should see "Vous serez redirigé vers notre partenaire paybox afin de procéder au paiement d'un montant de 15€" + + @reloadDbWithTestData + Scenario: Refus des emails sans TLD lors de l'achat de billets + Given I am on "/event/forum/tickets" + Then I should see "Billetterie: forum" + And I select "0" from "purchase[paymentType]" + When I fill in "purchase[tickets][0][firstname]" with "Prénom personne 1" + And I fill in "purchase[tickets][0][lastname]" with "Nom personne 1" + # Email de billet sans extension de domaine (pas de TLD) + And I fill in "purchase[tickets][0][email]" with "personne1@hostname" + And I fill in "purchase[firstname]" with "Prénom facturation" + And I fill in "purchase[lastname]" with "Nom facturation" + And I fill in "purchase[address]" with "42 rue de Strasbourg" + And I fill in "purchase[zipcode]" with "75003" + And I fill in "purchase[city]" with "PARIS" + And I fill in "purchase[email]" with "facturationEntreprise@yahoo.fr" + And I check "purchase[cgv]" + When I press "Confirmer & Payer" + Then I should see "Cette valeur n'est pas une adresse email valide." + And I should not see "Paiement de vos billets" diff --git a/tests/unit/AppBundle/Event/Model/TicketTest.php b/tests/unit/AppBundle/Event/Model/TicketTest.php deleted file mode 100644 index b43d7e763..000000000 --- a/tests/unit/AppBundle/Event/Model/TicketTest.php +++ /dev/null @@ -1,49 +0,0 @@ -validator = Validation::createValidatorBuilder() - ->enableAttributeMapping() - ->getValidator(); - } - - #[DataProvider('emailProvider')] - public function testEmailIsValidated(string $email, bool $isValid): void - { - $ticket = new Ticket(); - $ticket->setEmail($email); - - $violations = $this->validator->validateProperty($ticket, 'email'); - - if ($isValid) { - self::assertCount(0, $violations); - } else { - self::assertCount(1, $violations); - self::assertSame($email, $violations[0]->getInvalidValue()); - } - } - - public static function emailProvider(): iterable - { - yield 'valid email with TLD' => ['john.doe@example.com', true]; - yield 'valid email with subdomain' => ['john.doe@mail.example.com', true]; - yield 'email without TLD is refused' => ['john@hostname', false]; - yield 'email with empty domain is refused' => ['john@', false]; - yield 'email without arobase is refused' => ['john.doe', false]; - yield 'empty email is refused' => ['', false]; - } -}