Files
chill-bundles/src/Bundle/ChillCalendarBundle/Security/Voter/CalendarVoter.php

125 lines
4.2 KiB
PHP

<?php
/**
* Chill is a software for social workers.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\CalendarBundle\Security\Voter;
use Chill\CalendarBundle\Entity\Calendar;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
class CalendarVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
final public const CREATE = 'CHILL_CALENDAR_CALENDAR_CREATE';
final public const DELETE = 'CHILL_CALENDAR_CALENDAR_DELETE';
final public const EDIT = 'CHILL_CALENDAR_CALENDAR_EDIT';
final public const SEE = 'CHILL_CALENDAR_CALENDAR_SEE';
private readonly VoterHelperInterface $voterHelper;
public function __construct(
private readonly Security $security,
VoterHelperFactoryInterface $voterHelperFactory,
) {
$this->voterHelper = $voterHelperFactory
->generate(self::class)
->addCheckFor(AccompanyingPeriod::class, [self::SEE, self::CREATE])
->addCheckFor(Person::class, [self::SEE, self::CREATE])
->addCheckFor(Calendar::class, [self::SEE, self::CREATE, self::EDIT, self::DELETE])
->build();
}
public function getRoles(): array
{
return [
self::CREATE,
self::DELETE,
self::EDIT,
self::SEE,
];
}
public function getRolesWithHierarchy(): array
{
return ['Calendar' => $this->getRoles()];
}
public function getRolesWithoutScope(): array
{
return [
self::CREATE,
self::DELETE,
self::EDIT,
self::SEE,
];
}
protected function supports($attribute, $subject): bool
{
return $this->voterHelper->supports($attribute, $subject);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
if ($subject instanceof AccompanyingPeriod) {
switch ($attribute) {
case self::SEE:
case self::CREATE:
if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) {
return false;
}
// we first check here that the user has read access to the period
if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject)) {
return false;
}
// There is no scope on Calendar, but there are some on accompanying period
// so, to ignore AccompanyingPeriod's scopes, we create a blank Calendar
// linked with an accompanying period.
return $this->voterHelper->voteOnAttribute($attribute, (new Calendar())->setAccompanyingPeriod($subject), $token);
}
} elseif ($subject instanceof Person) {
switch ($attribute) {
case self::SEE:
case self::CREATE:
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
}
} elseif ($subject instanceof Calendar) {
switch ($attribute) {
case self::SEE:
case self::EDIT:
case self::CREATE:
case self::DELETE:
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
}
}
throw new \LogicException('attribute or not implemented');
}
}