End update for 21/11/23

This commit is contained in:
ExostFlash 2023-11-21 22:02:38 +01:00
parent 15361f28cd
commit bcaad13d6f
32 changed files with 849 additions and 201 deletions

View file

@ -12,6 +12,7 @@
"doctrine/orm": "^2.17",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.24",
"sensio/framework-extra-bundle": "^6.2",
"symfony/asset": "6.1.*",
"symfony/console": "6.1.*",
"symfony/doctrine-messenger": "6.1.*",

156
composer.lock generated
View file

@ -4,8 +4,84 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "989072ca54ad28f1eb15250b46306f66",
"content-hash": "20a9cc49a87829044729ea14036c4de9",
"packages": [
{
"name": "doctrine/annotations",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"shasum": ""
},
"require": {
"doctrine/lexer": "^2 || ^3",
"ext-tokenizer": "*",
"php": "^7.2 || ^8.0",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/cache": "^2.0",
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"symfony/cache": "^5.4 || ^6",
"vimeo/psalm": "^4.10"
},
"suggest": {
"php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Docblock Annotations Parser",
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
"keywords": [
"annotations",
"docblock",
"parser"
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
"source": "https://github.com/doctrine/annotations/tree/2.0.1"
},
"time": "2023-02-02T22:02:53+00:00"
},
{
"name": "doctrine/cache",
"version": "2.2.0",
@ -1967,6 +2043,84 @@
},
"time": "2021-07-14T16:46:02+00:00"
},
{
"name": "sensio/framework-extra-bundle",
"version": "v6.2.10",
"source": {
"type": "git",
"url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git",
"reference": "2f886f4b31f23c76496901acaedfedb6936ba61f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/2f886f4b31f23c76496901acaedfedb6936ba61f",
"reference": "2f886f4b31f23c76496901acaedfedb6936ba61f",
"shasum": ""
},
"require": {
"doctrine/annotations": "^1.0|^2.0",
"php": ">=7.2.5",
"symfony/config": "^4.4|^5.0|^6.0",
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/framework-bundle": "^4.4|^5.0|^6.0",
"symfony/http-kernel": "^4.4|^5.0|^6.0"
},
"conflict": {
"doctrine/doctrine-cache-bundle": "<1.3.1",
"doctrine/persistence": "<1.3"
},
"require-dev": {
"doctrine/dbal": "^2.10|^3.0",
"doctrine/doctrine-bundle": "^1.11|^2.0",
"doctrine/orm": "^2.5",
"symfony/browser-kit": "^4.4|^5.0|^6.0",
"symfony/doctrine-bridge": "^4.4|^5.0|^6.0",
"symfony/dom-crawler": "^4.4|^5.0|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0",
"symfony/finder": "^4.4|^5.0|^6.0",
"symfony/monolog-bridge": "^4.0|^5.0|^6.0",
"symfony/monolog-bundle": "^3.2",
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0",
"symfony/security-bundle": "^4.4|^5.0|^6.0",
"symfony/twig-bundle": "^4.4|^5.0|^6.0",
"symfony/yaml": "^4.4|^5.0|^6.0",
"twig/twig": "^1.34|^2.4|^3.0"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "6.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Sensio\\Bundle\\FrameworkExtraBundle\\": "src/"
},
"exclude-from-classmap": [
"/tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "This bundle provides a way to configure your controllers with annotations",
"keywords": [
"annotations",
"controllers"
],
"support": {
"source": "https://github.com/sensiolabs/SensioFrameworkExtraBundle/tree/v6.2.10"
},
"abandoned": "Symfony",
"time": "2023-02-24T14:57:12+00:00"
},
{
"name": "symfony/asset",
"version": "v6.1.11",

View file

@ -12,4 +12,5 @@ return [
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
];

View file

@ -4,14 +4,23 @@ security:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: "auto"
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
users_in_memory: { memory: null }
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: users_in_memory
provider: app_user_provider
form_login:
login_path: app_user_login
check_path: app_user_login
logout:
path: app_user_logout
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall

View file

@ -0,0 +1,3 @@
sensio_framework_extra:
router:
annotations: false

View file

@ -1,33 +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 Version20231121091411 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('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(100) NOT NULL, fullname VARCHAR(100) NOT NULL, grade VARCHAR(50) DEFAULT NULL, mail VARCHAR(255) NOT NULL, mdp VARCHAR(255) NOT NULL, address VARCHAR(255) DEFAULT NULL, id_resto INT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE messenger_messages (id BIGINT AUTO_INCREMENT NOT NULL, body LONGTEXT NOT NULL, headers LONGTEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at DATETIME NOT NULL, available_at DATETIME NOT NULL, delivered_at DATETIME DEFAULT NULL, INDEX IDX_75EA56E0FB7336F0 (queue_name), INDEX IDX_75EA56E0E3BD61CE (available_at), INDEX IDX_75EA56E016BA31DB (delivered_at), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE user');
$this->addSql('DROP TABLE messenger_messages');
}
}

