SOMMAIRE


Introduction


Dans le chapitre précédent, nous avons protégé la page qui affiche la liste des prises de contact. Un simple utilisateur connecté peut la consulter. Dans ce chapitre, nous allons protéger des pages suivant le rôle donné aux utilisateurs.


Définition des rôles


Nous allons distinguer 3 types d’utilisateurs :

L’administrateur qui pourra se rendre sur toutes les pages du site afin de gérer toutes les données.

Le modérateur qui pourra gérer ses données et consulter la liste des contacts.

L’utilisateur qui pourra gérer uniquement ses données.


En Symfony, les rôles doivent commencer par « ROLE_ ».

Ainsi, voici les rôles de notre application :


Nom

Rôle

Le rôle comprend les droits :

Administrateur

ROLE_ADMIN

ROLE_MOD et ROLE_USER

Modérateur

ROLE_MOD

ROLE_USER

Utilisateur

ROLE_USER



Remarque :

Nous remarquons qu’il y a une hiérarchie dans les droits, nous allons l’indiquer dans le fichier « config/packages/security.yaml ». Le code complet de cette page sera donné plus bas.


   role_hierarchy:
        ROLE_MOD: [ROLE_USER]
        ROLE_ADMIN: [ ROLE_MOD]   


Remarque :

Il est inutile de créer une ligne pour le ROLE_USER car il n’y a pas de compte en dessous de lui.

L’administrateur aura ses droits ainsi que les droits des utilisateurs et des modérateurs.


Nous allons maintenant exiger le rôle modérateur pour nous rendre sur une page dont l’url commence par « /private ». Modifiez la ligne pour obtenir ceci :


 access_control:
     # - { path: ^/admin, roles: ROLE_ADMIN }
     # - { path: ^/profile, roles: ROLE_USER }
       - { path: ^/private, roles: ROLE_MOD }


Un utilisateur inscrit aura automatiquement un « ROLE_USER » car si nous regardons l’entité « User », nous remarquons ceci :


     /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }


Commentaire :

Quoiqu’il arrive, le code ajoute le rôle « ROLE_USER » au tableau des rôles lors de l’appel à la méthode « getRoles ».


Code complet de la page « config/packages/security.yaml


security:
    enable_authenticator_manager: true
    # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
        App\Entity\User:
            algorithm: auto

    # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
    providers:
        # 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: app_user_provider
            custom_authenticator: App\Security\AppCustomAuthenticator
            logout:
                path: app_logout
                # where to redirect after logout
                # target: app_any_route

            # activate different ways to authenticate
            # https://symfony.com/doc/current/security.html#the-firewall

            # https://symfony.com/doc/current/security/impersonating_user.html
            # switch_user: true

    role_hierarchy:
        ROLE_MOD: [ROLE_USER]
        ROLE_ADMIN: [ROLE_MOD]        

    # 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: ^/profile, roles: ROLE_USER }
        - { path: ^/private, roles: ROLE_MOD }


Tester les rôles


Habituellement, lorsque vous installez un site Wordpress, Joomla ou autres, l’administrateur d’un site Web est la personne qui installe le site Web. Nous allons tricher un peu en donnant à notre compte le rôle administrateur en passant directement par MariaDB.


Allez dans votre base de données avec PhpMyadmin et affichez la table « user ».





Dans la colonne « roles », mettez « ROLE_ADMIN » entre les crochets en cliquant sur « éditez ».





Maintenant que votre compte est « administrateur », rendez-vous à l’url « /private-liste-contacts » en étant connecté. Vous voyez que vous avez l’autorisation.


Travail à faire :

Inscrivez 2 autres comptes à l’aide du formulaire prévu à cet effet. Activez manuellement les utilisateurs en mettant un 1 dans la colonne « is_verified ».

Choisissez un des 2 comptes pour lui donner le rôle de modérateur. Testez la connexion à la page dont l’url est « /private-liste-contacts ». Cela doit fonctionner.

