diff --git a/assets/app.js b/assets/app.js index cbcfb63..0706665 100644 --- a/assets/app.js +++ b/assets/app.js @@ -47,17 +47,21 @@ if (! location.pathname.includes('login')) { const userMenu = document.querySelector('.dropdown-trigger'); const userCaret = document.querySelector('#user-caret'); - document.querySelector('#for-vocabs').addEventListener('click', function () { - vocabs.classList.toggle('is-hidden'); + const forVocabs = document.querySelector('#for-vocabs') + + if (forVocabs) { + forVocabs.addEventListener('click', function () { + vocabs.classList.toggle('is-hidden'); - if (this.firstElementChild.classList.contains('fa-angle-right')) { - this.firstElementChild.classList.remove('fa-angle-right'); - this.firstElementChild.classList.add('fa-angle-down'); - } else { - this.firstElementChild.classList.remove('fa-angle-down'); - this.firstElementChild.classList.add('fa-angle-right'); - } - }); + if (this.firstElementChild.classList.contains('fa-angle-right')) { + this.firstElementChild.classList.remove('fa-angle-right'); + this.firstElementChild.classList.add('fa-angle-down'); + } else { + this.firstElementChild.classList.remove('fa-angle-down'); + this.firstElementChild.classList.add('fa-angle-right'); + } + }); + } userMenu.addEventListener('click', function () { document.querySelector('.dropdown').classList.toggle('is-active'); diff --git a/src/Controller/VocabFuncContextController.php b/src/Controller/VocabFuncContextController.php index cde3520..b323c2c 100644 --- a/src/Controller/VocabFuncContextController.php +++ b/src/Controller/VocabFuncContextController.php @@ -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(); diff --git a/src/Entity/VocabFuncContext.php b/src/Entity/VocabFuncContext.php index 710809f..2baf29a 100644 --- a/src/Entity/VocabFuncContext.php +++ b/src/Entity/VocabFuncContext.php @@ -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] diff --git a/src/Security/Voter/VocabVoter.php b/src/Security/Voter/VocabVoter.php new file mode 100644 index 0000000..3fa3537 --- /dev/null +++ b/src/Security/Voter/VocabVoter.php @@ -0,0 +1,49 @@ +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; + } +} diff --git a/src/VocabInterface.php b/src/VocabInterface.php new file mode 100644 index 0000000..6f0782c --- /dev/null +++ b/src/VocabInterface.php @@ -0,0 +1,7 @@ + Profile - {% if 'ROLE_ADMIN' in app.user.roles %} + {% if is_granted('ROLE_ADMIN') %} @@ -57,6 +57,7 @@