Symfony No user token or you forgot to put your controller behind a firewall @Security

Viewed 445

I'm coming to you because i have an issue and i can't resolve it.

On my website, an user can upload pictures and videos. He can also delete them. But when he tries to delete a picture or a video, he got this error:

"No user token or you forgot to put your controller behind a firewall while using a @Security tag."

I already use @Security with other functions and it works. It doesn't work only for functions pictureDelete and videoDelete.

pictureDelete function :

/** Page de suppression d'une image
     *
     * @Route("/images/suppression/{id}/", name="delete_picture")
     * @Security("is_granted('ROLE_USER')")
     */
    public function pictureDelete(Picture $picture, Request $request): Response
    {

        if(!$this->isCsrfTokenValid('delete_picture_' . $picture->getId(), $request->query->get('csrf_token')  )){

            $this->AddFlash('error', 'Token sécurité invalide, veuillez ré-essayer.');

        } else {

            $em = $this->getDoctrine()->getManager();

            $em->remove($picture);

            $em->flush();

            //TODO: le message flash ne s'affiche pas sur la bonne page
            $this->addFlash('success', 'L\'image a été supprimée avec succès');

        }

        return $this->redirectToRoute('pictures');

    }

videoDelete function :

/** Page de suppression d'une vidéo
     *
     * @Route("/videos/suppression/{id}/", name="delete_video")
     * @Security("is_granted('ROLE_USER')")
     */
    public function videoDelete(Video $video, Request $request): Response
    {

        if(!$this->isCsrfTokenValid('delete_video_' . $video->getId(), $request->query->get('csrf_token')  )){

            $this->AddFlash('error', 'Token sécurité invalide, veuillez ré-essayer.');

        } else {

            $em = $this->getDoctrine()->getManager();

            $em->remove($video);

            $em->flush();

            //TODO: le message flash ne s'affiche pas sur la bonne page
            $this->addFlash('success', 'La vidéo a été supprimée avec succès');

        }

        return $this->redirectToRoute('videos');

    }

security.yaml :

security:
    encoders:
        App\Entity\User:
            algorithm: auto

    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    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:
            anonymous: true
            lazy: true
            provider: app_user_provider
            guard:
                authenticators:
                    - App\Security\LoginFormAuthenticator
            logout:
                path: app_logout
                # where to redirect after logout
                target: home

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

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

    role_hierarchy:
        ROLE_ADMIN:      ROLE_USER

    # 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 }

My controller (with function addPicture and addVideo) :

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\User;
use App\Entity\Picture;
use App\Form\PictureType;
use App\Entity\Video;
use App\Form\VideoType;
use \DateTime;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use App\Form\UserType;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;



class MainController extends AbstractController
{
    /** Page d'accueil
     *
     * @Route("/", name="home")
     */
    public function index(): Response
    {

        $pictureRepository = $this->getDoctrine()->getRepository(Picture::class);
        $pictureFound = $pictureRepository->LastThreePic();

        $videoRepository = $this->getDoctrine()->getRepository(Video::class);
        $videoFound = $videoRepository->LastThreeVid();

        return $this->render('main/home.html.twig', [
            'picture' => $pictureFound,
            'video' => $videoFound
        ]);
    }



    /** Page de profil
     *
     * @Route("/mon-profil", name="profil")
     * @Security("is_granted('ROLE_USER')")
     */
    public function profil(): Response
    {
        return $this->render('main/profil.html.twig');
    }



     /** Page de modification de profil
     *
     * @Route("/modifier-mon-profil/", name="edit_profil")
     * @Security("is_granted('ROLE_USER')")
     */
    public function editProfil(Request $request, UserPasswordEncoderInterface $encoder): Response
    {

        $user = $this->getUser();

        $form = $this->createForm(UserType::class, $user);

        $form->handleRequest($request);

        if($form->isSubmitted() && $form->isValid()){

            $em = $this->getDoctrine()->getManager();

            $newPassword = $form->get('plainPassword')['first']->getData();

            // Grâce au service, on génère un nouveau hash de notre nouveau mot de passe
            $hashOfNewPassword = $encoder->encodePassword($user, $newPassword);

            // On change l'ancien mot de passe hashé par le nouveau que l'on a généré juste au dessus
            $user->setPassword( $hashOfNewPassword );

            $em->flush();

            $this->addFlash('success', 'Profil modifié avec succès.');
            return $this->redirectToRoute('profil');
        }

        // Pour que la vue puisse afficher le formulaire, on doit lui envoyer le formulaire généré, avec $form->createView()
        return $this->render('main/editProfil.html.twig', [
            'editProfilForm' => $form->createView()
        ]);
    }



