Messing with voters

This commit is contained in:
2024-10-30 17:44:47 +01:00
parent b991ae8d00
commit b7381eafa3
8 changed files with 104 additions and 30 deletions

View File

@@ -3,12 +3,14 @@
namespace App\Controller;
use App\Entity\VocabFuncContext;
use App\Repository\VocabFuncContextRepository;
use App\Security\Voter\VocabVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class VocabFuncContextController extends AbstractController
{
@@ -17,10 +19,8 @@ class VocabFuncContextController extends AbstractController
{
$roles = $this->getUser()->getRoles();
if (! in_array('ROLE_REVISOR', $roles)
&& ! in_array('ROLE_ADMIN', $roles)
) {
$this->addFlash('warning', 'Only revisors and administrators can edit vocabularies');
if (in_array('ROLE_READER', $roles)) {
$this->addFlash('warning', 'Only editors, revisors and administrators can view vocabularies');
return $this->redirectToRoute('app_home');
}
@@ -35,9 +35,16 @@ class VocabFuncContextController extends AbstractController
#[Route('/vocabs/functional_context/add', name: 'app_vocab_func_context_add')]
public function addTerm(Request $request, EntityManagerInterface $em): Response
{
$term = $request->getPayload()->get('_term');
$vocab = new VocabFuncContext;
try {
$this->denyAccessUnlessGranted(VocabVoter::EDIT, $vocab);
}
catch (AccessDeniedException) {
$this->addFlash('warning', 'Only revisors and administrators can edit vocabularies');
return $this->redirectToRoute('app_home');
}
$term = $request->getPayload()->get('_term');
$vocab->setTerm($term);
$em->persist($vocab);
$em->flush();

View File

@@ -7,7 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity()]
#[ORM\Table(name: 'lis_contesto_funz')]
class VocabFuncContext
class VocabFuncContext implements \App\VocabInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]

View File

@@ -0,0 +1,49 @@
<?php
namespace App\Security\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;
final class VocabVoter extends Voter
{
public const EDIT = 'VOCAB_EDIT';
public const DELETE = 'VOCAB_DELETE';
public const VIEW = 'VOCAB_VIEW';
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, self::DELETE])
&& $subject instanceof \App\VocabInterface;
}
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 UserInterface) {
return false;
}
$roles = $user->getRoles();
// TODO: Better way to check roles?
switch ($attribute) {
case self::EDIT:
case self::DELETE:
return in_array('ROLE_ADMIN', $roles)
|| in_array('ROLE_REVISOR', $roles);
break;
case self::VIEW:
return ! in_array('ROLE_READER', $roles);
break;
}
return false;
}
}

7
src/VocabInterface.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
namespace App;
interface VocabInterface
{
}