This commit is contained in:
Rudy Masson 2022-10-16 10:36:53 +02:00
parent 85125c7d6b
commit 0f3447adf5
27 changed files with 1183 additions and 75 deletions

View File

@ -4,10 +4,20 @@ export default class GetEvent{
}
static getEvent(){
console.log("test init");
let saisie = $('#saisie');
saisie.focus();
let value;
let $infoDon = $('#info-don');
let $infoDonneur = $('#info-donneur');
let $infoPsl = $('#info-psl');
let $don = $('#don');
let $nom = $('#nom');
let $prenom = $('#prenom');
let $naissance = $('#naissance');
let $typeDon = $('#typeDon');
let $typePoche = $('#typePoche');
let $nbreTube = $('#nbreTube');
let $displayError = $('#error');
document.addEventListener('keydown', function (event) {
saisie.focus();
if(event.code == 'Tab'){
@ -19,7 +29,106 @@ export default class GetEvent{
dataType: "json",
data: {'codeBarre': value},
success: function(response){
console.log(response)
console.log(response.data)
switch(response.data.step){
case '0':
if(response.data.status == 'success'){
$don.html(response.data.codeBarre);
$nom.html(response.data.nom);
$prenom.html(response.data.prenom);
$naissance.html(new Date(response.data.birthdate).toLocaleDateString());
$typeDon.html(response.data.type_don);
$nbreTube.html(response.data.nbre_tube);
saisie.focus();
}
if(response.data.status == 'init'){
$don.html(response.data.codeBarre);
$nom.html(response.data.nom);
$prenom.html(response.data.prenom);
$naissance.html(new Date(response.data.birthdate).toLocaleDateString());
$typeDon.html(response.data.type_don);
$nbreTube.html(response.data.nbre_tube);
$typePoche.html('');
saisie.focus();
}
if(response.data.status == 'error'){
$displayError.css('background', "red");
}
break;
case '1':
if(response.data.status == 'success'){
$typePoche.html(response.data.nbre_poche)
saisie.focus();
}
case '2':
if(response.data.status == 'success'){
saisie.focus();
$typePoche.html(response.data.nbre_poche)
console.log(response.data.nbre_poche)
}
if(response.data.status == 'final'){
saisie.focus();
$typePoche.html(response.data.nbre_poche)
console.log(response.data.nbre_poche)
console.log('valider avec un scan de poche!')
}
if(response.data.status == 'error_scan'){
console.log('error_scan');
saisie.focus();
}
if(response.data.status == 'error_doublon'){
console.log('error_doublon');
saisie.focus();
}
if(response.data.status == 'error_donneur'){
console.log('error_donneur');
saisie.focus();
}
break;
case '3':
if(response.data.status == "success"){
console.log("on passe aux tubes");
}
if(response.data.status == "error_scan"){
console.log("error_scan");
}
break;
case '4':
if(response.data.status == 'success'){
$nbreTube.html(response.data.nbre_tube)
saisie.focus();
console.log(response.data.nbre_poche)
}
if(response.data.status == 'final'){
$nbreTube.html(response.data.nbre_tube)
saisie.focus();
console.log(response.data.nbre_poche)
}
if(response.data.status == 'error_scan'){
console.log('error_scan');
saisie.focus();
}
if(response.data.status == 'error_doublon'){
console.log('error_doublon');
saisie.focus();
}
if(response.data.status == 'error_donneur'){
console.log('error_donneur');
saisie.focus();
}
break;
}
}
})

26
assets/styles/front.scss Normal file
View File

@ -0,0 +1,26 @@
.info{
display: flex;
justify-content: center;
align-items: center;
#info-don{
flex: 30%;
}
#info-donneur{
flex: 40%;
}
#info-psl{
flex: 30%;
}
}
#error{
height: 300px;
width: 300px;
background-color: grey;
}
#saisie{
position: absolute;
left:-300px
}

View File

@ -1,4 +1,4 @@
@import './header', './footer', './sidebar', 'common/login', 'add-flash';
@import './header', './footer', './sidebar', 'common/login', 'add-flash', 'front';
@import './global';
@import '~bootstrap/scss/bootstrap';
@import '~bootstrap/scss/bootstrap-utilities';

