Compare commits
No commits in common. "oscar" and "master" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,4 +23,3 @@
|
|||||||
/public/assets/
|
/public/assets/
|
||||||
/assets/vendor/
|
/assets/vendor/
|
||||||
###< symfony/asset-mapper ###
|
###< symfony/asset-mapper ###
|
||||||
.idea
|
|
@ -4,10 +4,10 @@ services:
|
|||||||
database:
|
database:
|
||||||
image: postgres:${POSTGRES_VERSION:-16}-alpine
|
image: postgres:${POSTGRES_VERSION:-16}-alpine
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-hegresphere}
|
POSTGRES_DB: ${POSTGRES_DB:-app}
|
||||||
# You should definitely change the password in production
|
# You should definitely change the password in production
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Btssio2024}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-bourgoino}
|
POSTGRES_USER: ${POSTGRES_USER:-app}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
|
test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
@ -23,4 +23,3 @@ volumes:
|
|||||||
###> doctrine/doctrine-bundle ###
|
###> doctrine/doctrine-bundle ###
|
||||||
database_data:
|
database_data:
|
||||||
###< doctrine/doctrine-bundle ###
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
"symfony/validator": "7.1.*",
|
"symfony/validator": "7.1.*",
|
||||||
"symfony/web-link": "7.1.*",
|
"symfony/web-link": "7.1.*",
|
||||||
"symfony/yaml": "7.1.*",
|
"symfony/yaml": "7.1.*",
|
||||||
"symfonycasts/sass-bundle": "^0.7.0",
|
|
||||||
"twig/extra-bundle": "^2.12|^3.0",
|
"twig/extra-bundle": "^2.12|^3.0",
|
||||||
"twig/twig": "^2.12|^3.0"
|
"twig/twig": "^2.12|^3.0"
|
||||||
},
|
},
|
||||||
|
57
composer.lock
generated
57
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "39f4377209acc13ab9e977a5301faef0",
|
"content-hash": "1bc99d81c026aaf4e662ffffde457d04",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
@ -7344,61 +7344,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-09-17T12:49:58+00:00"
|
"time": "2024-09-17T12:49:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "symfonycasts/sass-bundle",
|
|
||||||
"version": "v0.7.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/SymfonyCasts/sass-bundle.git",
|
|
||||||
"reference": "d88601c50eff716d9273dffbd736adefdc19e2fc"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/SymfonyCasts/sass-bundle/zipball/d88601c50eff716d9273dffbd736adefdc19e2fc",
|
|
||||||
"reference": "d88601c50eff716d9273dffbd736adefdc19e2fc",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=8.1",
|
|
||||||
"symfony/asset-mapper": "^6.3|^7.0",
|
|
||||||
"symfony/console": "^5.4|^6.3|^7.0",
|
|
||||||
"symfony/filesystem": "^5.4|^6.3|^7.0",
|
|
||||||
"symfony/http-client": "^5.4|^6.3|^7.0",
|
|
||||||
"symfony/process": "^5.4|^6.3|^7.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"matthiasnoback/symfony-config-test": "^5.0",
|
|
||||||
"phpstan/phpstan-symfony": "^1.4",
|
|
||||||
"symfony/framework-bundle": "^6.3|^7.0",
|
|
||||||
"symfony/phpunit-bridge": "^6.3|^7.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Symfonycasts\\SassBundle\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Mathéo Daninos",
|
|
||||||
"homepage": "https://github.com/WebMamba"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Delightful Sass Support for Symfony + AssetMapper",
|
|
||||||
"keywords": [
|
|
||||||
"asset-mapper",
|
|
||||||
"sass"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/SymfonyCasts/sass-bundle/issues",
|
|
||||||
"source": "https://github.com/SymfonyCasts/sass-bundle/tree/v0.7.0"
|
|
||||||
},
|
|
||||||
"time": "2024-05-22T14:59:07+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "twig/extra-bundle",
|
"name": "twig/extra-bundle",
|
||||||
"version": "v3.13.0",
|
"version": "v3.13.0",
|
||||||
|
@ -13,5 +13,4 @@ return [
|
|||||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
Symfonycasts\SassBundle\SymfonycastsSassBundle::class => ['all' => true],
|
|
||||||
];
|
];
|
||||||
|
@ -4,31 +4,14 @@ security:
|
|||||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||||
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
||||||
providers:
|
providers:
|
||||||
# used to reload user from session & other features (e.g. switch_user)
|
users_in_memory: { memory: null }
|
||||||
app_user_provider:
|
|
||||||
entity:
|
|
||||||
class: App\Entity\User
|
|
||||||
property: nickname
|
|
||||||
firewalls:
|
firewalls:
|
||||||
dev:
|
dev:
|
||||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||||
security: false
|
security: false
|
||||||
main:
|
main:
|
||||||
lazy: true
|
lazy: true
|
||||||
provider: app_user_provider
|
provider: users_in_memory
|
||||||
custom_authenticator: App\Security\UserAuthenticator
|
|
||||||
logout:
|
|
||||||
path: app_logout
|
|
||||||
# where to redirect after logout
|
|
||||||
# target: app_any_route
|
|
||||||
|
|
||||||
remember_me:
|
|
||||||
secret: '%kernel.secret%'
|
|
||||||
lifetime: 604800
|
|
||||||
path: /
|
|
||||||
# by default, the feature is enabled by checking a checkbox in the
|
|
||||||
# login form, uncomment the following line to always enable it.
|
|
||||||
#always_remember_me: true
|
|
||||||
|
|
||||||
# activate different ways to authenticate
|
# activate different ways to authenticate
|
||||||
# https://symfony.com/doc/current/security.html#the-firewall
|
# https://symfony.com/doc/current/security.html#the-firewall
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||||
parameters:
|
parameters:
|
||||||
app.jwtsecret : '%env(JWT_SECRET)%'
|
|
||||||
services:
|
services:
|
||||||
# default configuration for services in *this* file
|
# default configuration for services in *this* file
|
||||||
_defaults:
|
_defaults:
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
|
||||||
*/
|
|
||||||
final class Version20241017125351 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this up() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('DROP SEQUENCE user_id_seq CASCADE');
|
|
||||||
$this->addSql('CREATE SEQUENCE "userApp_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
|
|
||||||
$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, email VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_NICKNAME ON "userApp" (nickname)');
|
|
||||||
$this->addSql('ALTER TABLE employee DROP CONSTRAINT fk_5d9f75a1bf396750');
|
|
||||||
$this->addSql('ALTER TABLE intern DROP CONSTRAINT fk_a5795f36bf396750');
|
|
||||||
$this->addSql('DROP TABLE employee');
|
|
||||||
$this->addSql('DROP TABLE "user"');
|
|
||||||
$this->addSql('DROP TABLE intern');
|
|
||||||
}
|
|
||||||
|
|
||||||
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 "userApp_id_seq" CASCADE');
|
|
||||||
$this->addSql('CREATE SEQUENCE user_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
|
||||||
$this->addSql('CREATE TABLE employee (id INT NOT NULL, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('CREATE TABLE "user" (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 "user" (nickname)');
|
|
||||||
$this->addSql('CREATE TABLE intern (id INT NOT NULL, cover_letter TEXT NOT NULL, resume VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('ALTER TABLE employee ADD CONSTRAINT fk_5d9f75a1bf396750 FOREIGN KEY (id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
|
||||||
$this->addSql('ALTER TABLE intern ADD CONSTRAINT fk_a5795f36bf396750 FOREIGN KEY (id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
|
||||||
$this->addSql('DROP TABLE "userApp"');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controller;
|
|
||||||
|
|
||||||
use App\Entity\User;
|
|
||||||
use App\Form\RegistrationFormType;
|
|
||||||
use App\Security\UserAuthenticator;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
|
||||||
|
|
||||||
class RegistrationController extends AbstractController
|
|
||||||
{
|
|
||||||
#[Route('/register', name: 'app_register')]
|
|
||||||
public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, Security $security, EntityManagerInterface $entityManager): Response
|
|
||||||
{
|
|
||||||
$user = new User();
|
|
||||||
$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, UserAuthenticator::class, 'main');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->render('registration/register.html.twig', [
|
|
||||||
'registrationForm' => $form,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controller;
|
|
||||||
|
|
||||||
use App\Form\ResetPasswordRequestFormType;
|
|
||||||
use App\Repository\UserRepository;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|
||||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
|
||||||
|
|
||||||
class SecurityController extends AbstractController
|
|
||||||
{
|
|
||||||
#[Route(path: '/login', name: 'app_login')]
|
|
||||||
public function login(AuthenticationUtils $authenticationUtils): Response
|
|
||||||
{
|
|
||||||
// if ($this->getUser()) {
|
|
||||||
// return $this->redirectToRoute('target_path');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// get the login error if there is one
|
|
||||||
$error = $authenticationUtils->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.');
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/mot-de-passe-oublie', name: 'forgotten_password')]
|
|
||||||
public function forgottenPassword(
|
|
||||||
Request $request,
|
|
||||||
UserRepository $userRepository,
|
|
||||||
JWTService $jwt,
|
|
||||||
SendEmailService $mail
|
|
||||||
) : Response
|
|
||||||
{
|
|
||||||
$form = $this->createForm(ResetPasswordRequestFormType::class);
|
|
||||||
|
|
||||||
$form->handleRequest($request);
|
|
||||||
|
|
||||||
if($form->isSubmitted() && $form->isValid()) {
|
|
||||||
// Le formulaire est envoyé ET valide
|
|
||||||
// On va aller chercher l'utilisateur dans la base
|
|
||||||
$user = $userRepository->findOneByEmail($form->get('email')->getData());
|
|
||||||
|
|
||||||
// On verifie si on a un utilisateur
|
|
||||||
if($user) {
|
|
||||||
// On a un utilisateur
|
|
||||||
// On génère un JWT
|
|
||||||
// Générer le token
|
|
||||||
// Header
|
|
||||||
$header = [
|
|
||||||
'typ' => 'JWT',
|
|
||||||
'alg' => 'HS256'
|
|
||||||
];
|
|
||||||
|
|
||||||
//Payload
|
|
||||||
$payload = [
|
|
||||||
'user_id' => $user->getId()
|
|
||||||
];
|
|
||||||
|
|
||||||
//On Génère le token
|
|
||||||
$token = $jwt->generate($header, $payload, $this->getParameter('app.jwtsecret'));
|
|
||||||
|
|
||||||
// On génère l'URL vers reset_password
|
|
||||||
$url = $this->generateUrl('reset_password', ['token' => $token],
|
|
||||||
UrlGeneratorInterface::ABSOLUTE_URL);
|
|
||||||
|
|
||||||
// Envoyer l'e-mail
|
|
||||||
$mail->send(
|
|
||||||
'no-reply@openblog.test',
|
|
||||||
$user->getEmail(),
|
|
||||||
'Récupération de votre mode de passe sur le site OpenBlog',
|
|
||||||
'password_reset',
|
|
||||||
compact('user','url') // ['user' => $user, 'url'=>$url]
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addFlash('success', 'Email envoyé avec succès');
|
|
||||||
return $this->redirectToRoute('app_login');
|
|
||||||
|
|
||||||
}
|
|
||||||
// $user est null
|
|
||||||
$this->addFlash('danger', 'Un problème est survenu');
|
|
||||||
return $this->redirectToRoute('app_login');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return $this->render('security/reset_password_request.html.twig', ['requestPassForm' => $form->createView()]);
|
|
||||||
}
|
|
||||||
//#[Route('/mot-de-passe-oublie/{token}', name: 'reset_password')]
|
|
||||||
//public function resetPassword(): Response{
|
|
||||||
|
|
||||||
//};
|
|
||||||
}
|
|
@ -1,186 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
|
||||||
#[ORM\Table(name: 'userApp')]
|
|
||||||
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_NICKNAME', fields: ['nickname'])]
|
|
||||||
#[UniqueEntity(fields: ['nickname'], message: 'Il y a déjà un utilisateur à ce nom')]
|
|
||||||
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|
||||||
{
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\GeneratedValue]
|
|
||||||
#[ORM\Column]
|
|
||||||
private ?int $id = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 180)]
|
|
||||||
private ?string $nickname = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var list<string> The user roles
|
|
||||||
*/
|
|
||||||
#[ORM\Column]
|
|
||||||
private array $roles = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string The hashed password
|
|
||||||
*/
|
|
||||||
#[ORM\Column]
|
|
||||||
private ?string $password = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
|
||||||
private ?string $firstName = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
|
||||||
private ?string $lastName = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
|
||||||
private ?string $tel = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
|
||||||
private ?string $address = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
|
||||||
private ?string $email = null;
|
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getNickname(): ?string
|
|
||||||
{
|
|
||||||
return $this->nickname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setNickname(string $nickname): static
|
|
||||||
{
|
|
||||||
$this->nickname = $nickname;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A visual identifier that represents this user.
|
|
||||||
*
|
|
||||||
* @see UserInterface
|
|
||||||
*/
|
|
||||||
public function getUserIdentifier(): string
|
|
||||||
{
|
|
||||||
return (string) $this->nickname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see UserInterface
|
|
||||||
*
|
|
||||||
* @return list<string>
|
|
||||||
*/
|
|
||||||
public function getRoles(): array
|
|
||||||
{
|
|
||||||
$roles = $this->roles;
|
|
||||||
// guarantee every user at least has ROLE_USER
|
|
||||||
$roles[] = 'ROLE_USER';
|
|
||||||
|
|
||||||
return array_unique($roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param list<string> $roles
|
|
||||||
*/
|
|
||||||
public function setRoles(array $roles): static
|
|
||||||
{
|
|
||||||
$this->roles = $roles;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see PasswordAuthenticatedUserInterface
|
|
||||||
*/
|
|
||||||
public function getPassword(): ?string
|
|
||||||
{
|
|
||||||
return $this->password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPassword(string $password): static
|
|
||||||
{
|
|
||||||
$this->password = $password;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see UserInterface
|
|
||||||
*/
|
|
||||||
public function eraseCredentials(): void
|
|
||||||
{
|
|
||||||
// If you store any temporary, sensitive data on the user, clear it here
|
|
||||||
// $this->plainPassword = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFirstName(): ?string
|
|
||||||
{
|
|
||||||
return $this->firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setFirstName(string $firstName): static
|
|
||||||
{
|
|
||||||
$this->firstName = $firstName;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLastName(): ?string
|
|
||||||
{
|
|
||||||
return $this->lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setLastName(string $lastName): static
|
|
||||||
{
|
|
||||||
$this->lastName = $lastName;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTel(): ?string
|
|
||||||
{
|
|
||||||
return $this->tel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTel(string $tel): static
|
|
||||||
{
|
|
||||||
$this->tel = $tel;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAddress(): ?string
|
|
||||||
{
|
|
||||||
return $this->address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setAddress(string $address): static
|
|
||||||
{
|
|
||||||
$this->address = $address;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEmail(): ?string
|
|
||||||
{
|
|
||||||
return $this->email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setEmail(string $email): static
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Form;
|
|
||||||
|
|
||||||
use App\Entity\User;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
use Symfony\Component\Validator\Constraints\IsTrue;
|
|
||||||
use Symfony\Component\Validator\Constraints\Length;
|
|
||||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
|
||||||
|
|
||||||
class RegistrationFormType extends AbstractType
|
|
||||||
{
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
|
||||||
{
|
|
||||||
$builder
|
|
||||||
->add('nickname')
|
|
||||||
->add('email')
|
|
||||||
->add('agreeTerms', CheckboxType::class, [
|
|
||||||
'mapped' => false,
|
|
||||||
'constraints' => [
|
|
||||||
new IsTrue([
|
|
||||||
'message' => 'You should agree to our terms.',
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
])
|
|
||||||
->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' => 'Please enter a password',
|
|
||||||
]),
|
|
||||||
new Length([
|
|
||||||
'min' => 8,
|
|
||||||
'minMessage' => 'Your password should be at least {{ limit }} characters',
|
|
||||||
// max length allowed by Symfony for security reasons
|
|
||||||
'max' => 4096,
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
])
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver): void
|
|
||||||
{
|
|
||||||
$resolver->setDefaults([
|
|
||||||
'data_class' => User::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Form;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
|
|
||||||
class ResetPasswordRequestFormType extends AbstractType
|
|
||||||
{
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
|
||||||
{
|
|
||||||
$builder
|
|
||||||
->add('email', EmailType::class)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver): void
|
|
||||||
{
|
|
||||||
$resolver->setDefaults([
|
|
||||||
// Configure your form options here
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repository;
|
|
||||||
|
|
||||||
use App\Entity\User;
|
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
|
||||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
|
||||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
|
||||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @extends ServiceEntityRepository<User>
|
|
||||||
*/
|
|
||||||
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
|
|
||||||
{
|
|
||||||
public function __construct(ManagerRegistry $registry)
|
|
||||||
{
|
|
||||||
parent::__construct($registry, User::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to upgrade (rehash) the user's password automatically over time.
|
|
||||||
*/
|
|
||||||
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
|
|
||||||
{
|
|
||||||
if (!$user instanceof User) {
|
|
||||||
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
|
|
||||||
}
|
|
||||||
|
|
||||||
$user->setPassword($newHashedPassword);
|
|
||||||
$this->getEntityManager()->persist($user);
|
|
||||||
$this->getEntityManager()->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * @return User[] Returns an array of User objects
|
|
||||||
// */
|
|
||||||
// public function findByExampleField($value): array
|
|
||||||
// {
|
|
||||||
// return $this->createQueryBuilder('u')
|
|
||||||
// ->andWhere('u.exampleField = :val')
|
|
||||||
// ->setParameter('val', $value)
|
|
||||||
// ->orderBy('u.id', 'ASC')
|
|
||||||
// ->setMaxResults(10)
|
|
||||||
// ->getQuery()
|
|
||||||
// ->getResult()
|
|
||||||
// ;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public function findOneBySomeField($value): ?User
|
|
||||||
// {
|
|
||||||
// return $this->createQueryBuilder('u')
|
|
||||||
// ->andWhere('u.exampleField = :val')
|
|
||||||
// ->setParameter('val', $value)
|
|
||||||
// ->getQuery()
|
|
||||||
// ->getOneOrNullResult()
|
|
||||||
// ;
|
|
||||||
// }
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Security;
|
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
|
||||||
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;
|
|
||||||
use Symfony\Component\Security\Http\SecurityRequestAttributes;
|
|
||||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
|
||||||
|
|
||||||
class UserAuthenticator extends AbstractLoginFormAuthenticator
|
|
||||||
{
|
|
||||||
use TargetPathTrait;
|
|
||||||
|
|
||||||
public const LOGIN_ROUTE = 'app_login';
|
|
||||||
|
|
||||||
public function __construct(private UrlGeneratorInterface $urlGenerator)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function authenticate(Request $request): Passport
|
|
||||||
{
|
|
||||||
$nickname = $request->getPayload()->getString('nickname');
|
|
||||||
|
|
||||||
$request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $nickname);
|
|
||||||
|
|
||||||
return new Passport(
|
|
||||||
new UserBadge($nickname),
|
|
||||||
new PasswordCredentials($request->getPayload()->getString('password')),
|
|
||||||
[
|
|
||||||
new CsrfTokenBadge('authenticate', $request->getPayload()->getString('_csrf_token')),
|
|
||||||
new RememberMeBadge(),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
|
||||||
{
|
|
||||||
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
|
|
||||||
return new RedirectResponse($targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For example:
|
|
||||||
return new RedirectResponse($this->urlGenerator->generate('index'));
|
|
||||||
//throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getLoginUrl(Request $request): string
|
|
||||||
{
|
|
||||||
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
|
|
||||||
}
|
|
||||||
}
|
|
@ -288,9 +288,6 @@
|
|||||||
"config/packages/messenger.yaml"
|
"config/packages/messenger.yaml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"symfonycasts/sass-bundle": {
|
|
||||||
"version": "v0.7.0"
|
|
||||||
},
|
|
||||||
"twig/extra-bundle": {
|
"twig/extra-bundle": {
|
||||||
"version": "v3.13.0"
|
"version": "v3.13.0"
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}M'inscrire{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>M'inscrire</h1>
|
|
||||||
|
|
||||||
{{ form_errors(registrationForm) }}
|
|
||||||
|
|
||||||
{{ form_start(registrationForm) }}
|
|
||||||
<div>
|
|
||||||
{{ form_row(registrationForm.nickname) }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ form_row(registrationForm.plainPassword, {
|
|
||||||
label: 'Password'
|
|
||||||
}) }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ form_row(registrationForm.email) }}
|
|
||||||
{{ form_row(registrationForm.agreeTerms) }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn">M'inscrire</button>
|
|
||||||
{{ form_end(registrationForm) }}
|
|
||||||
<p>Déjà inscrit(e) ? <a href="{{ path('app_login') }}">Me connecter</a></p>
|
|
||||||
{% endblock %}
|
|
@ -1,42 +0,0 @@
|
|||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}Me connecter{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<form method="post">
|
|
||||||
{% if error %}
|
|
||||||
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if app.user %}
|
|
||||||
<div class="mb-3">
|
|
||||||
Vous êtes déjà connecté(e) en tant que {{ app.user.userIdentifier }}, <a href="{{ path('app_logout') }}">Se déconnecter</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<h1 class="h3 mb-3 font-weight-normal">Me connecter</h1>
|
|
||||||
<div>
|
|
||||||
<label for="inputNickname">Nickname</label>
|
|
||||||
<input type="text" value="{{ last_username }}" name="nickname" id="inputNickname" class="form-control" autocomplete="username" required autofocus>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="inputPassword">Mot de passe</label>
|
|
||||||
<input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required>
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="_csrf_token"
|
|
||||||
value="{{ csrf_token('authenticate') }}"
|
|
||||||
>
|
|
||||||
|
|
||||||
<div class="checkbox mb-3">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" name="_remember_me"> Remember me
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button class="btn btn-lg btn-primary" type="submit">
|
|
||||||
Me connecter
|
|
||||||
</button>
|
|
||||||
<p><a href="{{ path('forgotten_password') }}">Mot de passe oublié</a></p>
|
|
||||||
<p>Pas encore inscrit(e) ? <a href="{{path('app_register')}}">M'inscrire</a></p>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
@ -1,14 +0,0 @@
|
|||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}Demande de réinitialisation de mot de passe{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<section>
|
|
||||||
<h1>Demande de réinitialisation de mot de passe</h1>
|
|
||||||
{{ form_start(requestPassForm) }}
|
|
||||||
{{ form_row(requestPassForm.email) }}
|
|
||||||
<button type="submit">Envoyer</button>
|
|
||||||
|
|
||||||
{{ form_end(requestPassForm) }}
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
Loading…
Reference in New Issue
Block a user