12 - Live Coding : Gérer les rôles utilisateurs avec Symfony 4

Dans la plupart des sites, il est nécessaire de créer plusieurs rôles pour les utilisateurs afin de leur donner accès à différentes parties du site en fonction de leur profil.



Nous aurons donc assez régulièrement des profils du type :




  • Utilisateur

  • Editeur

  • Modérateur

  • Administrateur



Dans cet article, nous allons voir comment créer et utiliser ces rôles dans notre site réalisé avec Symfony 4.



Nous allons donc commencer par définir les différents types de profils dont nous aurons besoin, et leur donner une hiérarchie.



Ainsi, si un utilisateur a un rôle "supérieur" au rôle requis pour accéder à une fonctionnalité, il y aura accès sans pour autant avoir besoin qu'on lui attribue le rôle en question.



Dans notre exemple, nous aurons 3 rôles pour notre site :




  • Utilisateur

  • Editeur

  • Administrateur



Les utilisateurs pourront lire et commenter, les éditeurs pourront ajouter des articles et les administrateurs pourront gérer le site.



Déclarer les rôles



Nous allons déclarer les rôles que nous utiliserons, leur hiérarchie et les routes qui leur sont réservées dans le fichier "config/packages/security.yaml"




security:

# ici se trouve votre contenu par défaut

# Dans la partie access_control nous définissons les routes protégées
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/profil, roles: ROLE_USER }

# La partie role_hierarchy contient la hiérarchie des rôles
# Un éditeur sera également utilisateur
# Un administrateur sera également éditeur et donc utilisateur
role_hierarchy:
ROLE_EDITOR: ROLE_USER
ROLE_ADMIN: ROLE_EDITOR


Attribuer les rôles



Nous attribuons les rôles aux utilisateurs après leur inscription. Nous partirons du principe que seuls les administrateurs pourront modifier ces rôles.



1er utilisateur



ATTENTION, le 1er administrateur doit être configuré dans la base de données.



Il faudra acéder à PHPMyAdmin (ou tout autre outil de gestion de la base de données) et lui attribuer le rôle administrateur en modifiant son rôle en mettant ceci




[
"ROLE_ADMIN"
]


Gestion des utilisateurs



Une fois le 1er administrateur créé, nous allons pouvoir créer nos pages de gestion des utilisateurs, qui permettront de modifier ou supprimer des utilisateurs.



Pour la gestion des utilisateurs, il est possible d'utiliser "Easy Admin", traité dans le tutoriel "Créer une interface d'administration". Dans cet exemple, nous allons créer les pages sans l'utiliser.



Création du contrôleur



Nous allons commencer par créer le contrôleur d'administration. Nous l'appellerons "AdminController". Saisir cette commande




php bin/console make:controller


Pour protéger la totalité des routes gérées par ce contrôleur, nous allons lui attribuer la route "/admin" en modifiant les annotations comme ceci




/**
* @Route("/admin", name="admin_")
*/
class AdminController extends AbstractController
{
/**
* @Route("/", name="accueil")
*/
public function index()
{
return $this->render('admin/index.html.twig', [
'controller_name' => 'AdminController',
]);
}
}


Lister les utilisateurs



Dans notre contrôleur d'administration, nous allons créer une méthode permettant de lister les utilisateurs inscrits ainsi que leurs rôles.



Cette méthode, que nous appellerons "usersList", par exemple, s'écrira comme suit




/**
* @Route("/utilisateurs", name="utilisateurs")
*/
public function usersList(UsersRepository $users)
{
return $this->render('admin/users.html.twig', [
'users' => $users->findAll(),
]);
}


Il nous faut donc également créer un fichier twig, que nous stockerons dans le dossier "/templates/admin" et que nous appellerons "users.html.twig"



Ce fichier contiendra ce qui suit




{% extends 'base.html.twig' %}

{% block title %}Liste des utilisateurs{% endblock %}

{% block body %}
<h1>Liste des utilisateurs</h1>
<table>
<thead>
<th>ID</th>
<th>Email</th>
<th>Rôles</th>
<th>Articles</th>
<th>Actions</th>
</thead>
<tbody>
{# On boucle sur les utilisateurs #}
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.email }}</td>
<td>
{# On boucle sur les rôles #}
{% for role in user.roles %}
{% if role == "ROLE_USER" %}
Utilisateur
{% elseif role == "ROLE_EDITOR" %}
Editeur
{% elseif role == "ROLE_ADMIN" %}
Administrateur
{% endif %}
{% endfor %}
</td>
<td>{{ user.articles|length }}</td>
<td><a href="{{ path('admin_modifier_utilisateur', {'id': user.id}) }}">Modifier</a></td>
</tr>

{% else %}
<p>Aucun utilisateur inscrit</p>
{% endfor %}
</tbody>
</table>
{% endblock %}


A ce stade, nous aurons une erreur indiquant que la route "admin_modifier_utilisateur" n'a pas été trouvée. Nous allons donc la créer à l'étape suivante.



Modifier un utilisateur



Pour modifier un utilisateur, nous allons devoir créer un formulaire, une méthode dans notre contrôleur et un fichier Twig pour l'afficher.



Le formulaire sera créé au moyen de la commande




php bin/console make:form


Nous allons nommer notre formulaire "EditUserType". Il contiendra ce code par défaut.




<?php

namespace App\Form;

use App\Entity\Users;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class EditUserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email')
->add('roles')
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Users::class,
]);
}
}


