Update calendar authorization checks

The CalendarDocVoter now also supports Calendar instances, not only CalendarDoc instances. This allows refining permissions checks based on the actual instance type. In addition, the ChillCalendarBundle's view has been updated to correctly use permissions when displaying action buttons. Obsolete TODO comments are also removed.
This commit is contained in:
Julien Fastré 2024-04-10 21:15:49 +02:00
parent ca398195b0
commit b2eb2b0968
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
2 changed files with 21 additions and 18 deletions

View File

@ -151,7 +151,7 @@
<div class="item-row separator">
<ul class="record_actions">
{% if is_granted('CHILL_CALENDAR_CALENDAR_SEE', calendar) %}
{% if is_granted('CHILL_CALENDAR_DOC_EDIT', calendar) %}
{% if templates|length == 0 %}
<li>
<a class="btn btn-create"
@ -213,24 +213,18 @@
class="btn btn-show "></a>
</li>
{% endif %}
{# TOOD
{% if is_granted('CHILL_ACTIVITY_UPDATE', calendar) %}
#}
{% if is_granted('CHILL_CALENDAR_CALENDAR_EDIT', calendar) %}
<li>
<a href="{{ chill_path_add_return_path('chill_calendar_calendar_edit', { 'id': calendar.id }) }}"
class="btn btn-update "></a>
</li>
{# TOOD
{% endif %}
{% if is_granted('CHILL_ACTIVITY_DELETE', calendar) %}
#}
{% if is_granted('CHILL_CALENDAR_CALENDAR_DELETE', calendar) %}
<li>
<a href="{{ chill_path_add_return_path('chill_calendar_calendar_delete', { 'id': calendar.id } ) }}"
class="btn btn-delete "></a>
</li>
{#
{% endif %}
#}
</ul>
</div>

View File

@ -11,9 +11,11 @@ declare(strict_types=1);
namespace Chill\CalendarBundle\Security\Voter;
use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Entity\CalendarDoc;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Exception\LogicException;
use Symfony\Component\Security\Core\Security;
class CalendarDocVoter extends Voter
@ -31,18 +33,25 @@ class CalendarDocVoter extends Voter
protected function supports($attribute, $subject): bool
{
return \in_array($attribute, self::ALL, true) && $subject instanceof CalendarDoc;
return \in_array($attribute, self::ALL, true) && ($subject instanceof CalendarDoc || $subject instanceof Calendar);
}
/**
* @param CalendarDoc $subject
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
return match ($attribute) {
self::EDIT => $this->security->isGranted(CalendarVoter::EDIT, $subject->getCalendar()),
self::SEE => $this->security->isGranted(CalendarVoter::SEE, $subject->getCalendar()),
default => throw new \UnexpectedValueException('Attribute not supported: '.$attribute),
};
if ($subject instanceof Calendar) {
return match ($attribute) {
self::EDIT => $this->security->isGranted(CalendarVoter::EDIT, $subject),
self::SEE => $this->security->isGranted(CalendarVoter::SEE, $subject),
default => throw new LogicException('attribute not supported for this Voter'),
};
} elseif ($subject instanceof CalendarDoc) {
return match ($attribute) {
self::EDIT => $this->security->isGranted(CalendarVoter::EDIT, $subject->getCalendar()),
self::SEE => $this->security->isGranted(CalendarVoter::SEE, $subject->getCalendar()),
default => throw new \UnexpectedValueException('Attribute not supported: '.$attribute),
};
}
throw new LogicException('Subject not supported for this Voter');
}
}