'How to make a user can only delete or modify thier own Post using Symfony

How can I make a user can only delete or modify their own post.

I can successfully add a post with the user id who's logging and I can delete or modify a post but i want to make sure that the post can be modified or deleted by the specific user who add it.

Here is my function modify post in the controller

public function edit(Request $request, Posts $post, EntityManagerInterface $entityManager, $id): Response
    {
        // $post= $this->getDoctrine()->getRepository(Posts::class)->find($id);
        // $resultat=$this->getUser()->getPosts();
        // $resultat->contains($post);

        // if (!($resultat ==true))
        // {
        //     return $this->json(['code' => 403, 'error' => 'Vous devez être connecté !'], 403);
        // }

        $user = $this->getUser();
        if ($post->isPostedByUser($user))
        {
            return $this->json(['code' => 403, 'error' => 'c est votre post  !'], 403);
        }


        $form = $this->createForm(PostType::class, $post);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $entityManager->flush();

            return $this->redirectToRoute('posts_index', [], Response::HTTP_SEE_OTHER);
        }

        return $this->render('blog/edit.html.twig', [
            'post' => $post,
            'postform' => $form->createView(),
        ]);
    }

And this is the function I use to see if this post is posted by the current user in the entity Posts.php

    public function isPostedByUser(User $user): bool
    {
        
            if ($this->getUser()->getPosts() === $user) {
                return true;
            }
        

        return false;
    }

Is there another way?



Solution 1:[1]

There are 2 ways to do this, the first is to do the check directly in the method, the second is to use the symfony tools, namely Voter.

1.Way of checking in a method

public function edit(Request $request, Posts $post, EntityManagerInterface $entityManager, $id): Response
{
 if($post->getUser() != $this->getUser()){  // $post->getUser() or another method that returns the user of your post
 return $this->json(['code' => 403, 'error' => 'c est votre post  !'], 403);
 }

 // some you action

}

2.Variant using symfony Voter

Create PostVoter in Security folder

// src/Security/PostVoter.php

class PostVoter extends Voter
{

    const EDIT = 'edit';
    protected function supports(string $attribute, $subject): bool
    {
        if (!$subject instanceof Posts) {
            return false;
        }
        return true;
    }

    protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
    {
        $user = $token->getUser();
        if (!$user instanceof User) {
            return false;
        }
        /** @var Posts $post */
        $post = $subject;
        switch ($attribute) {
            case self::EDIT:
                return $this->canEdit($post, $user);
        }
        throw new \LogicException('This code should not be reached!');
    }

    private function canEdit(Posts $post, User $user): bool
    {
        return $user === $post->getUser(); // $post->getUser() or another method that returns the user of your post
    }
}

Add to the top of your edit method a check against the newly created PostVoter

public function edit(Request $request, Posts $post, EntityManagerInterface $entityManager, $id): Response
{
    $this->denyAccessUnlessGranted('edit', $post); // here we connect the check PostVoter 
  
    // some you action
}

If you chose option 2, then here is more information from the official documentation

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1