Enfin, déconnectez-vous, et reconnectez-vous avec le 3ème compte. A-t-il le droit d’accéder à la liste des contacts ?








Vérifier les rôles dans TWIG


Le site a normalement un bon comportement. Il interdit à un utilisateur lambda de se connecter à la page « /private-liste-contacts ». En revanche, il propose à l’utilisateur de se rendre sur cette page à partir du menu.

En effet, dans « templates/base.html.twig », nous trouvons ce code :


{% if not is_granted('IS_AUTHENTICATED_FULLY') %}
    <li class="nav-item">
        <a class="nav-link text-white" href="{{path('app_login')}}">Se connecter</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-white" href="{{path('app_register')}}">S'inscrire</a>
    </li>
{% else %}
     <li class="nav-item">
         <a class="nav-link text-white" href="{{path('liste-contacts')}}">Liste des contacts</a>
     </li>
     <li class="nav-item">
         <a class="nav-link text-white" href="{{path('app_logout')}}"> {{app.user.email}}
         <i class="bi bi-x-circle-fill text-white"></i></a>
     </li>
{% endif %}


Remarque :

Le test du « if » regarde si vous avez réussi à vous connecter. Il ne vérifie pas si vous avez les bons droits.


Voici le test qu’il faut mettre dans TWIG pour afficher le lien uniquement aux modérateurs ou aux administrateurs.


{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_MOD')%}
    <li class="nav-item">
	<a class="nav-link text-white" href="{{path('liste-contacts')}}">Liste des contacts</a>
    </li>
{% endif %}


Exercices 


Exercice 1 :


Réalisez une page qui affichera la liste des utilisateurs. Nous souhaitons visualiser, l’adresse email, la date d’inscription (à vous d’intégrer cette nouvelle donnée), la valeur « validé » si l’utilisateur a validé son compte ou « non validé » dans le cas contraire. Il serait intéressant de trier la liste par l’ordre décroissant des inscriptions.




Cette page sera accessible uniquement à un administrateur du site via un menu déroulant, voir plus bas pour être guidé.






Pour réaliser le menu avec un menu déroulant d’administration, adaptez le code suivant tiré de la documentation de Bootstrap :


<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Navbar scroll</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarScroll" aria-controls="navbarScroll" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarScroll">
      <ul class="navbar-nav me-auto my-2 my-lg-0 navbar-nav-scroll" style="--bs-scroll-height: 100px;">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarScrollingDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Link
          </a>
          <ul class="dropdown-menu" aria-labelledby="navbarScrollingDropdown">
            <li><a class="dropdown-item" href="#">Action</a></li>
            <li><a class="dropdown-item" href="#">Another action</a></li>
            <li><hr class="dropdown-divider"></li>
            <li><a class="dropdown-item" href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="nav-item">
          <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Link</a>
        </li>
      </ul>
      <form class="d-flex">
        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-success" type="submit">Search</button>
      </form>
    </div>
  </div>
</nav>



Twig dispose du « in » permettant de tester l’existence d’une valeur dans un tableau.


Exercice 2 :


Dans la liste précédente, ajoutez une colonne indiquant si la personne est un administrateur, un modérateur ou un utilisateur. Aidez-vous d’un test dans TWIG qui permet de tester si une valeur se trouve dans un tableau.


{% if value in array %}





Exercice 3 :







Une personne connectée pourra consulter son profil accessible depuis la page d’accueil. Il s’agira d’une nouvelle page sur laquelle vous afficherez le nom, le prénom de la personne, son rôle et sa date d’inscription.





Certaines données ne sont pas encore présentes dans l’entité « User ». Ajoutez-les et modifiez le formulaire d’inscription afin de les saisir lors de la création d’un compte.




La correction est disponible sur simple demande. Cependant, faites de votre mieux et prenez le temps de réfléchir.