Просмотр исходного кода

Ajout du voter pour le droit d'éditer les articles

Sangfroid 5 месяцев назад
Родитель
Сommit
7feccc997c

+ 3 - 0
src/Controller/ArticleController.php

@@ -45,6 +45,7 @@ final class ArticleController extends AbstractController
     }
 
     #[Route('/{id}', name: 'app_article_show', methods: ['GET'])]
+    #[IsGranted('view', 'article')]
     public function show(Article $article): Response
     {
         return $this->render('article/show.html.twig', [
@@ -53,6 +54,7 @@ final class ArticleController extends AbstractController
     }
 
     #[Route('/{id}/edit', name: 'app_article_edit', methods: ['GET', 'POST'])]
+    #[IsGranted('edit', 'article')]
     public function edit(Request $request, Article $article, EntityManagerInterface $entityManager): Response
     {
         $form = $this->createForm(ArticleType::class, $article);
@@ -71,6 +73,7 @@ final class ArticleController extends AbstractController
     }
 
     #[Route('/{id}', name: 'app_article_delete', methods: ['POST'])]
+    #[IsGranted('edit', 'article')]
     public function delete(Request $request, Article $article, EntityManagerInterface $entityManager): Response
     {
         if ($this->isCsrfTokenValid('delete'.$article->getId(), $request->getPayload()->getString('_token'))) {

+ 58 - 0
src/Security/Voter/ArticleVoter.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace App\Security\Voter;
+
+use App\Entity\Article;
+use App\Entity\User;
+use Symfony\Bundle\SecurityBundle\Security;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authorization\Voter\Voter;
+
+final class ArticleVoter extends Voter
+{
+    public const EDIT = 'edit';
+    public const VIEW = 'view';
+
+    public function __construct(
+        private readonly Security $security
+    )
+    {
+        
+    }
+
+    protected function supports(string $attribute, mixed $subject): bool
+    {
+        // replace with your own logic
+        // https://symfony.com/doc/current/security/voters.html
+        return in_array($attribute, [self::EDIT, self::VIEW])
+            && $subject instanceof \App\Entity\Article;
+    }
+
+    protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
+    {
+        $user = $token->getUser();
+
+        // if the user is anonymous, do not grant access
+        if (!$user instanceof User) {
+            return false;
+        }
+
+        $article = $subject;
+
+        return match($attribute) {
+            self::VIEW => $this->canView($article, $user),
+            self::EDIT => $this->canEdit($article, $user),
+            default => throw new \LogicException('This code should not be reached!')
+        };
+    }
+
+    private function canView(Article $article, User $user): bool
+    {
+        return $this->canEdit($article, $user);
+    }
+
+    private function canEdit(Article $article, User $user): bool
+    {
+        return $user === $article->getAuthor() || $this->security->isGranted('ROLE_ADMIN');
+    }
+}

+ 7 - 0
templates/article/index.html.twig

@@ -16,15 +16,22 @@
         </thead>
         <tbody>
         {% for article in articles %}
+            {% if is_granted('edit', article) %}
             <tr>
                 <td>{{ article.id }}</td>
                 <td>{{ article.title }}</td>
                 <td>{{ article.publicationDate ? article.publicationDate|date('Y-m-d H:i:s') : '' }}</td>
                 <td>
+                    {% if is_granted('view', article) %}
                     <a href="{{ path('app_article_show', {'id': article.id}) }}">show</a>
+                    {% endif %}
+
+                    {% if is_granted('edit', article) %}
                     <a href="{{ path('app_article_edit', {'id': article.id}) }}">edit</a>
+                    {% endif %}
                 </td>
             </tr>
+            {% endif %}
         {% else %}
             <tr>
                 <td colspan="4">no records found</td>