View File

@ -95,6 +95,7 @@
}
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4",
"phpunit/phpunit": "^9.5",
"symfony/browser-kit": "5.4.*",
"symfony/css-selector": "5.4.*",

167
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9f134246af84bf2d92c0ce49baff860b",
"content-hash": "69d13c1b69c850fca1f29419846bdfcb",
"packages": [
{
"name": "doctrine/annotations",
@ -8203,6 +8203,171 @@
}
],
"packages-dev": [
{
"name": "doctrine/data-fixtures",
"version": "1.5.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/data-fixtures.git",
"reference": "ba37bfb776de763c5bf04a36d074cd5f5a083c42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/ba37bfb776de763c5bf04a36d074cd5f5a083c42",
"reference": "ba37bfb776de763c5bf04a36d074cd5f5a083c42",
"shasum": ""
},
"require": {
"doctrine/common": "^2.13|^3.0",
"doctrine/persistence": "^1.3.3|^2.0|^3.0",
"php": "^7.2 || ^8.0"
},
"conflict": {
"doctrine/dbal": "<2.13",
"doctrine/phpcr-odm": "<1.3.0"
},
"require-dev": {
"doctrine/coding-standard": "^9.0",
"doctrine/dbal": "^2.13 || ^3.0",
"doctrine/mongodb-odm": "^1.3.0 || ^2.0.0",
"doctrine/orm": "^2.7.0",
"ext-sqlite3": "*",
"jangregor/phpstan-prophecy": "^1",
"phpstan/phpstan": "^1.5",
"phpunit/phpunit": "^8.5 || ^9.5",
"symfony/cache": "^5.0 || ^6.0",
"vimeo/psalm": "^4.10"
},
"suggest": {
"alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)",
"doctrine/mongodb-odm": "For loading MongoDB ODM fixtures",
"doctrine/orm": "For loading ORM fixtures",
"doctrine/phpcr-odm": "For loading PHPCR ODM fixtures"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Data Fixtures for all Doctrine Object Managers",
"homepage": "https://www.doctrine-project.org",
"keywords": [
"database"
],
"support": {
"issues": "https://github.com/doctrine/data-fixtures/issues",
"source": "https://github.com/doctrine/data-fixtures/tree/1.5.3"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures",
"type": "tidelift"
}
],
"time": "2022-04-19T10:01:44+00:00"
},
{
"name": "doctrine/doctrine-fixtures-bundle",
"version": "3.4.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/DoctrineFixturesBundle.git",
"reference": "601988c5b46dbd20a0f886f967210aba378a6fd5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/601988c5b46dbd20a0f886f967210aba378a6fd5",
"reference": "601988c5b46dbd20a0f886f967210aba378a6fd5",
"shasum": ""
},
"require": {
"doctrine/data-fixtures": "^1.3",
"doctrine/doctrine-bundle": "^1.11|^2.0",
"doctrine/orm": "^2.6.0",
"doctrine/persistence": "^1.3.7|^2.0|^3.0",
"php": "^7.1 || ^8.0",
"symfony/config": "^3.4|^4.3|^5.0|^6.0",
"symfony/console": "^3.4|^4.3|^5.0|^6.0",
"symfony/dependency-injection": "^3.4.47|^4.3|^5.0|^6.0",
"symfony/doctrine-bridge": "^3.4|^4.1|^5.0|^6.0",
"symfony/http-kernel": "^3.4|^4.3|^5.0|^6.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"phpstan/phpstan": "^1.4.10",
"phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20",
"symfony/phpunit-bridge": "^6.0.8",
"vimeo/psalm": "^4.22"
},
"type": "symfony-bundle",
"autoload": {
"psr-4": {
"Doctrine\\Bundle\\FixturesBundle\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Doctrine Project",
"homepage": "https://www.doctrine-project.org"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony DoctrineFixturesBundle",
"homepage": "https://www.doctrine-project.org",
"keywords": [
"Fixture",
"persistence"
],
"support": {
"issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues",
"source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.4.2"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-fixtures-bundle",
"type": "tidelift"
}
],
"time": "2022-04-28T17:58:29+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",

View File

@ -14,4 +14,5 @@ return [
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
];

View File

@ -5,14 +5,25 @@ 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
entry_point: form_login
form_login:
login_path: app_login
check_path: app_login
username_parameter: email
password_parameter: password
enable_csrf: true
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall
@ -23,7 +34,8 @@ security:
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/front, roles: ROLE_ADMIN }
- { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
when@test:

View File

@ -2,6 +2,7 @@
namespace App\Controller\Api;
use App\Entity\Don;
use App\Repository\DonRepository;
use App\Repository\DmuCatRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
@ -14,20 +15,23 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class ApiController extends AbstractController
{
public const REGEX_DON = '/^[0-9]{11}$/';
public const REGEX_GROUP_POCHE = '/^\d{6}[A-Z]{3}$/';
public const REGEX_GROUP_POCHE = '/[0-9]{6}[A-Z]{2}$/';
public const REGEX_ETIQUETTE = '/^\d{11}[\|]{1}[a-z]{1}$/';
public const NBRE_POCHE = 'nbre_poche';
/** @var DonRepository*/
public $donRepository;
/** @var DmuCatRepository*/
public $dmuCatRepository;
/** @var RequestStack*/
public $requestStack;
public function __construct(DmuCatRepository $dmuCatRepository, RequestStack $requestStack)
public function __construct(DonRepository $donRepository, RequestStack $requestStack, DmuCatRepository $dmuCatRepository)
{
$this->dmuCatRepository = $dmuCatRepository;
$this->donRepository = $donRepository;
$this->requestStack = $requestStack;
$this->dmuCatRepository = $dmuCatRepository;
}
/**
* @Route("/get-code-barre-type", name="code_barre_type_", methods={"POST"})
@ -36,122 +40,197 @@ class ApiController extends AbstractController
{
$codeBarre = $request->request->get('codeBarre');
$session = $request->getSession();
$step = $session->get('step') ?? 0;
$step = null !== $session->get('step') ? $session->get('step') : 0;
if($step != 0 && preg_match(self::REGEX_DON, $codeBarre)){
$this->init($session, $don = $this->dmuCatRepository->findOneByGiftNumber($codeBarre));
$this->init($session, $don = $this->donRepository->findOneByCodeBarre($codeBarre));
return $this->json(['data'=>[
'status'=>'init',
'step'=> '0',
'codeBarre'=>$don->GetCodeBarre(),
'nbre_tube'=>$don->getNbreTube(),
'donneur'=>$don->getPatient()->getFirstname() . ' ' . $don->getPatient()->getLastname()
]]);
'type_don'=> $don->getDonCat()->getName(),
'nom'=>$don->getDonneur()->getLastname(),
'prenom'=>$don->getDonneur()->getFirstname(),
'birthdate'=>$don->getDonneur()->getBirthdate(), ]]);
}
switch($step){
case 0:
if(preg_match(self::REGEX_DON, $codeBarre)){
$don = $this->dmuCatRepository->findOneByGiftNumber($codeBarre);
$don = $this->donRepository->findOneByCodeBarre($codeBarre);
$this->init($session, $don);
return $this->json(['data'=>[
'step'=> '0',
'status'=>'success',
'codeBarre'=>$don->GetCodeBarre(),
'nbre_tube'=>$don->getNbreTube(),
'donneur'=>$don->getPatient()->getFirstname() . ' ' . $don->getPatient()->getLastname()
'type_don'=> $don->getDonCat()->getName(),
'nom'=>$don->getDonneur()->getLastname(),
'prenom'=>$don->getDonneur()->getFirstname(),
'birthdate'=>$don->getDonneur()->getBirthdate(),
]]);
}else{
return $this->json(['data'=>'error']);
return $this->json(['data'=>[
'step'=>'0',
'status'=>'error',
'codebarre'=>$codeBarre
]
]);
}
break;
case 1:
if(preg_match(self::REGEX_GROUP_POCHE, $codeBarre)){
// if(self::REGEX_GROUP_POCHE == $codeBarre){
$dmuCatNumber = $this->dmuCatRepository->findOneByCodeBarre($codeBarre)->getPocheNumber();
$session->set('step', 2);
$session->set('nbre_poche' , $dmuCatNumber);
return $this->json(['data'=>[
'step'=> '1',
'status'=>'success',
'nbre_poche'=>$dmuCatNumber,
]]);
}else{
return $this->json(['data'=>'error']);
return $this->json(['data'=>[
'step'=> '1',
'status'=>'error',
'codebarre'=>$codeBarre
]
]);
}
break;
case 2:
if(preg_match(self::REGEX_ETIQUETTE, $codeBarre)){
$nbrePoche = $session->get('nbre_poche');
$listPoche = $session->get('list_poche');
$donCodeBarre = $session->get('don_code_barre');
$in = strpos('zz'.$codeBarre, $donCodeBarre);
if(!$in){
return $this->json(['data'=>[
'step'=> '2',
'status'=>'error_donneur',
'donCodeBarre'=>$donCodeBarre,
'codeBarre'=>$codeBarre,
'result'=>$in
]]);
}
$listPoche = $session->get('liste_poche');
if(!in_array($codeBarre, $listPoche)){
$listPoche[] = $codeBarre;
$session->set('liste_poche', $listPoche);
}else{
return $this->json(['data'=>'doublon']);
}
if($nbrePoche == 1){
$session->set('step', 3);
$session->set('nbre_poche', 0);
return $this->json(['data'=>[
'nbre_poche'=>$nbrePoche - 1,
'poche'=>'success'
]
]
);
}else{
'step'=> '2',
'status'=>'error_doublon'
]]);
}
if($nbrePoche > 1){
$session->set('nbre_poche', $nbrePoche - 1);
return $this->json(['data'=>[
'step'=> '2',
'status'=>'success',
'nbre_poche'=>$nbrePoche - 1
]
]);
}else{
$session->set('step', 3);
$session->set('nbre_poche', 0);
return $this->json(['data'=>[
'step'=> '2',
'status'=>'final',
'nbre_poche'=>$nbrePoche - 1,
]
]
);
}
}else{
return $this->json(['data'=>'error']);
return $this->json(['data'=>[
'step'=>'2',
'status'=> 'error_scan'
]]);
}
break;
case 3:
if(preg_match(self::REGEX_GROUP_POCHE, $codeBarre)){
$session->set('step', 4);
return $this->json(['data'=>[
'tube'=>true,
'step'=>'3',
'status'=>'success',
]]);
}else{
return $this->json(['data'=>'error']);
return $this->json(['data'=>[
'step'=> '3',
'status'=>'error_scan',
]
]);
}
break;
case 4:
if(preg_match(self::REGEX_ETIQUETTE, $codeBarre)){
$nbreTube = $session->get('nbre_tube');
$listTube = $session->get('list_tube');
$donCodeBarre = $session->get('don_code_barre');
if(!strpos('zz'.$codeBarre, $donCodeBarre)){
return $this->json(['data'=>[
'step'=>'4',
'status'=>'error_donneur'
]
]);
}
$listTube = $session->get('liste_tube');
if(!in_array($codeBarre, $listTube)){
$listTube[] = $codeBarre;
$session->set('list_tube', $listTube);
$session->set('liste_tube', $listTube);
}else{
return $this->json(['data'=>'doublon']);
return $this->json(['data'=>[
'step'=>'4',
'status'=>'error_doublon']
]);
}
if($nbreTube == 1){
if($nbreTube > 1){
$session->set('nbre_tube', $nbreTube - 1);
return $this->json(['data'=>[
'step'=>'4',
'status'=>'success',
'nbre_tube'=>$nbreTube - 1
]
]);
}else{
$session->set('step', 0);
$session->set('nbre_tube', 0);
$session->clear();
return $this->json(['data'=>[
'nbre_tube'=>$nbreTube - 1,
'tube'=>'success'
'step'=>'4',
'status'=>'final',
'nbre_tube'=>$nbreTube - 1
]
]
);
}else{
$session->set('nbre_tube', $nbreTube - 1);
return $this->json(['data'=>[
'nbre_tube'=>$nbreTube - 1
]
]);
}
}else{
return $this->json(['data'=>'error']);
return $this->json(['data'=>[
'step'=>'4',
'status'=>'error_scan']
]);
}
break;
default:
return $this->json(['data'=>'error']);
return $this->json(['data'=>[
'step'=>'4',
'status'=>'error_scan']
]);
}
}
public function init($session, Don $don)
{
$session->set('don' , $don->getId());
$session->set('don_code_barre' , $don->getCodeBarre());
$session->set('categorie_don' , $don->getDonCat()->getName());
$session->set('nbre_tube', $don->getNbreTube());
$session->set('liste_poche', []);
$session->set('liste_tube', []);
@ -159,16 +238,4 @@ class ApiController extends AbstractController
$session->set('step', 1);
}
// public function raz()
// {
// $session = $this->requestStack->getSession();
// $session->remove('don' );
// $session->remove('nbre_tube');
// $session->remove('liste_poche');
// $session->remove('liste_tube');
// $session->remove('donneur');
// $session->remove('step');
// }
}

View File

@ -54,7 +54,7 @@ class DonController extends AbstractController
],
'fields' => [
'Id' => 'Id',
'GiftNumber' => 'GiftNumber',
'CodeBarre' => 'CodeBarre',
'Nombre tube'=> 'NbreTube',
'Categorie' => 'DonCat',
'Donneur' => 'Donneur',

View File

@ -8,9 +8,23 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class FrontController extends AbstractController
{
#[Route("/", name: "app_front")]
#[Route("/front", name: "app_front")]
public function index(Request $request): Response
{
return $this->render('front/index.html.twig');
}
#[Route("/test", name: "app_reset_step")]
public function test(Request $request): Response
{
dump($request->getSession()->get('step'));
$request->getSession()->set('step', 0);
return $this->render('front/test.html.twig');
}
#[Route("/session", name: "app_session")]
public function session(Request $request): Response
{
dump($request->getSession()->get('liste_poche'));
return $this->render('front/session.html.twig', ['session'=>$request->getSession()->get('step')]);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController
{
private $requestStack;
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
if($error){
}
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}

View File

@ -0,0 +1,145 @@
<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\UserType;
use App\Form\Handler\UserHandler;
use App\Repository\UserRepository;
use App\Services\Tools;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Container\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Knp\Component\Pager\PaginatorInterface;
/**
* Class UserController
* @package App\Controller
* @Route("/admin/user", name="admin_app_user_")
*/
class UserController extends AbstractController
{
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @Route("/", name="index", methods={"GET"})
* @param UserRepository $userRepository
* PaginatorInterface $paginator
* Request $request
*/
public function index(UserRepository $userRepository, PaginatorInterface $paginator, Request $request): Response
{
$els = $paginator->paginate(
$userRepository->createQueryBuilder('a')->getQuery(),
$request->query->getInt('page', 1),
10
);
return $this->render('admin/crud/index.html.twig', [
'els'=>$els,
'paginator'=>false,
'search'=>false,
'class'=> User::class,
'route'=> 'admin_app_user',
'breadcrumb'=>[
[
'text'=>'tous les éléments'
]
],
'fields' => [
'Id' => 'Id',
'Email' => 'Email',
'UserIdentifier' => 'UserIdentifier',
'Roles' => 'Roles',
],
'title' => 'Tous les élements',
'add_button_label'=>'Ajouter un élément'
]);
}
/**
* @Route("/new", name="new", methods={"GET","POST"})
* @param Request $request
* @param UserHandler $userHandler
* @param Tools $tools
* @return Response
*/
public function new(Request $request, Tools $tools, UserHandler $userHandler): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
if ($userHandler->new($form, $request)) {
return $this->redirectToRoute('admin_app_user_index');
}
return $this->render('admin/crud/_form.html.twig', [
'form'=>$form->createView(),
'el'=>$user,
'button_label'=>'Créer',
'route'=>'admin_app_user',
'title'=>'Ajouter un élément',
'breadcrumb'=>[
[
'route'=>'admin_app_user_index',
'text'=>'tous les éléments'
],
[
'text'=>'ajouter un élément'
]
],
]);
}
/**
* @Route("/edit/{id}", name="edit")
* @param Request $request
* @param User $user
* @param Tools $tools
* @return Response
*/
public function edit(Request $request, User $user, Tools $tools): Response
{
$form = $this->createForm(UserType::class, $user);
if ($userHandler->edit($form, $request)) {
return $this->redirectToRoute('admin_app_user_edit', ['id'=>$user->getId()]);
}
return $this->render('admin/crud/_form.html.twig', [
'el' => $user,
'route'=> 'admin_app_user',
'form' => $form->createView(),
'button_label' => 'Mettre à jour',
'title' => 'Edition',
'breadcrumb'=>[
[
'route'=>'admin_app_user_index',
'text'=>'users'
],
[
'text'=>'édition '
]
],
]);
}
/**
* @Route("/{id}", name="delete", methods={"DELETE"})
* @param Request $request
* @return Response
*/
public function delete(Request $request,User $user): Response
{
if ($this->isCsrfTokenValid('delete'.$user->getId(), $request->request->get('_token'))) {
$this->entityManager->remove($user);
$this->entityManager->flush();
}
return $this->redirectToRoute('admin_app_user_index');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\DataFixtures;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
class AppFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
// $product = new Product();
// $manager->persist($product);
$manager->flush();
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\DataFixtures;
use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
class UserFixtures extends Fixture implements FixtureGroupInterface
{
private $passwordEncoder;
public function __construct(UserPasswordHasherInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
public function load(ObjectManager $manager)
{
$user = new User();
$user->setPassword($this->passwordEncoder->hashPassword(
$user,
"rootroot"
));
$user->setEmail("rmasson.pro@gmail.com")
->setRoles(["ROLE_USER","ROLE_ADMIN"]);
$manager->persist($user);
$manager->flush();
}
public static function getGroups(): array
{
return ['userGroup'];
}
}

View File

@ -14,7 +14,7 @@ class Don
private ?int $id = null;
#[ORM\Column]
private ?string $giftNumber = null;
private ?string $codeBarre = null;
#[ORM\ManyToOne(inversedBy: 'dons')]
#[ORM\JoinColumn(nullable: false)]
@ -32,14 +32,14 @@ class Don
return $this->id;
}
public function getGiftNumber(): ?string
public function getCodeBarre(): ?string
{
return $this->giftNumber;
return $this->codeBarre;
}
public function setGiftNumber(string $giftNumber): self
public function setCodeBarre(string $codeBarre): self
{
$this->giftNumber = $giftNumber;
$this->codeBarre = $codeBarre;
return $this;
}

118
src/Entity/User.php Normal file
View File

@ -0,0 +1,118 @@
<?php
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;
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180, unique: true)]
private ?string $email = null;
#[ORM\Column]
private array $roles = [];
/**
* @var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* @deprecated since Symfony 5.3, use getUserIdentifier instead
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* @see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
}

View File

@ -15,7 +15,7 @@ class DonType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('giftNumber')
->add('codeBarre')
->add('donCat', EntityType::class, [
'class'=> DonCat::class,
'choice_label'=> 'name'

View File

@ -0,0 +1,40 @@
<?php
namespace App\Form\Handler;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\FormInterface;
class UserHandler extends AbstractController
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function new(FormInterface $form, Request $request): bool
{
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$this->entityManager->persist($user);
$this->entityManager->flush();
return true;
}
return false;
}
public function edit(FormInterface $form, Request $request): bool
{
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->flush();
return true;
}
return false;
}
}

27
src/Form/UserType.php Normal file
View File

@ -0,0 +1,27 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('email')
->add('roles')
->add('password')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}

View File

@ -0,0 +1,83 @@
<?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>
*
* @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 implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
public function save(User $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
public function remove(User $entity, bool $flush = false): void
{
$this->getEntityManager()->remove($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
/**
* 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.', \get_class($user)));
}
$user->setPassword($newHashedPassword);
$this->save($user, true);
}
// /**
// * @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()
// ;
// }
}

View File

@ -0,0 +1,97 @@
<?php
namespace App\Security;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
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\Util\TargetPathTrait;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
private UserRepository $userRepository;
private RouterInterface $router;
public function __construct(RouterInterface $router, UserRepository $userRepository)
{
$this->userRepository = $userRepository;
$this->router = $router;
}
public function supports(Request $request): bool
{
dd("supports");
return self::LOGIN_ROUTE === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function authenticate(Request $request): Passport
{
$email = $request->request->get('email');
$password = $request->request->get('password');
return new Passport(
new UserBadge($email, function($userIdentifier) {
// optionally pass a callback to load the User manually
$user = $this->userRepository->findOneBy(['email' => $userIdentifier]);
if (!$user) {
throw new UserNotFoundException();
}
// dd($user);
return $user;
}),
// new CustomCredentials(function($credentials, User $user) {
// dd($credentials, $user);
// }, $password)
new PasswordCredentials($password),
[
new CsrfTokenBadge(
'authenticate',
$request->request->get('_csrf_token')
)
]
);
}
protected function getLoginUrl(Request $request): string
{
return $this->router->generate('app_login');
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->router->generate("admin_home"));
// For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
// throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
{
dd('sdlkedlkhbfea');
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
return new RedirectResponse(
$this->router->generate('app_login')
);
}
}

View File

@ -25,6 +25,18 @@
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-fixtures-bundle": {
"version": "3.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "1f5514cfa15b947298df4d771e694e578d4c204d"
},
"files": [
"src/DataFixtures/AppFixtures.php"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.2",
"recipe": {

View File

@ -10,6 +10,7 @@
<li><a href="{{ path('admin_app_patient_index') }}">Donneur</a></li>
<li><a href="{{ path('admin_app_tube_index') }}">Tube</a></li>
<li><a href="{{ path('admin_app_dmu_cat_index') }}">Categorie DMU</a></li>
<li><a href="{{ path('admin_app_user_index') }}">User</a></li>
</ul>
</div>

View File

@ -16,13 +16,31 @@
</head>
<body>
<form action="">
<input type="text" style="visibility:visible" id="saisie">
<input type="text" id="saisie">
</form>
<div class="container">
<div class="wrapper">
<div class="container">
<div class="info">
<div id="info-don">
<h2>numéro de don</h2>
<span id="don"></span>
</div>
<div id="info-donneur">
<span id="nom"></span>
<span id="prenom"></span>
<span id="naissance"></span>
</div>
<div id="info-psl">
<span id="typeDon"></span>
<span id="typePoche"></span>
<span id="nbreTube"></span>
</div>
</div>
</div>
<div class="container">
<div class="wrapper">
<div id="error"></div>
</div>
</div>
</div>
{{ encore_entry_script_tags('app') }}
</body>
</html>

View File

@ -0,0 +1,20 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{% block title %}Administration{% endblock %}</title>
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" type="image/png" href="{{ asset('favicon/favicon.ico') }}"/>
{{ encore_entry_link_tags('adminStyle') }}
{% block stylesheets %}
{% endblock %}
</head>
<body>
<h1>{{session}}</h1>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{% block title %}Administration{% endblock %}</title>
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" type="image/png" href="{{ asset('favicon/favicon.ico') }}"/>
{{ encore_entry_link_tags('adminStyle') }}
{% block stylesheets %}
{% endblock %}
</head>
<body>
{{ encore_entry_script_tags('app') }}
</body>
</html>

View File

@ -0,0 +1,35 @@
{% extends 'base.html.twig' %}
{% block title %}Log in!{% endblock %}
{% block body %}
<div class="login-wrapper">
<div class="login">
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail">Email</label>
<input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" required autofocus>
<label for="inputPassword">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" required>
<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">
Sign in
</button>
</form>
</div>
</div>
{% endblock %}