    /** Fonction permettant de supprimer son compte depuis la page de profil
     *
     * @Route("/delete-account", name="delete_account")
     * @Security("is_granted('ROLE_USER')")
     */
    public function deleteAccount(): Response
    {
        $user = $this->getUser();
        $this->container->get('security.token_storage')->setToken(null);

        $em = $this->getDoctrine()->getManager();
        $em->remove($user);
        $em->flush();

        $this->addFlash('success', 'Votre compte a bien été supprimé.');

        return $this->redirectToRoute('home');
    }



    /** Page des catégories d'images
     *
     * @Route("/categorie/images", name="pictures")
     */
    public function pictures(): Response
    {
        return $this->render('main/pictures.html.twig');
    }



    /** Page des catégories de vidéos
     *
     * @Route("/categorie/videos", name="videos")
     */
    public function videos(): Response
    {
        return $this->render('main/videos.html.twig');
    }



    /** Page des images favorites
     *
     * @Route("/favoris/images", name="fav_pic")
     */
    public function favPic(): Response
    {

        $pictureRepository = $this->getDoctrine()->getRepository(Picture::class);
        $picturesFound = $pictureRepository->findAll();

        return $this->render('main/favPic.html.twig', [
            'pictures' => $picturesFound
        ]);
    }



     /** Page des vidéos favorites
      *
     * @Route("/favoris/videos", name="fav_vid")
     */
    public function favVid(): Response
    {

        $videoRepository = $this->getDoctrine()->getRepository(Video::class);
        $videosFound = $videoRepository->findAll();

        return $this->render('main/favVid.html.twig', [
            'videos' => $videosFound
        ]);
    }



    /** Page d'ajout d'image en favoris
     *
     * @Route("/favoris/ajout/{id}", name="add_fav_pic")
     */
    public function addFavPic(Picture $picture): Response
    {

        if(!$picture){
            throw new NotFoundHttpException('Pas d\'image trouvée.');
        }
        $picture->addFav($this->getUser());

        $em = $this->getDoctrine()->getManager();
        $em->persist($picture);
        $em->flush();

        $this->addFlash('success', 'Image ajoutée aux favoris avec succès.');
        return $this->redirectToRoute('fav_pic');
    }



    /** Page d'ajout de vidéo en favoris
     *
     * @Route("/favoris/videos/ajout/{id}", name="add_fav_vid")
     */
    public function addFavVid(Video $video): Response
    {

        if(!$video){
            throw new NotFoundHttpException('Pas de vidéo trouvée.');
        }
        $video->addFav($this->getUser());

        $em = $this->getDoctrine()->getManager();
        $em->persist($video);
        $em->flush();

        $this->addFlash('success', 'Vidéo ajoutée aux favoris avec succès.');
        return $this->redirectToRoute('fav_vid');
    }



    /** Fonction pour supprimer une image de ses favoris
     *
     * @Route("/favoris/images/suppression/{id}", name="del_fav_pic")
     */
    public function deleteFavPic(Picture $picture): Response
    {

        if(!$picture){
            throw new NotFoundHttpException('Pas d\'image trouvée.');
        }
        $picture->removeFav($this->getUser());

        $em = $this->getDoctrine()->getManager();
        $em->persist($picture);
        $em->flush();

        $this->addFlash('success', 'Image supprimée des favoris avec succès.');
        return $this->redirectToRoute('fav_pic');
    }



    /** Fonction pour supprimer une vidéo de ses favoris
     *
     * @Route("/favoris/videos/suppression/{id}", name="del_fav_vid")
     */
    public function deleteFavVid(Video $video): Response
    {

        if(!$video){
            throw new NotFoundHttpException('Pas de vidéo trouvée.');
        }
        $video->removeFav($this->getUser());

        $em = $this->getDoctrine()->getManager();
        $em->persist($video);
        $em->flush();

        $this->addFlash('success', 'Vidéo supprimée des favoris avec succès.');
        return $this->redirectToRoute('fav_vid');
    }



    /** Page de suppression d'une image
     *
     * @Route("/images/suppression/{id}/", name="delete_picture")
     * @Security("is_granted('ROLE_USER')")
     */
    //TODO: @Security fait tout planter
    public function pictureDelete(Picture $picture, Request $request): Response
    {

        if(!$this->isCsrfTokenValid('delete_picture_' . $picture->getId(), $request->query->get('csrf_token')  )){

            $this->AddFlash('error', 'Token sécurité invalide, veuillez ré-essayer.');

        } else {

            $em = $this->getDoctrine()->getManager();

            $em->remove($picture);

            $em->flush();

            //TODO: le message flash ne s'affiche pas sur la bonne page
            $this->addFlash('success', 'L\'image a été supprimée avec succès');

        }

        return $this->redirectToRoute('pictures');

    }



