Messing with voters
This commit is contained in:
parent
b991ae8d00
commit
b7381eafa3
@ -47,17 +47,21 @@ if (! location.pathname.includes('login')) {
|
|||||||
const userMenu = document.querySelector('.dropdown-trigger');
|
const userMenu = document.querySelector('.dropdown-trigger');
|
||||||
const userCaret = document.querySelector('#user-caret');
|
const userCaret = document.querySelector('#user-caret');
|
||||||
|
|
||||||
document.querySelector('#for-vocabs').addEventListener('click', function () {
|
const forVocabs = document.querySelector('#for-vocabs')
|
||||||
vocabs.classList.toggle('is-hidden');
|
|
||||||
|
if (forVocabs) {
|
||||||
|
forVocabs.addEventListener('click', function () {
|
||||||
|
vocabs.classList.toggle('is-hidden');
|
||||||
|
|
||||||
if (this.firstElementChild.classList.contains('fa-angle-right')) {
|
if (this.firstElementChild.classList.contains('fa-angle-right')) {
|
||||||
this.firstElementChild.classList.remove('fa-angle-right');
|
this.firstElementChild.classList.remove('fa-angle-right');
|
||||||
this.firstElementChild.classList.add('fa-angle-down');
|
this.firstElementChild.classList.add('fa-angle-down');
|
||||||
} else {
|
} else {
|
||||||
this.firstElementChild.classList.remove('fa-angle-down');
|
this.firstElementChild.classList.remove('fa-angle-down');
|
||||||
this.firstElementChild.classList.add('fa-angle-right');
|
this.firstElementChild.classList.add('fa-angle-right');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
userMenu.addEventListener('click', function () {
|
userMenu.addEventListener('click', function () {
|
||||||
document.querySelector('.dropdown').classList.toggle('is-active');
|
document.querySelector('.dropdown').classList.toggle('is-active');
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\VocabFuncContext;
|
use App\Entity\VocabFuncContext;
|
||||||
use App\Repository\VocabFuncContextRepository;
|
use App\Security\Voter\VocabVoter;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
class VocabFuncContextController extends AbstractController
|
class VocabFuncContextController extends AbstractController
|
||||||
{
|
{
|
||||||
@ -17,10 +19,8 @@ class VocabFuncContextController extends AbstractController
|
|||||||
{
|
{
|
||||||
$roles = $this->getUser()->getRoles();
|
$roles = $this->getUser()->getRoles();
|
||||||
|
|
||||||
if (! in_array('ROLE_REVISOR', $roles)
|
if (in_array('ROLE_READER', $roles)) {
|
||||||
&& ! in_array('ROLE_ADMIN', $roles)
|
$this->addFlash('warning', 'Only editors, revisors and administrators can view vocabularies');
|
||||||
) {
|
|
||||||
$this->addFlash('warning', 'Only revisors and administrators can edit vocabularies');
|
|
||||||
return $this->redirectToRoute('app_home');
|
return $this->redirectToRoute('app_home');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,9 +35,16 @@ class VocabFuncContextController extends AbstractController
|
|||||||
#[Route('/vocabs/functional_context/add', name: 'app_vocab_func_context_add')]
|
#[Route('/vocabs/functional_context/add', name: 'app_vocab_func_context_add')]
|
||||||
public function addTerm(Request $request, EntityManagerInterface $em): Response
|
public function addTerm(Request $request, EntityManagerInterface $em): Response
|
||||||
{
|
{
|
||||||
$term = $request->getPayload()->get('_term');
|
|
||||||
|
|
||||||
$vocab = new VocabFuncContext;
|
$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);
|
$vocab->setTerm($term);
|
||||||
$em->persist($vocab);
|
$em->persist($vocab);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
@ -7,7 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
|
|
||||||
#[ORM\Entity()]
|
#[ORM\Entity()]
|
||||||
#[ORM\Table(name: 'lis_contesto_funz')]
|
#[ORM\Table(name: 'lis_contesto_funz')]
|
||||||
class VocabFuncContext
|
class VocabFuncContext implements \App\VocabInterface
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
#[ORM\GeneratedValue]
|
#[ORM\GeneratedValue]
|
||||||
|
49
src/Security/Voter/VocabVoter.php
Normal file
49
src/Security/Voter/VocabVoter.php
Normal 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
7
src/VocabInterface.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
interface VocabInterface
|
||||||
|
{
|
||||||
|
}
|
@ -33,7 +33,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="pl-2">Profile</span>
|
<span class="pl-2">Profile</span>
|
||||||
</a>
|
</a>
|
||||||
{% if 'ROLE_ADMIN' in app.user.roles %}
|
{% if is_granted('ROLE_ADMIN') %}
|
||||||
<a href="/admin" class="dropdown-item">
|
<a href="/admin" class="dropdown-item">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<i class="fa fa-cogs"></i>
|
<i class="fa fa-cogs"></i>
|
||||||
@ -57,6 +57,7 @@
|
|||||||
<div class="columns mb-0">
|
<div class="columns mb-0">
|
||||||
<div class="column is-one-fifth arcoa-menu mb-0">
|
<div class="column is-one-fifth arcoa-menu mb-0">
|
||||||
<aside class="menu pl-4">
|
<aside class="menu pl-4">
|
||||||
|
{% if 'ROLE_READER' not in app.user.roles %}
|
||||||
<p class="menu-label has-text-white mt-3 pt-5 pl-5 is-size-6">
|
<p class="menu-label has-text-white mt-3 pt-5 pl-5 is-size-6">
|
||||||
Vocabularies
|
Vocabularies
|
||||||
<span class="icon is-clickable pl-4" id="for-vocabs">
|
<span class="icon is-clickable pl-4" id="for-vocabs">
|
||||||
@ -201,6 +202,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
<p class="menu-label has-text-white mt-3 pt-5 pl-5 is-size-6">
|
<p class="menu-label has-text-white mt-3 pt-5 pl-5 is-size-6">
|
||||||
Records
|
Records
|
||||||
<span class="icon is-clickable pl-4" id="for-records">
|
<span class="icon is-clickable pl-4" id="for-records">
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
{% block title %}Home | ArCOA{% endblock %}
|
{% block title %}Home | ArCOA{% endblock %}
|
||||||
|
|
||||||
{% block rightpanel %}
|
{% block rightpanel %}
|
||||||
|
{% for message in app.flashes('warning') %}
|
||||||
|
<article class="message is-warning mb-6 mt-3 ml-auto mr-auto" style="max-width: 35vw">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>Warning</p>
|
||||||
|
<button class="delete" aria-label="delete"></button>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">{{ message }}</div>
|
||||||
|
</article>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<div class="has-text-centered">
|
<div class="has-text-centered">
|
||||||
<img width="200px" src="{{ asset('img/Logo-ArCOA-def.png') }}" />
|
<img width="200px" src="{{ asset('img/Logo-ArCOA-def.png') }}" />
|
||||||
</div>
|
</div>
|
||||||
@ -11,15 +21,6 @@
|
|||||||
<h2 class="is-size-3 mb-3 has-text-centered">Archivi e Collezioni dell'Oriente Antico</h2>
|
<h2 class="is-size-3 mb-3 has-text-centered">Archivi e Collezioni dell'Oriente Antico</h2>
|
||||||
<h2 class="is-size-3 mb-6 has-text-centered">Archives and Collections of the Ancient Near East</h2>
|
<h2 class="is-size-3 mb-6 has-text-centered">Archives and Collections of the Ancient Near East</h2>
|
||||||
|
|
||||||
{% for message in app.flashes('warning') %}
|
|
||||||
<article class="message is-warning" style="max-width: 35vw; margin: 0 auto;">
|
|
||||||
<div class="message-header">
|
|
||||||
<p>Warning</p>
|
|
||||||
<button class="delete" aria-label="delete"></button>
|
|
||||||
</div>
|
|
||||||
<div class="message-body">{{ message }}</div>
|
|
||||||
</article>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<div class="columns" style="max-width: 35vw; margin: 0 auto;">
|
<div class="columns" style="max-width: 35vw; margin: 0 auto;">
|
||||||
<div class="column mt-6 mb-5">
|
<div class="column mt-6 mb-5">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
{% block rightpanel %}
|
{% block rightpanel %}
|
||||||
<div class="container" style="max-width: 50vw">
|
<div class="container" style="max-width: 50vw">
|
||||||
<h1 class="is-size-1 mt-0 has-text-centered">Edit vocabulary</h1>
|
<h1 class="is-size-1 mt-0 has-text-centered">Vocabulary</h1>
|
||||||
<h2 class="is-size-3 mt-4 has-text-centered">Functional context</h2>
|
<h2 class="is-size-3 mt-4 has-text-centered">Functional context</h2>
|
||||||
|
|
||||||
<div class="container mt-6">
|
<div class="container mt-6">
|
||||||
@ -18,6 +18,7 @@
|
|||||||
{{ message }}
|
{{ message }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}
|
||||||
<form method="post" action="{{ path('app_vocab_func_context_add') }}">
|
<form method="post" action="{{ path('app_vocab_func_context_add') }}">
|
||||||
<label class="label">Add new term</label>
|
<label class="label">Add new term</label>
|
||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
@ -34,15 +35,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<h3 class="mt-6 mb-5 is-size-5"><strong>Terms in vocabulary</strong></h3>
|
<h3 class="mt-6 mb-5 is-size-5"><strong>Terms in vocabulary</strong></h3>
|
||||||
<table class="table is-fullwidth" id="terms">
|
<table class="table is-fullwidth" id="terms">
|
||||||
<tr><th>Term</th><th>Actions</th></tr>
|
<tr><th>Term</th>{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}<th>Actions</th>{% endif %}</tr>
|
||||||
{% for term in terms %}
|
{% for term in terms %}
|
||||||
<tr data-row-id="{{ term.id }}">
|
<tr data-row-id="{{ term.id }}">
|
||||||
<td>
|
<td>
|
||||||
<input class="input" type="text" value="{{ term.term }}" disabled data-term-id="{{ term.id }}" />
|
<input class="input" type="text" value="{{ term.term }}" disabled data-term-id="{{ term.id }}" />
|
||||||
</td>
|
</td>
|
||||||
|
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}
|
||||||
<td>
|
<td>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button class="button is-link" data-id-edit="{{ term.id }}">
|
<button class="button is-link" data-id-edit="{{ term.id }}">
|
||||||
@ -59,6 +62,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
Loading…
Reference in New Issue
Block a user