View file

@ -1,33 +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 Version20231121092109 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('CREATE TABLE resto (id INT AUTO_INCREMENT NOT NULL, pay VARCHAR(255) NOT NULL, ville VARCHAR(255) NOT NULL, address VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE user CHANGE grade grade VARCHAR(50) DEFAULT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE resto');
$this->addSql('ALTER TABLE user CHANGE grade grade VARCHAR(50) DEFAULT \'Client\'');
}
}

View file

@ -1,31 +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 Version20231121092649 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('CREATE TABLE ticket (id INT AUTO_INCREMENT NOT NULL, id_resto INT NOT NULL, id_users INT NOT NULL, payement VARCHAR(50) NOT NULL, id_menu INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE ticket');
}
}

View file

@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20231121092325 extends AbstractMigration
final class Version20231121152707 extends AbstractMigration
{
public function getDescription(): string
{
@ -20,12 +20,12 @@ final class Version20231121092325 extends AbstractMigration
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE menu (id INT AUTO_INCREMENT NOT NULL, entre VARCHAR(255) DEFAULT NULL, plat VARCHAR(255) DEFAULT NULL, dessert VARCHAR(255) DEFAULT NULL, id_resto INT NOT NULL, id_users INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, name VARCHAR(200) NOT NULL, fullname VARCHAR(200) NOT NULL, address VARCHAR(255) DEFAULT NULL, id_resto INT DEFAULT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE menu');
$this->addSql('DROP TABLE user');
}
}

View file

@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20231121093127 extends AbstractMigration
final class Version20231121194307 extends AbstractMigration
{
public function getDescription(): string
{
@ -20,12 +20,12 @@ final class Version20231121093127 extends AbstractMigration
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE avis (id INT AUTO_INCREMENT NOT NULL, note INT DEFAULT NULL, com VARCHAR(255) NOT NULL, id_ticket INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE user ADD grade VARCHAR(50) DEFAULT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE avis');
$this->addSql('ALTER TABLE user DROP grade');
}
}

View file

@ -1,4 +1,4 @@
body {
body .center {
margin: 1em auto;
max-width: 800px;
width: 95%;

View file

@ -0,0 +1,26 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class SecurityController extends AbstractController
{
#[Route('/user/login', name: 'app_user_login', methods: ['GET', 'POST'])]
public function login(): Response
{
return $this->render('user/login.html.twig', [
'controller_name' => 'SecurityController',
]);
}
#[Route('/user/logout', name: 'app_user_logout')]
public function logout(): Response
{
return $this->render('user/login.html.twig', [
'controller_name' => 'SecurityController',
]);
}
}

View file

@ -0,0 +1,102 @@
<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\UserType;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
#[Route('/admin/user')]
class UserAdminController extends AbstractController
{
private UserPasswordHasherInterface $hasher;
public function __construct(UserPasswordHasherInterface $hasher)
{
$this->hasher = $hasher;
}
#[Route('/', name: 'app_user_admin_index', methods: ['GET'])]
public function index(UserRepository $userRepository): Response
{
return $this->render('user_admin/index.html.twig', [
'users' => $userRepository->findAll(),
]);
}
#[Route('/new', name: 'app_user_admin_new', methods: ['GET', 'POST'])]
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('app_user_admin_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('user_admin/new.html.twig', [
'user' => $user,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_user_admin_show', methods: ['GET'])]
public function show(User $user): Response
{
return $this->render('user_admin/show.html.twig', [
'user' => $user,
]);
}
#[Route('/{id}/edit', name: 'app_user_admin_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, User $user, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$plainPassword = $form->get('password')->getData();
// Encodage sécurisé du mot de passe
$hashedPassword = $this->hasher->hashPassword(
$user,
$plainPassword
);
// Définition du mot de passe haché sur l'entité User
$user->setPassword($hashedPassword);
// Enregistrement de l'utilisateur
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('app_user_admin_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('user_admin/edit.html.twig', [
'user' => $user,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_user_admin_delete', methods: ['POST'])]
public function delete(Request $request, User $user, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('delete' . $user->getId(), $request->request->get('_token'))) {
$entityManager->remove($user);
$entityManager->flush();
}
return $this->redirectToRoute('app_user_admin_index', [], Response::HTTP_SEE_OTHER);
}
}

View file

@ -10,10 +10,18 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
class UserController extends AbstractController
{
private UserPasswordHasherInterface $hasher;
public function __construct(UserPasswordHasherInterface $hasher)
{
$this->hasher = $hasher;
}
#[Route('/user', name: 'app_user')]
public function index(): Response
{
@ -31,13 +39,16 @@ class UserController extends AbstractController
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// Récupération du mot de passe en clair depuis le formulaire
$plainPassword = $form->get('mdp')->getData();
$plainPassword = $form->get('password')->getData();
// Encodage sécurisé du mot de passe
$hashedPassword = password_hash($plainPassword, PASSWORD_DEFAULT);
$hashedPassword = $this->hasher->hashPassword(
$user_entity,
$plainPassword
);
// Définition du mot de passe haché sur l'entité User
$user_entity->setMdp($hashedPassword);
$user_entity->setPassword($hashedPassword);
// Enregistrement de l'utilisateur
$entityManager->persist($user_entity);
@ -51,12 +62,4 @@ class UserController extends AbstractController
'form' => $form->createView(),
]);
}
#[Route('/user/login', name: 'app_user_login')]
public function login(): Response
{
return $this->render('user/login.html.twig', [
'controller_name' => 'UserController',
]);
}
}

View file

@ -4,41 +4,129 @@ namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
#[UniqueEntity('email')]
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 100)]
#[ORM\Column(length: 180, unique: true)]
private ?string $email = null;
#[ORM\Column]
private array $roles = [];
private ?string $plainPassword = null;
/**
* @var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
#[ORM\Column(length: 200)]
private ?string $name = null;
#[ORM\Column(length: 100)]
#[ORM\Column(length: 200)]
private ?string $fullname = null;
#[ORM\Column(length: 50, nullable: true)]
private ?string $grade = null;
#[ORM\Column(length: 255)]
private ?string $mail = null;
#[ORM\Column(length: 255)]
private ?string $mdp = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $address = null;
#[ORM\Column(nullable: true)]
private ?int $id_resto = null;
#[ORM\Column(length: 50, nullable: true)]
private ?string $grade = "client";
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): static
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
return array_unique($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;
}
public function setPlainPassword(string $password): static
{
$this->plainPassword = $password;
return $this;
}
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
/**
* @see UserInterface
*/
public function eraseCredentials(): void
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getName(): ?string
{
return $this->name;
@ -63,42 +151,6 @@ class User
return $this;
}
public function getGrade(): ?string
{
return $this->grade;
}
public function setGrade(?string $grade): static
{
$this->grade = $grade;
return $this;
}
public function getMail(): ?string
{
return $this->mail;
}
public function setMail(string $mail): static
{
$this->mail = $mail;
return $this;
}
public function getMdp(): ?string
{
return $this->mdp;
}
public function setMdp(string $mdp): static
{
$this->mdp = $mdp;
return $this;
}
public function getAddress(): ?string
{
return $this->address;
@ -122,4 +174,16 @@ class User
return $this;
}
public function getGrade(): ?string
{
return $this->grade;
}
public function setGrade(?string $grade): static
{
$this->grade = $grade;
return $this;
}
}