Nous allons modifier le "builder" pour personnaliser l'affichage du formulaire :




  • Le champ email sera de type "email" et ne pourra pas être vide

  • Le champ rôles affichera des cases à cocher avec les 3 rôles prévus

  • Nous allons ajouter un bouton pour valider la modification



Le code sera le suivant




$builder
->add('email', EmailType::class,[
'constraints' => [
new NotBlank([
'message' => 'Merci d\'entrer un e-mail',
]),
],
'required' => true,
'attr' => ['class' =>'form-control'],
])
->add('roles', ChoiceType::class, [
'choices' => [
'Utilisateur' => 'ROLE_USER',
'Editeur' => 'ROLE_EDITOR',
'Administrateur' => 'ROLE_ADMIN'
],
'expanded' => true,
'multiple' => true,
'label' => 'Rôles'
])
->add('valider', SubmitType::class)
;


Avec ces nouvelles modifications, nous allons devoir ajouter des dépendances




use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Validator\Constraints\NotBlank;


Dans notre contrôleur, la méthode doit récupérer l'information de l'utilisateur à modifier, créer le formulaire et le gérer si le formulaire est soumis.



Le code sera le suivant




/**
* @Route("/utilisateurs/modifier/{id}", name="modifier_utilisateur")
*/
public function editUser(Users $user, Request $request)
{
$form = $this->createForm(EditUserType::class, $user);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();

$this->addFlash('message', 'Utilisateur modifié avec succès');
return $this->redirectToRoute('admin_utilisateurs');
}

return $this->render('admin/edituser.html.twig', [
'userForm' => $form->createView(),
]);
}


Enfin, dans le fichier twig, que nous pourrons, par exemple, appeler "edituser.html.twig", nous allons appeler ce formulaire.




{% extends 'base.html.twig' %}

{% block title %}Modifier un utilisateur{% endblock %}

{% block body %}
<h1>Modifier un utilisateur</h1>
{{ form(userForm) }}
{% endblock %}


Protéger les routes



Une fois les rôles utilisateurs gérés, nous allons pouvoir donner des permissions d'accès à nos routes.



Il y a plusieurs façons de protéger les routes, les principales sont traitées dans les parties suivantes.



security.yaml



Au début de cet article, nous avons modifié le fichier "security.yaml" pour y intégrer la hiérarchie des rôles et certaines protections de routes.



Cette protection se trouve dans cette partie




access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/profil, roles: ROLE_USER }


Dans le code ci-dessus, nous imposons un rôle d'administrateur pour accéder à la route "/admin" et un rôle d'utilisateur pour accéder à la route "/profil"



Annotations



Il est également possible de protéger les routes par l'intermédiaire des annotations.



Dans un article précédent nous avons créé une route pour ajouter un article sur notre blog. Nous avions protégé cette route pour la réserver aux utilisateurs connectés en ajoutant cette annotation




/**
* @IsGranted("ROLE_USER")
* @Route("/article/ajouter", name="ajout_article")
*/


Si nous souhaitons réserver cette route aux éditeurs et administrateurs, nous allons modifier l'annotation de la façon suivante




/**
* @IsGranted("ROLE_EDITOR")
* @Route("/article/ajouter", name="ajout_article")
*/


Contrôleur



Enfin, une autre méthode commune de protection des routes est une méthode php dans le contrôleur.



Il est possible d'ajouter la ligne suivante où nous le souhaitons dans nos méthodes de contrôleurs




$this->denyAccessUnlessGranted('ROLE_ADMIN');


Dans cet exemple, l'utilisateur qui n'a pas le rôle administrateur se verra interdire l'accès.



Gérer l'affichage en fonction des rôles



Pour terminer, il est possible de gérer l'affichage dans nos fichiers twig en fonction du rôle des utilisateurs.



Ainsi, nous pourrons afficher certaines informations ou certains liens selon le contexte.



Vérifier si l'utilisateur est connecté



Certains contenus sont affichés si l'utilisateur est connecté, quel que soit son rôle.



Avec Symfony, tout utilisateur connecté aura le rôle "utilisateur" par défaut.



De ce fait, nous pourrons vérifier si ce rôle existe dans notre fichier twig de cette façon




{% if is_granted('ROLE_USER') %}

{# Ici le contenu réservé aux utilisateurs connectés #}

{% else %}

{# Ici le contenu affiché aux utilisateurs non connectés #}

{% endif %}


Vérifier si l'utilisateur a un certain rôle



Certains contenus sont affichés uniquement si l'utilisateur a un certain rôle.



Nous pourrons utiliser la même méthode pour vérifier les rôles.




{% if is_granted('ROLE_EDITOR') %}

{# Ici le contenu réservé aux éditeurs #}

{% endif %}

{% if is_granted('ROLE_ADMIN') %}

{# Ici le contenu réservé aux administrateurs#}

{% endif %}


Obtenir de l'aide



Pour obtenir de l'aide, vous pouvez accéder au serveur Discord pour une entraide par chat

12 - Live Coding : Gérer les rôles utilisateurs avec Symfony 4
Article publié le - Modifié le

Catégories : MVC PHP Tutoriel Symfony Live-Coding

Mots-clés : Tutoriel Controllers Framework MVC PHP Routes Utilisateurs Symfony Live-Coding Formulaires roles

Partager : Partager sur Facebook Partager sur Twitter Partager sur LinkedIn