From 95aca509fcc48aa806bd97e2aaf4a476d562bbf2 Mon Sep 17 00:00:00 2001 From: barillote Date: Thu, 21 Nov 2024 15:59:55 +0100 Subject: [PATCH] Login Register --- config/packages/security.yaml | 36 +++++++++-- migrations/Version20241017134137.php | 67 ------------------- migrations/Version20241017142722.php | 52 --------------- migrations/Version20241017152949.php | 46 ------------- migrations/Version20241121141451.php | 38 +++++++++++ migrations/Version20241121141722.php | 40 ++++++++++++ migrations/Version20241121141818.php | 31 +++++++++ migrations/Version20241121141912.php | 32 ++++++++++ migrations/Version20241121142119.php | 34 ++++++++++ migrations/Version20241121142432.php | 31 +++++++++ migrations/Version20241121145353.php | 32 ++++++++++ src/Controller/RegistrationController.php | 73 +++++++++++++++++++++ src/Controller/SecurityController.php | 32 ++++++++++ src/Entity/Announcement.php | 9 ++- src/Entity/Employee.php | 2 +- src/Entity/Intern.php | 4 +- src/Entity/Status.php | 78 ----------------------- src/Entity/UserApp.php | 29 +++++++-- src/Form/RegistrationFormType.php | 57 +++++++++++++++++ src/Repository/StatusRepository.php | 43 ------------- src/Security/EmailVerifier.php | 52 +++++++++++++++ templates/registration/register.html.twig | 19 ++++++ templates/security/login.html.twig | 41 ++++++++++++ 23 files changed, 573 insertions(+), 305 deletions(-) delete mode 100644 migrations/Version20241017134137.php delete mode 100644 migrations/Version20241017142722.php delete mode 100644 migrations/Version20241017152949.php create mode 100644 migrations/Version20241121141451.php create mode 100644 migrations/Version20241121141722.php create mode 100644 migrations/Version20241121141818.php create mode 100644 migrations/Version20241121141912.php create mode 100644 migrations/Version20241121142119.php create mode 100644 migrations/Version20241121142432.php create mode 100644 migrations/Version20241121145353.php create mode 100644 src/Controller/RegistrationController.php create mode 100644 src/Controller/SecurityController.php delete mode 100644 src/Entity/Status.php create mode 100644 src/Form/RegistrationFormType.php delete mode 100644 src/Repository/StatusRepository.php create mode 100644 src/Security/EmailVerifier.php create mode 100644 templates/registration/register.html.twig create mode 100644 templates/security/login.html.twig diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 6b3167f..7c33053 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,21 +1,47 @@ security: # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords password_hashers: - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'plaintext' # à mettre en auto pour sécuriser les mdp # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: # used to reload user from session & other features (e.g. switch_user) - app_user_provider: + app_intern_provider: entity: - class: App\Entity\User + class: App\Entity\Intern property: nickname + + app_employee_provider: + entity: + class: App\Entity\Employee + property: nickname + # used to reload user from session & other features (e.g. switch_user) + # used to reload user from session & other features (e.g. switch_user) firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false - main: + intern: lazy: true - provider: app_user_provider + provider: app_intern_provider + form_login: + login_path: app_login + check_path: app_login + enable_csrf: true + logout: + path: app_logout + # where to redirect after logout + # target: app_any_route + employee: + lazy: true + provider: app_employee_provider + form_login: + login_path: app_login + check_path: app_login + enable_csrf: true + logout: + path: app_logout + # where to redirect after logout + # target: app_any_route # activate different ways to authenticate # https://symfony.com/doc/current/security.html#the-firewall diff --git a/migrations/Version20241017134137.php b/migrations/Version20241017134137.php deleted file mode 100644 index 0dc3e3c..0000000 --- a/migrations/Version20241017134137.php +++ /dev/null @@ -1,67 +0,0 @@ -addSql('CREATE SEQUENCE announcement_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); - $this->addSql('CREATE SEQUENCE company_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); - $this->addSql('CREATE SEQUENCE userApp_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); - $this->addSql('CREATE TABLE announcement (id INT NOT NULL, title VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE TABLE company (id INT NOT NULL, name VARCHAR(255) NOT NULL, address VARCHAR(255) NOT NULL, tel VARCHAR(255) NOT NULL, mail VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE TABLE employee (id INT NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE TABLE intern (id INT NOT NULL, cover_letter TEXT NOT NULL, resume VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE TABLE userApp (id INT NOT NULL, nickname VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, tel VARCHAR(255) NOT NULL, address VARCHAR(255) NOT NULL, mail VARCHAR(255) NOT NULL, DISCRIMINATOR VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_NICKNAME ON userApp (nickname)'); - $this->addSql('CREATE TABLE messenger_messages (id BIGSERIAL NOT NULL, body TEXT NOT NULL, headers TEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, available_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, delivered_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0 ON messenger_messages (queue_name)'); - $this->addSql('CREATE INDEX IDX_75EA56E0E3BD61CE ON messenger_messages (available_at)'); - $this->addSql('CREATE INDEX IDX_75EA56E016BA31DB ON messenger_messages (delivered_at)'); - $this->addSql('COMMENT ON COLUMN messenger_messages.created_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('COMMENT ON COLUMN messenger_messages.available_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('COMMENT ON COLUMN messenger_messages.delivered_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('CREATE OR REPLACE FUNCTION notify_messenger_messages() RETURNS TRIGGER AS $$ - BEGIN - PERFORM pg_notify(\'messenger_messages\', NEW.queue_name::text); - RETURN NEW; - END; - $$ LANGUAGE plpgsql;'); - $this->addSql('DROP TRIGGER IF EXISTS notify_trigger ON messenger_messages;'); - $this->addSql('CREATE TRIGGER notify_trigger AFTER INSERT OR UPDATE ON messenger_messages FOR EACH ROW EXECUTE PROCEDURE notify_messenger_messages();'); - $this->addSql('ALTER TABLE employee ADD CONSTRAINT FK_5D9F75A1BF396750 FOREIGN KEY (id) REFERENCES userApp (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE intern ADD CONSTRAINT FK_A5795F36BF396750 FOREIGN KEY (id) REFERENCES userApp (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE SCHEMA public'); - $this->addSql('DROP SEQUENCE announcement_id_seq CASCADE'); - $this->addSql('DROP SEQUENCE company_id_seq CASCADE'); - $this->addSql('DROP SEQUENCE userApp_id_seq CASCADE'); - $this->addSql('ALTER TABLE employee DROP CONSTRAINT FK_5D9F75A1BF396750'); - $this->addSql('ALTER TABLE intern DROP CONSTRAINT FK_A5795F36BF396750'); - $this->addSql('DROP TABLE announcement'); - $this->addSql('DROP TABLE company'); - $this->addSql('DROP TABLE employee'); - $this->addSql('DROP TABLE intern'); - $this->addSql('DROP TABLE userApp'); - $this->addSql('DROP TABLE messenger_messages'); - } -} diff --git a/migrations/Version20241017142722.php b/migrations/Version20241017142722.php deleted file mode 100644 index 73818a8..0000000 --- a/migrations/Version20241017142722.php +++ /dev/null @@ -1,52 +0,0 @@ -addSql('CREATE SEQUENCE status_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); - $this->addSql('CREATE TABLE status (id INT NOT NULL, label VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('ALTER TABLE announcement ADD company_id INT NOT NULL'); - $this->addSql('ALTER TABLE announcement ADD status_id INT NOT NULL'); - $this->addSql('ALTER TABLE announcement ADD CONSTRAINT FK_4DB9D91C979B1AD6 FOREIGN KEY (company_id) REFERENCES company (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE announcement ADD CONSTRAINT FK_4DB9D91C6BF700BD FOREIGN KEY (status_id) REFERENCES status (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('CREATE INDEX IDX_4DB9D91C979B1AD6 ON announcement (company_id)'); - $this->addSql('CREATE INDEX IDX_4DB9D91C6BF700BD ON announcement (status_id)'); - $this->addSql('ALTER TABLE employee ADD company_id INT NOT NULL'); - $this->addSql('ALTER TABLE employee ADD CONSTRAINT FK_5D9F75A1979B1AD6 FOREIGN KEY (company_id) REFERENCES company (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('CREATE INDEX IDX_5D9F75A1979B1AD6 ON employee (company_id)'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE SCHEMA public'); - $this->addSql('ALTER TABLE announcement DROP CONSTRAINT FK_4DB9D91C6BF700BD'); - $this->addSql('DROP SEQUENCE status_id_seq CASCADE'); - $this->addSql('DROP TABLE status'); - $this->addSql('ALTER TABLE announcement DROP CONSTRAINT FK_4DB9D91C979B1AD6'); - $this->addSql('DROP INDEX IDX_4DB9D91C979B1AD6'); - $this->addSql('DROP INDEX IDX_4DB9D91C6BF700BD'); - $this->addSql('ALTER TABLE announcement DROP company_id'); - $this->addSql('ALTER TABLE announcement DROP status_id'); - $this->addSql('ALTER TABLE employee DROP CONSTRAINT FK_5D9F75A1979B1AD6'); - $this->addSql('DROP INDEX IDX_5D9F75A1979B1AD6'); - $this->addSql('ALTER TABLE employee DROP company_id'); - } -} diff --git a/migrations/Version20241017152949.php b/migrations/Version20241017152949.php deleted file mode 100644 index 1282d23..0000000 --- a/migrations/Version20241017152949.php +++ /dev/null @@ -1,46 +0,0 @@ -addSql('CREATE TABLE favorites (intern_id INT NOT NULL, announcement_id INT NOT NULL, PRIMARY KEY(intern_id, announcement_id))'); - $this->addSql('CREATE INDEX IDX_E46960F5525DD4B4 ON favorites (intern_id)'); - $this->addSql('CREATE INDEX IDX_E46960F5913AEA17 ON favorites (announcement_id)'); - $this->addSql('CREATE TABLE applications (intern_id INT NOT NULL, announcement_id INT NOT NULL, PRIMARY KEY(intern_id, announcement_id))'); - $this->addSql('CREATE INDEX IDX_F7C966F0525DD4B4 ON applications (intern_id)'); - $this->addSql('CREATE INDEX IDX_F7C966F0913AEA17 ON applications (announcement_id)'); - $this->addSql('ALTER TABLE favorites ADD CONSTRAINT FK_E46960F5525DD4B4 FOREIGN KEY (intern_id) REFERENCES intern (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE favorites ADD CONSTRAINT FK_E46960F5913AEA17 FOREIGN KEY (announcement_id) REFERENCES announcement (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE applications ADD CONSTRAINT FK_F7C966F0525DD4B4 FOREIGN KEY (intern_id) REFERENCES intern (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE applications ADD CONSTRAINT FK_F7C966F0913AEA17 FOREIGN KEY (announcement_id) REFERENCES announcement (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE SCHEMA public'); - $this->addSql('ALTER TABLE favorites DROP CONSTRAINT FK_E46960F5525DD4B4'); - $this->addSql('ALTER TABLE favorites DROP CONSTRAINT FK_E46960F5913AEA17'); - $this->addSql('ALTER TABLE applications DROP CONSTRAINT FK_F7C966F0525DD4B4'); - $this->addSql('ALTER TABLE applications DROP CONSTRAINT FK_F7C966F0913AEA17'); - $this->addSql('DROP TABLE favorites'); - $this->addSql('DROP TABLE applications'); - } -} diff --git a/migrations/Version20241121141451.php b/migrations/Version20241121141451.php new file mode 100644 index 0000000..d51cde4 --- /dev/null +++ b/migrations/Version20241121141451.php @@ -0,0 +1,38 @@ +addSql('DROP SEQUENCE status_id_seq CASCADE'); + $this->addSql('DROP TABLE status'); + $this->addSql('ALTER TABLE userapp ADD is_verified BOOLEAN NOT NULL'); + $this->addSql('ALTER TABLE userapp ALTER roles SET NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('CREATE SEQUENCE status_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE status (id INT NOT NULL, label VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('ALTER TABLE userApp DROP is_verified'); + $this->addSql('ALTER TABLE userApp ALTER roles DROP NOT NULL'); + } +} diff --git a/migrations/Version20241121141722.php b/migrations/Version20241121141722.php new file mode 100644 index 0000000..6259ec7 --- /dev/null +++ b/migrations/Version20241121141722.php @@ -0,0 +1,40 @@ +addSql('ALTER TABLE userapp ALTER first_name DROP NOT NULL'); + $this->addSql('ALTER TABLE userapp ALTER last_name DROP NOT NULL'); + $this->addSql('ALTER TABLE userapp ALTER tel DROP NOT NULL'); + $this->addSql('ALTER TABLE userapp ALTER address DROP NOT NULL'); + $this->addSql('ALTER TABLE userapp ALTER mail DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE userApp ALTER first_name SET NOT NULL'); + $this->addSql('ALTER TABLE userApp ALTER last_name SET NOT NULL'); + $this->addSql('ALTER TABLE userApp ALTER tel SET NOT NULL'); + $this->addSql('ALTER TABLE userApp ALTER address SET NOT NULL'); + $this->addSql('ALTER TABLE userApp ALTER mail SET NOT NULL'); + } +} diff --git a/migrations/Version20241121141818.php b/migrations/Version20241121141818.php new file mode 100644 index 0000000..7eb43e8 --- /dev/null +++ b/migrations/Version20241121141818.php @@ -0,0 +1,31 @@ +addSql('CREATE SCHEMA public'); + } +} diff --git a/migrations/Version20241121141912.php b/migrations/Version20241121141912.php new file mode 100644 index 0000000..fbc5345 --- /dev/null +++ b/migrations/Version20241121141912.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE userapp ALTER is_verified DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE userApp ALTER is_verified SET NOT NULL'); + } +} diff --git a/migrations/Version20241121142119.php b/migrations/Version20241121142119.php new file mode 100644 index 0000000..44746a0 --- /dev/null +++ b/migrations/Version20241121142119.php @@ -0,0 +1,34 @@ +addSql('ALTER TABLE intern ALTER cover_letter DROP NOT NULL'); + $this->addSql('ALTER TABLE intern ALTER resume DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE intern ALTER cover_letter SET NOT NULL'); + $this->addSql('ALTER TABLE intern ALTER resume SET NOT NULL'); + } +} diff --git a/migrations/Version20241121142432.php b/migrations/Version20241121142432.php new file mode 100644 index 0000000..8226230 --- /dev/null +++ b/migrations/Version20241121142432.php @@ -0,0 +1,31 @@ +addSql('CREATE SCHEMA public'); + } +} diff --git a/migrations/Version20241121145353.php b/migrations/Version20241121145353.php new file mode 100644 index 0000000..439bd80 --- /dev/null +++ b/migrations/Version20241121145353.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE employee ALTER company_id DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE employee ALTER company_id SET NOT NULL'); + } +} diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php new file mode 100644 index 0000000..b078d9d --- /dev/null +++ b/src/Controller/RegistrationController.php @@ -0,0 +1,73 @@ +createForm(RegistrationFormType::class, $user); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + /** @var string $plainPassword */ + $plainPassword = $form->get('plainPassword')->getData(); + + // encode the plain password + $user->setPassword($userPasswordHasher->hashPassword($user, $plainPassword)); + + $entityManager->persist($user); + $entityManager->flush(); + + // do anything else you need here, like send an email + + return $security->login($user, 'form_login', 'intern'); + } + + return $this->render('registration/register.html.twig', [ + 'registrationForm' => $form, + ]); + } + + #[Route('/employee', name: '_employee')] + public function registerEmployee(Request $request, UserPasswordHasherInterface $userPasswordHasher, Security $security, EntityManagerInterface $entityManager): Response + { + $user = new Employee(); + $form = $this->createForm(RegistrationFormType::class, $user); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + /** @var string $plainPassword */ + $plainPassword = $form->get('plainPassword')->getData(); + + // encode the plain password + $user->setPassword($userPasswordHasher->hashPassword($user, $plainPassword)); + + $entityManager->persist($user); + $entityManager->flush(); + + // do anything else you need here, like send an email + + return $security->login($user, 'form_login', 'employee'); + } + + return $this->render('registration/register.html.twig', [ + 'registrationForm' => $form, + ]); + } +} diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php new file mode 100644 index 0000000..76bf5c4 --- /dev/null +++ b/src/Controller/SecurityController.php @@ -0,0 +1,32 @@ +getLastAuthenticationError(); + + // last username entered by the user + $lastUsername = $authenticationUtils->getLastUsername(); + + return $this->render('security/login.html.twig', [ + 'last_username' => $lastUsername, + 'error' => $error, + ]); + } + + #[Route(path: '/logout', name: 'app_logout')] + public function logout(): void + { + throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); + } +} diff --git a/src/Entity/Announcement.php b/src/Entity/Announcement.php index 94cf1a6..10e9d9d 100644 --- a/src/Entity/Announcement.php +++ b/src/Entity/Announcement.php @@ -26,9 +26,8 @@ class Announcement #[ORM\JoinColumn(nullable: false)] private ?Company $company = null; - #[ORM\ManyToOne(inversedBy: 'announcements')] - #[ORM\JoinColumn(nullable: false)] - private ?Status $status = null; + #[ORM\Column(length: 255)] + private ?string $status = 'notVerified'; /** * @var ?Collection @@ -92,12 +91,12 @@ class Announcement return $this; } - public function getStatus(): ?Status + public function getStatus(): ?string { return $this->status; } - public function setStatus(?Status $status): static + public function setStatus(?string $status): static { $this->status = $status; diff --git a/src/Entity/Employee.php b/src/Entity/Employee.php index 393a529..42f71b3 100644 --- a/src/Entity/Employee.php +++ b/src/Entity/Employee.php @@ -9,7 +9,7 @@ use Doctrine\ORM\Mapping as ORM; class Employee extends UserApp { #[ORM\ManyToOne(inversedBy: 'employees')] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: true)] private ?Company $company = null; public function getCompany(): ?Company diff --git a/src/Entity/Intern.php b/src/Entity/Intern.php index 2ca1f8e..daaf428 100644 --- a/src/Entity/Intern.php +++ b/src/Entity/Intern.php @@ -12,10 +12,10 @@ use Doctrine\ORM\Mapping as ORM; class Intern extends UserApp { - #[ORM\Column(type: Types::TEXT)] + #[ORM\Column(type: Types::TEXT,nullable: true)] private ?string $coverLetter = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255,nullable: true)] private ?string $resume = null; /** diff --git a/src/Entity/Status.php b/src/Entity/Status.php deleted file mode 100644 index e672f8c..0000000 --- a/src/Entity/Status.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ - #[ORM\OneToMany(targetEntity: Announcement::class, mappedBy: 'status')] - private Collection $announcements; - - public function __construct() - { - $this->announcements = new ArrayCollection(); - } - - public function getId(): ?int - { - return $this->id; - } - - public function getLabel(): ?string - { - return $this->label; - } - - public function setLabel(string $label): static - { - $this->label = $label; - - return $this; - } - - /** - * @return Collection - */ - public function getAnnouncements(): Collection - { - return $this->announcements; - } - - public function addAnnouncement(Announcement $announcement): static - { - if (!$this->announcements->contains($announcement)) { - $this->announcements->add($announcement); - $announcement->setStatus($this); - } - - return $this; - } - - public function removeAnnouncement(Announcement $announcement): static - { - if ($this->announcements->removeElement($announcement)) { - // set the owning side to null (unless already changed) - if ($announcement->getStatus() === $this) { - $announcement->setStatus(null); - } - } - - return $this; - } -} diff --git a/src/Entity/UserApp.php b/src/Entity/UserApp.php index fe10006..8f87ba6 100644 --- a/src/Entity/UserApp.php +++ b/src/Entity/UserApp.php @@ -4,6 +4,7 @@ namespace App\Entity; use App\Repository\UserRepository; use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -13,6 +14,7 @@ use Symfony\Component\Security\Core\User\UserInterface; #[ORM\DiscriminatorColumn(name: 'DISCRIMINATOR', type: 'string')] #[ORM\DiscriminatorMap(['employee' => Employee::class, 'intern' => Intern::class])] #[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_NICKNAME', fields: ['nickname'])] +#[UniqueEntity(fields: ['nickname'], message: 'Il y a déjà un compte avec ces identifiants !')] class UserApp implements UserInterface, PasswordAuthenticatedUserInterface { #[ORM\Id] @@ -27,7 +29,7 @@ class UserApp implements UserInterface, PasswordAuthenticatedUserInterface * @var list The user roles */ #[ORM\Column] - private array $roles = []; + private array $roles = ["ROLE_USER"]; /** * @var string The hashed password @@ -35,21 +37,24 @@ class UserApp implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column] private ?string $password = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $firstName = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $lastName = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255,nullable: true)] private ?string $tel = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255,nullable: true)] private ?string $address = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255,nullable: true)] private ?string $mail = null; + #[ORM\Column(nullable: true)] + private bool $isVerified = false; + public function getId(): ?int { return $this->id; @@ -184,6 +189,18 @@ class UserApp implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + + public function isVerified(): bool + { + return $this->isVerified; + } + + public function setVerified(bool $isVerified): static + { + $this->isVerified = $isVerified; + + return $this; + } } diff --git a/src/Form/RegistrationFormType.php b/src/Form/RegistrationFormType.php new file mode 100644 index 0000000..264b544 --- /dev/null +++ b/src/Form/RegistrationFormType.php @@ -0,0 +1,57 @@ +add('nickname') + ->add('agreeTerms', CheckboxType::class, [ + 'mapped' => false, + 'constraints' => [ + new IsTrue([ + 'message' => 'Vous devez accepter les conditions d\'utilisation.', + ]), + ], + ]) + ->add('plainPassword', PasswordType::class, [ + // instead of being set onto the object directly, + // this is read and encoded in the controller + 'mapped' => false, + 'attr' => ['autocomplete' => 'new-password'], + 'constraints' => [ + new NotBlank([ + 'message' => 'Merci d\'entrer votre mot de passe.', + ]), + new Length([ + 'min' => 6, + 'minMessage' => 'Votre mot de passe doit avoir au moins {{ limit }} caractères', + // max length allowed by Symfony for security reasons + 'max' => 4096, + ]), + ], + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => UserApp::class, + ]); + } +} diff --git a/src/Repository/StatusRepository.php b/src/Repository/StatusRepository.php deleted file mode 100644 index ea2e260..0000000 --- a/src/Repository/StatusRepository.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ -class StatusRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Status::class); - } - -// /** -// * @return Status[] Returns an array of Status objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('v') -// ->andWhere('v.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('v.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } - -// public function findOneBySomeField($value): ?Status -// { -// return $this->createQueryBuilder('v') -// ->andWhere('v.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } -} diff --git a/src/Security/EmailVerifier.php b/src/Security/EmailVerifier.php new file mode 100644 index 0000000..0768c22 --- /dev/null +++ b/src/Security/EmailVerifier.php @@ -0,0 +1,52 @@ +verifyEmailHelper->generateSignature( + $verifyEmailRouteName, + (string) $user->getId(), + (string) $user->getMail() + ); + + $context = $email->getContext(); + $context['signedUrl'] = $signatureComponents->getSignedUrl(); + $context['expiresAtMessageKey'] = $signatureComponents->getExpirationMessageKey(); + $context['expiresAtMessageData'] = $signatureComponents->getExpirationMessageData(); + + $email->context($context); + + $this->mailer->send($email); + } + + /** + * @throws VerifyEmailExceptionInterface + */ + public function handleEmailConfirmation(Request $request, UserApp $user): void + { + $this->verifyEmailHelper->validateEmailConfirmationFromRequest($request, (string) $user->getId(), (string) $user->getMail()); + + $user->setVerified(true); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + } +} diff --git a/templates/registration/register.html.twig b/templates/registration/register.html.twig new file mode 100644 index 0000000..7b064ed --- /dev/null +++ b/templates/registration/register.html.twig @@ -0,0 +1,19 @@ +{% extends 'base.html.twig' %} + +{% block title %}Inscription{% endblock %} + +{% block body %} +

Inscription

+ + {{ form_errors(registrationForm) }} + + {{ form_start(registrationForm) }} + {{ form_row(registrationForm.nickname) }} + {{ form_row(registrationForm.plainPassword, { + label: 'Password' + }) }} + {{ form_row(registrationForm.agreeTerms) }} + + + {{ form_end(registrationForm) }} +{% endblock %} diff --git a/templates/security/login.html.twig b/templates/security/login.html.twig new file mode 100644 index 0000000..f711f6f --- /dev/null +++ b/templates/security/login.html.twig @@ -0,0 +1,41 @@ +{% extends 'base.html.twig' %} + +{% block title %}Connexion{% endblock %} + +{% block body %} +
+ {% if error %} +
{{ error.messageKey|trans(error.messageData, 'security') }}
+ {% endif %} + + {% if app.user %} +
+ You are logged in as {{ app.user.userIdentifier }}, Logout +
+ {% endif %} + +

Connexion à votre compte

+ + + + + + + + {# + 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 + +
+ + +
+ #} + + +
+{% endblock %}