View file

@ -1,26 +0,0 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
class UserLoginType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('mail')
->add('mdp', PasswordType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}

View file

@ -3,6 +3,7 @@
namespace App\Form;
use App\Entity\User;
use PharIo\Manifest\Email;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@ -19,10 +20,10 @@ class UserSignupType extends AbstractType
->add('fullname', null, [
'attr' => ['placeholder' => 'Entrez votre prénom']
])
->add('mail', null, [
->add('email', null, [
'attr' => ['placeholder' => 'exemple@exostflash.ovh']
])
->add('mdp', PasswordType::class, [
->add('password', PasswordType::class, [
'attr' => ['placeholder' => 'Entrez votre mot de passe']
])
->add('address', null, [

47
src/Form/UserType.php Normal file
View file

@ -0,0 +1,47 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', null, [
'attr' => ['placeholder' => 'Nom de famille']
])
->add('fullname', null, [
'attr' => ['placeholder' => 'Prénom']
])
->add('email', null, [
'attr' => ['placeholder' => 'exemple@exostflash.ovh']
])
->add('password', PasswordType::class, [
'attr' => ['placeholder' => 'Entrez votre mot de passe']
])
->add(
'address',
null,
[
'attr' => ['placeholder' => '265 chemin de l\'exemple, 31840 Exemple']
]
)
->add('grade', null, [
'attr' => ['placeholder' => 'Client/Waiter/Chef/Root']
])
->add('id_resto');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}

View file

@ -5,22 +5,41 @@ 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>
*
* @implements PasswordUpgraderInterface<User>
*
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository
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
// */

View file

@ -1,4 +1,13 @@
{
"doctrine/annotations": {
"version": "2.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.10",
"ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05"
}
},
"doctrine/doctrine-bundle": {
"version": "2.11",
"recipe": {
@ -40,6 +49,18 @@
"tests/bootstrap.php"
]
},
"sensio/framework-extra-bundle": {
"version": "6.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.2",
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
},
"files": [
"config/packages/sensio_framework_extra.yaml"
]
},
"symfony/console": {
"version": "6.1",
"recipe": {

View file

@ -4,10 +4,15 @@
{% block body %}
<div>
<h1>Bienvenue à McDoPlus !</h1>
<div class="center">
<h1>Bienvenue chez McDoPlus !</h1>
{% if not app.user %}
compte utilisateur c'est <code><a href="/user">ici</a></code>
{% endif %}
{% if app.user and ('waiter' in app.user.roles or 'chef' in app.user.roles) %}
User roles: {{ app.user.roles|join(', ') }}
{% endif %}
<article>
<h3>test</h3>

View file

@ -0,0 +1,20 @@
{% extends 'base.html.twig' %}
{% block title %}Hello SecurityController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code><a href="{{ '/home/exostflash/McDoPlus/src/Controller/SecurityController.php'|file_link(0) }}">src/Controller/SecurityController.php</a></code></li>
<li>Your template at <code><a href="{{ '/home/exostflash/McDoPlus/templates/security/index.html.twig'|file_link(0) }}">templates/security/index.html.twig</a></code></li>
</ul>
</div>
{% endblock %}

View file

@ -4,7 +4,7 @@
{% block body %}
<div>
<div class="center">
<h1>Compte utilisateur !</h1>
<ul>

View file

@ -4,8 +4,20 @@
{% block body %}
<div>
<div class="center">
<h1>Login !</h1>
<article>
<form action=" {{ path('app_user_login') }}" method="post">
<div class="form-group">
<label for="username" class="form-label mt-4">Adresse email</label>
<input type="email" class="form-controle" id="username" name="_username" placeholder="exemple@exostflash.ovh">
</div>
<div class="form-group">
<label for="password" class="form-label mt-4">Mot de passe</label>
<input type="password" class="form-controle" id="password" name="_password" placeholder="********">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</article>
</div>
{% endblock %}

View file

@ -4,7 +4,7 @@
{% block body %}
<div>
<div class="center">
<h1>Signup !</h1>
<article>

View file

@ -0,0 +1,4 @@
<form method="post" action="{{ path('app_user_admin_delete', {'id': user.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ user.id) }}">
<button class="btn">Delete</button>
</form>

View file

@ -0,0 +1,4 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

View file

@ -0,0 +1,15 @@
{% extends 'base.html.twig' %}
{% block title %}Edit User{% endblock %}
{% block body %}
<div class="center">
<h1>Edit User</h1>
<article>
{{ include('user_admin/_form.html.twig', {'button_label': 'Update'}) }}
{{ include('user_admin/_delete_form.html.twig') }}
<a href="{{ path('app_user_admin_index') }}">back to list</a>
</article>
</div>
{% endblock %}

View file

@ -0,0 +1,47 @@
{% extends 'base.html.twig' %}
{% block title %}User index{% endblock %}
{% block body %}
<h1>User index</h1>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Fullname</th>
<th>Email</th>
<th>Password</th>
<th>Address</th>
<th>Grade</th>
<th>Id_resto</th>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.fullname }}</td>
<td>{{ user.email }}</td>
<td>{{ user.password }}</td>
<td>{{ user.address }}</td>
<td>{{ user.grade }}</td>
<td>{{ user.idResto }}</td>
<td>
<a href="{{ path('app_user_admin_show', {'id': user.id}) }}">show</a>
<a href="{{ path('app_user_admin_edit', {'id': user.id}) }}">edit</a>
</td>
</tr>
{% else %}
<tr>
<td colspan="9">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{{ path('app_user_admin_new') }}">Create new</a>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends 'base.html.twig' %}
{% block title %}New User{% endblock %}
{% block body %}
<h1>Create new User</h1>
{{ include('user_admin/_form.html.twig') }}
<a href="{{ path('app_user_admin_index') }}">back to list</a>
{% endblock %}

View file

@ -0,0 +1,50 @@
{% extends 'base.html.twig' %}
{% block title %}User{% endblock %}
{% block body %}
<h1>User</h1>
<table class="table">
<tbody>
<tr>
<th>Id</th>
<td>{{ user.id }}</td>
</tr>
<tr>
<th>Email</th>
<td>{{ user.email }}</td>
</tr>
<tr>
<th>Roles</th>
<td>{{ user.roles ? user.roles|json_encode : '' }}</td>
</tr>
<tr>
<th>Password</th>
<td>{{ user.password }}</td>
</tr>
<tr>
<th>Name</th>
<td>{{ user.name }}</td>
</tr>
<tr>
<th>Fullname</th>
<td>{{ user.fullname }}</td>
</tr>
<tr>
<th>Address</th>
<td>{{ user.address }}</td>
</tr>
<tr>
<th>Id_resto</th>
<td>{{ user.idResto }}</td>
</tr>
</tbody>
</table>
<a href="{{ path('app_user_admin_index') }}">back to list</a>
<a href="{{ path('app_user_admin_edit', {'id': user.id}) }}">edit</a>
{{ include('user_admin/_delete_form.html.twig') }}
{% endblock %}

View file

@ -0,0 +1,152 @@
<?php
namespace App\Test\Controller;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class UserControllerTest extends WebTestCase
{
private KernelBrowser $client;
private UserRepository $repository;
private string $path = '/user/admin/';
private EntityManagerInterface $manager;
protected function setUp(): void
{
$this->client = static::createClient();
$this->repository = static::getContainer()->get('doctrine')->getRepository(User::class);
foreach ($this->repository->findAll() as $object) {
$this->manager->remove($object);
}
}
public function testIndex(): void
{
$crawler = $this->client->request('GET', $this->path);
self::assertResponseStatusCodeSame(200);
self::assertPageTitleContains('User index');
// Use the $crawler to perform additional assertions e.g.
// self::assertSame('Some text on the page', $crawler->filter('.p')->first());
}
public function testNew(): void
{
$originalNumObjectsInRepository = count($this->repository->findAll());
$this->markTestIncomplete();
$this->client->request('GET', sprintf('%snew', $this->path));
self::assertResponseStatusCodeSame(200);
$this->client->submitForm('Save', [
'user[email]' => 'Testing',
'user[roles]' => 'Testing',
'user[password]' => 'Testing',
'user[name]' => 'Testing',
'user[fullname]' => 'Testing',
'user[address]' => 'Testing',
'user[id_resto]' => 'Testing',
]);
self::assertResponseRedirects('/user/admin/');
self::assertSame($originalNumObjectsInRepository + 1, count($this->repository->findAll()));
}
public function testShow(): void
{
$this->markTestIncomplete();
$fixture = new User();
$fixture->setEmail('My Title');
$fixture->setRoles('My Title');
$fixture->setPassword('My Title');
$fixture->setName('My Title');
$fixture->setFullname('My Title');
$fixture->setAddress('My Title');
$fixture->setId_resto('My Title');
$this->manager->persist($fixture);
$this->manager->flush();
$this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
self::assertResponseStatusCodeSame(200);
self::assertPageTitleContains('User');
// Use assertions to check that the properties are properly displayed.
}
public function testEdit(): void
{
$this->markTestIncomplete();
$fixture = new User();
$fixture->setEmail('My Title');
$fixture->setRoles('My Title');
$fixture->setPassword('My Title');
$fixture->setName('My Title');
$fixture->setFullname('My Title');
$fixture->setAddress('My Title');
$fixture->setId_resto('My Title');
$this->manager->persist($fixture);
$this->manager->flush();
$this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
$this->client->submitForm('Update', [
'user[email]' => 'Something New',
'user[roles]' => 'Something New',
'user[password]' => 'Something New',
'user[name]' => 'Something New',
'user[fullname]' => 'Something New',
'user[address]' => 'Something New',
'user[id_resto]' => 'Something New',
]);
self::assertResponseRedirects('/user/admin/');
$fixture = $this->repository->findAll();
self::assertSame('Something New', $fixture[0]->getEmail());
self::assertSame('Something New', $fixture[0]->getRoles());
self::assertSame('Something New', $fixture[0]->getPassword());
self::assertSame('Something New', $fixture[0]->getName());
self::assertSame('Something New', $fixture[0]->getFullname());
self::assertSame('Something New', $fixture[0]->getAddress());
self::assertSame('Something New', $fixture[0]->getId_resto());
}
public function testRemove(): void
{
$this->markTestIncomplete();
$originalNumObjectsInRepository = count($this->repository->findAll());
$fixture = new User();
$fixture->setEmail('My Title');
$fixture->setRoles('My Title');
$fixture->setPassword('My Title');
$fixture->setName('My Title');
$fixture->setFullname('My Title');
$fixture->setAddress('My Title');
$fixture->setId_resto('My Title');
$this->manager->persist($fixture);
$this->manager->flush();
self::assertSame($originalNumObjectsInRepository + 1, count($this->repository->findAll()));
$this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
$this->client->submitForm('Delete');
self::assertSame($originalNumObjectsInRepository, count($this->repository->findAll()));
self::assertResponseRedirects('/user/admin/');
}
}