    /** Page de suppression d'une vidéo
     *
     * @Route("/videos/suppression/{id}/", name="delete_video")
     * @Security("is_granted('ROLE_USER')")
     */
    //TODO: @Security fait tout planter
    public function videoDelete(Video $video, Request $request): Response
    {

        if(!$this->isCsrfTokenValid('delete_video_' . $video->getId(), $request->query->get('csrf_token')  )){

            $this->AddFlash('error', 'Token sécurité invalide, veuillez ré-essayer.');

        } else {

            $em = $this->getDoctrine()->getManager();

            $em->remove($video);

            $em->flush();

            //TODO: le message flash ne s'affiche pas sur la bonne page
            $this->addFlash('success', 'La vidéo a été supprimée avec succès');

        }

        return $this->redirectToRoute('videos');

    }



    /** Page d'ajout d'une image
     *
     * @Route("/ajouter-une-image", name="add_pic")
     * @Security("is_granted('ROLE_USER')")
     */
    public function addPicture(Request $request): Response
    {

        // Création d'un nouvel objet de la classe Article, vide pour le moment
        $newPicture = new Picture();

        // Création d'un nouveau formulaire à partir de notre formulaire ArticleType et de notre nouvel article encore vide
        $form = $this->createForm(PictureType::class, $newPicture);

        $form->handleRequest($request);

        // Si le formulaire est envoyé et sans erreur
        if($form->isSubmitted() && $form->isValid()){

            $newPicture->setPublicationDate(new DateTime());
            $newPicture->setAuthor($this->getUser());

            // Extraction de l'objet de la photo envoyée dans le formulaire
            $picture = $form->get('image')->getData();

            // Création d'un nouveau nom aléatoire pour la photo avec son extension (récupérée via la méthode guessExtension() )
            $newFileName = md5(time() . rand() . uniqid() ) . '.' . $picture->guessExtension();

            $em = $this->getDoctrine()->getManager();

            $newPicture->setImage($newFileName);

            $em->persist($newPicture);

            $em->flush();

            // Déplacement de la photo dans le dossier que l'on avait paramétré dans le fichier services.yaml, avec le nouveau nom qu'on lui a généré
            $picture->move(
                $this->getParameter('app.user.pictures.directory'),     // Emplacement de sauvegarde du fichier
                $newFileName    // Nouveau nom du fichier
            );

            // Petit message de succès
            $this->addFlash('success', 'Image envoyée avec succès !');

            // Redirection sur une autre page du site
            return $this->redirectToRoute('home');

        }

        return $this->render('main/addPicture.html.twig', [
            'addPicForm' => $form->createView()
        ]);
    }

    /** Page d'ajout d'une vidéo
     *
     * @Route("/ajouter-une-video", name="add_vid")
     * @Security("is_granted('ROLE_USER')")
     */
    public function addVideo(Request $request): Response
    {

        // Création d'un nouvel objet de la classe Article, vide pour le moment
        $newVideo = new Video();

        // Création d'un nouveau formulaire à partir de notre formulaire ArticleType et de notre nouvel article encore vide
        $form = $this->createForm(VideoType::class, $newVideo);

        $form->handleRequest($request);

        // Si le formulaire est envoyé et sans erreur
        if($form->isSubmitted() && $form->isValid()){

            $newVideo->setPublicationDate(new DateTime());
            $newVideo->setAuthor($this->getUser());

            // Extraction de l'objet de la photo envoyée dans le formulaire
            $video = $form->get('vid')->getData();

            // Création d'un nouveau nom aléatoire pour la photo avec son extension (récupérée via la méthode guessExtension() )
            $newFileName = md5(time() . rand() . uniqid() ) . '.' . $video->guessExtension();

            $em = $this->getDoctrine()->getManager();

            $newVideo->setVid($newFileName);

            $em->persist($newVideo);

            $em->flush();

            // Déplacement de la photo dans le dossier que l'on avait paramétré dans le fichier services.yaml, avec le nouveau nom qu'on lui a généré
            $video->move(
                $this->getParameter('app.user.videos.directory'),     // Emplacement de sauvegarde du fichier
                $newFileName    // Nouveau nom du fichier
            );

            // Petit message de succès
            $this->addFlash('success', 'Vidéo envoyée avec succès !');

            // Redirection sur une autre page du site
            return $this->redirectToRoute('home');

        }


        return $this->render('main/addVideo.html.twig', [
            'addVidForm' => $form->createView()
        ]);
    }








}

0 Answers
Related