26/03/2023

2. Gestion d'accès

Lu 353 fois Licence Creative Commons

Roles

Les utilisateurs possèdent des rôles qui leur sont attribués et enregistrés en base de données. Ce sont des attributs sous la forme d'une chaîne de caractères commençant par ROLE_. On peut créer tous les rôles que l'on souhaite.
Par défaut, tous les utilisateurs possèdent le rôle ROLE_USER, on peut alors vérifier si l'utilisateur courant possède ce rôle pour savoir s'il est connecté ou non.

Twig

Dans /templates/_template.html.twig on souhaite changer les liens à droite du menu lorsque l'utilisateur est connecté. On va se servir de la fonction is_granted() et de la variable globale app pour accéder à l'utilisateur courant:

{# ... #}
<div class="navbar-end">
	<div class="navbar-item">
		<div class="buttons">
			{% if is_granted('ROLE_USER') %}
				<a class="button is-primary" href="#">
					<span class="icon"><i class="fa-solid fa-circle-user"></i></span>
					<strong>{{ app.user.pseudo }}</strong>
				</a>
				<a class="button is-light" href="{{ path('app_logout') }}">
					<i class="fa-solid fa-arrow-right-from-bracket"></i>
				</a>
			{% else %}
				<a class="button is-primary" href="#">
					<strong>Inscription</strong>
				</a>
				<a class="button is-light" href="{{ path('app_login') }}">
					Connexion
				</a>
			{% endif %}
		</div>
	</div>
</div>
{# ... #}

Controlleur

Créer un controlleur pour les routes liés à la gestion du compte utilisateur:

php bin/console make:controller
[output]
[output] Choose a name for your controller class (e.g. BravePizzaController):
 > UserController

Définir un préfixe pour les routes du controlleur et adapter la 1e route pour la page de profil:

#[Route('/profile', name: 'user_')]
class UserController extends AbstractController
{
    #[Route('', name: 'profile')]
    public function index(): Response
    {
        return $this->render('user/index.html.twig');
    }
}

Pour que les routes de ce controlleur ne soient accessibles qu'aux utilisateurs connectés, on utilisera un attribut IsGranted, qui s'applique sur la classe ou les méthodes:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
// ...

#[Route('/profile', name: 'user_')]
#[IsGranted('ROLE_USER')]
class UserController extends AbstractController

Remplacer le contenu du template /templates/user/index.html.twig:

{% extends "_template.html.twig" %}

{% block title app.user.pseudo %}

{% block content %}
    <div class="section">
        <h1 class="title">Profil de {{ app.user.pseudo }}:</h1>

        <div class="content">
            <p>
                <strong>Email</strong>: {{ app.user.email }}<br>
                <strong>Pseudo</strong>: {{ app.user.pseudo }}<br>
            </p>
        </div>
    </div>
{% endblock %}

Et enfin le lien dans le menu:

<a class="button is-primary" href="{{ path('user_profile') }}">
	<span class="icon"><i class="fa-solid fa-circle-user"></i></span>
	<strong>{{ app.user.pseudo }}</strong>
</a>

Tester l'accès à la page.

Redirection des utilisateurs non connectés

Déconnectez-vous puis essayez d'accéder à la page de profil: localhost:8000/profile
Vous devez être redirigé vers la page de connexion. Reconnectez-vous et vous serez ensuite redirigé vers la page de profil au lieu de la page d'accueil.

C'est un mécanisme automatiquement géré par Symfony qui permet de vous rediriger vers la page demandée si celle-ci nécessite un droit d'accès spécifique mais que vous n'étiez pas connecté. Vous pouvez notamment voir la partie redirection après authentification dans la méthode App\Security\LoginFormAuthenticator::onAuthenticationSuccess, il s'agit de la condition au début de la méthode:

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->urlGenerator->generate('homepage'));
}