From f0be849a2c8c956fad97319019ee4bb3e86983ef Mon Sep 17 00:00:00 2001 From: pfleu <pierre.fleutot@audemarspiguet.com> Date: Mon, 2 Dec 2024 11:34:31 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20formulaire=20User=20pour=20modifier=20l?= =?UTF-8?q?e=20r=C3=B4le=20et=20le=20pseudo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/packages/security.yaml | 2 +- src/Controller/AppUserController.php | 27 +++++++ src/Entity/User.php | 11 +++ src/Form/UserType.php | 115 +++++++++++++++++++++++++++ templates/user/index.html.twig | 6 +- 5 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 src/Form/UserType.php diff --git a/config/packages/security.yaml b/config/packages/security.yaml index a7a4e9c..fb717d5 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -26,7 +26,7 @@ security: api_token: pattern: ^/api/token$ security: false - api: + api: # Pour permettre à l'utilisateur connecté sur Balex (avec rôle admin) d'utiliser le swagger sans token, on commente tout le pare-feu "api" pattern: ^/api(?!/doc$) # Accepts routes under /api except /api/doc (pour api/doc, on utilisera donc le firewall "main" ce qui permettra d'accéder au swagger quand on est authentifié via Session PHP avec le role Admin security: true stateless: true # Pas d'authentification, pas de session utilisateur (mais le compte user est vérifié via le token) diff --git a/src/Controller/AppUserController.php b/src/Controller/AppUserController.php index c0a4336..53785dd 100644 --- a/src/Controller/AppUserController.php +++ b/src/Controller/AppUserController.php @@ -6,6 +6,7 @@ use App\Entity\Entry; use App\Entity\User; use App\Form\UserAddFriendType; use App\Form\UserProfileFormType; +use App\Form\UserType; use App\Repository\UserRepository; use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -87,6 +88,32 @@ class AppUserController extends AbstractController ]); } + /** + * @Route("/{id}/edit", name="user_edit", methods={"GET","POST"}) + * @IsGranted("ROLE_ADMIN") + */ + public function edit(Request $request, User $appUser): Response + { + $form = $this->createForm(UserType::class, $appUser, [ + 'action' => $this->generateUrl('user_edit', ['id' => $appUser->getId()]) + ]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + + $this->doctrine->getManager()->flush(); + $this->addFlash('success',$this->translator->trans("L'utilisateur a été modifié.")); + + return $this->render('closeModalAndReload.html.twig'); + } + + return $this->render('genericModalForm.html.twig', [ + 'title' => $this->translator->trans("Modifier l'utilisateur") . ': ' . $appUser, + 'user' => $appUser, + 'form' => $form->createView(), + ]); + } + /** * @Route("/{id}/edit-activation", name="app_user_toggle_activation") */ diff --git a/src/Entity/User.php b/src/Entity/User.php index 3953b6f..128c399 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -35,6 +35,12 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface 'C2' => 'C2', ]; + const EDIT_ROLES = [ + 'ROLE_USER' => 'Student', + 'ROLE_TEACHER' => 'Teacher', + 'ROLE_ADMIN' => 'Admin', + ]; + const ROLES = [ 'ROLE_USER' => 'Student', 'ROLE_TEACHER' => 'Teacher', @@ -395,12 +401,17 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface $this->successes->add($success); } + // Si on a que le ROLE_USER (student), on le retourne, sinon on le supprime de la liste (car on ne peut avoir qu'un rôle à la fois et on veut afficher le plus haut) public function getFormattedRoles() { $result = []; foreach ($this->getRoles() as $role) { $result[] = self::ROLES[$role]; } + if (count($result) > 1) { + $result = array_diff($result, [self::ROLES['ROLE_USER']]); + } + return $result; } diff --git a/src/Form/UserType.php b/src/Form/UserType.php new file mode 100644 index 0000000..ce31d1c --- /dev/null +++ b/src/Form/UserType.php @@ -0,0 +1,115 @@ +<?php + +namespace App\Form; + +use App\Entity\Company; +use App\Entity\Department; +use App\Entity\Project; +use Doctrine\ORM\EntityRepository; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; +use Symfony\Component\Security\Core\Security; +use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\NotBlank; +use App\Entity\User; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\PasswordType; +use Symfony\Component\Form\Extension\Core\Type\RepeatedType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class UserType extends AbstractType +{ + private $security; + + public function __construct(Security $security) + { + $this->security = $security; + } + public function buildForm(FormBuilderInterface $builder, array $options) + { + $stringToArrayTransformer = new CallbackTransformer( + function ($listAsArray) { + // transform the array to a string + + // On supprime le ROLE_USER + $filtered = []; + foreach ($listAsArray as $item) { + if ($item != "ROLE_USER" && $item != "ROLE_SUPER_ADMIN") { + $filtered[] = $item; + } + } + + if ($filtered) { + return implode("\r\n", $filtered); + } else { + return ''; + } + }, + function ($listAsString) { + // transform the string back to an array + if (empty($listAsString)) { + return array(); + } else { + $resultArray = explode("\r\n", $listAsString); + return array_filter($resultArray, function($value) { return $value !== ''; }); + } + } + ); + + + $rolesChoices = array_flip(User::EDIT_ROLES); + + $user = $builder->getData(); + + $builder + ->add('pseudo', null, ['label' => "Pseudo"]) + ; + + if ($user !== $this->security->getUser()) { + $builder + ->add('roles', ChoiceType::class, [ + 'label' => 'Rôle', + 'choices' => $rolesChoices, + 'constraints' => [new NotBlank(['message' => 'Veuillez indiquer un rôle.'])] + ]); + $builder->get('roles')->addModelTransformer($stringToArrayTransformer); + } + + $builder + ->add('submit', SubmitType::class, array( + 'label' => 'Enregistrer', + 'attr' => ['class' => 'btn-primary'] + )) + ; + +// if ($this->security->isGranted('CAN_EDIT_ROLES_USER', $builder->getData())) { +// $builder +// ->add('disabled', null, ['label' => "Désactiver l'utilisateur"]); +// } + + + +// $builder->get('languages')->addModelTransformer($stringToArrayTransformer); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => User::class, + 'attr' => [ + 'data-ajax-form' => '', + 'data-ajax-form-target' => '#bootstrap-modal .modal-content', + 'novalidate' => 'novalidate', + ], + ]); + } +} diff --git a/templates/user/index.html.twig b/templates/user/index.html.twig index ad7a5ac..adfd5c1 100644 --- a/templates/user/index.html.twig +++ b/templates/user/index.html.twig @@ -1,6 +1,7 @@ {% extends 'base.html.twig' %} {% block title %}{{ "Utilisateurs"|trans }}{% endblock %} +{% block container %}container-fluid {% endblock %} {% block body %} @@ -17,6 +18,7 @@ <tr> <th>Pseudo</th> <th>Email</th> + <th>Rôle</th> <th>Gamification</th> <th>{{ "Stats persos"|trans }}</th> <th>{{"Partage données"|trans}}<br>{{ "autres utilisateurs"|trans }}</th> @@ -33,6 +35,7 @@ <tr class="{{ not user.enabled ? 'text-muted fst-italic' }}"> <td>{{ user.pseudo }}</td> <td>{{ user.email }}</td> + <td>{{ user.formattedRoles|join(', ') }}</td> <td>{{ user.activeGamification ? '<i class="bi bi-check text-success"></i>' : '<i class="bi bi-x text-danger"></i>' }}</td> <td>{{ user.activePersonalStats ? '<i class="bi bi-check text-success"></i>' : '<i class="bi bi-x text-danger"></i>' }}</td> <td>{{ user.shareDataWithOtherUsers ? '<i class="bi bi-check text-success"></i>' : '<i class="bi bi-x text-danger"></i>' }}</td> @@ -47,7 +50,8 @@ <a href="{{ path('app_user_toggle_activation', {'id': user.id}) }}" class="btn btn-secondary btn-xs">{{ "Activer"|trans }}</a> {% endif %} </td> - <td> + <td class="text-nowrap"> + <a href="#" data-url="{{ path('user_edit', {'id': user.id}) }}" class="btn btn-secondary btn-xs modal-form"><i class="fa fa-pencil"></i></a> <a data-confirm="{{ "Confirmer la suppression ?"|trans }}" data-bs-toggle="modal" data-bs-target="#confirm-dialog" data-href="{{ path('app_user_delete', {id: user.id}) }}" class="btn btn-xs btn-danger"><i class="bi-x-circle"></i></a> </td> -- GitLab