Refactor authorization for AccompanyingPeriodWorkEvaluationDocuments

The AccompanyingPeriodWorkEvaluationStoredObjectVoter has been updated to use the AccompanyingPeriodWorkEvaluationDocument-related classes instead of the AccompanyingPeriodWork classes. Additionally, a new voters class, AccompanyingPeriodWorkEvaluationDocumentVoter has been created. Changes are also made in the repository to find the associated entity in the AccompanyingPeriodWorkEvaluationDocument repository instead of the AccompanyingPeriodWork repository.
This commit is contained in:
Julien Fastré 2024-07-15 17:53:06 +02:00
parent 7d0f9175be
commit 31f842471a
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
5 changed files with 40 additions and 27 deletions

View File

@ -14,15 +14,15 @@ namespace Chill\DocStoreBundle\Security\Authorization\StoredObjectVoters;
use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface;
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
use Chill\DocStoreBundle\Service\WorkflowDocumentService; use Chill\DocStoreBundle\Service\WorkflowDocumentService;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocumentRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationDocumentVoter;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
class AccompanyingPeriodWorkEvaluationStoredObjectVoter extends AbstractStoredObjectVoter class AccompanyingPeriodWorkEvaluationDocumentStoredObjectVoter extends AbstractStoredObjectVoter
{ {
public function __construct( public function __construct(
private readonly AccompanyingPeriodWorkRepository $repository, private readonly AccompanyingPeriodWorkEvaluationDocumentRepository $repository,
Security $security, Security $security,
WorkflowDocumentService $workflowDocumentService WorkflowDocumentService $workflowDocumentService
) { ) {
@ -36,14 +36,14 @@ class AccompanyingPeriodWorkEvaluationStoredObjectVoter extends AbstractStoredOb
protected function getClass(): string protected function getClass(): string
{ {
return AccompanyingPeriodWork::class; return AccompanyingPeriodWorkEvaluationDocument::class;
} }
protected function attributeToRole(StoredObjectRoleEnum $attribute): string protected function attributeToRole(StoredObjectRoleEnum $attribute): string
{ {
return match ($attribute) { return match ($attribute) {
StoredObjectRoleEnum::SEE => AccompanyingPeriodWorkVoter::SEE, StoredObjectRoleEnum::SEE => AccompanyingPeriodWorkEvaluationDocumentVoter::SEE,
StoredObjectRoleEnum::EDIT => AccompanyingPeriodWorkVoter::UPDATE, StoredObjectRoleEnum::EDIT => AccompanyingPeriodWorkEvaluationDocumentVoter::SEE_AND_EDIT,
}; };
} }

View File

@ -11,14 +11,18 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Repository\AccompanyingPeriod; namespace Chill\PersonBundle\Repository\AccompanyingPeriod;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\Persistence\ObjectRepository; use Doctrine\Persistence\ObjectRepository;
class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectRepository readonly class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectRepository, AssociatedEntityToStoredObjectInterface
{ {
private readonly EntityRepository $repository; private EntityRepository $repository;
public function __construct(EntityManagerInterface $em) public function __construct(EntityManagerInterface $em)
{ {
@ -58,4 +62,18 @@ class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectReposi
{ {
return AccompanyingPeriodWorkEvaluationDocument::class; return AccompanyingPeriodWorkEvaluationDocument::class;
} }
/**
* @throws NonUniqueResultException
*/
public function findAssociatedEntityToStoredObject(StoredObject $storedObject): ?AccompanyingPeriodWorkEvaluationDocument
{
$qb = $this->repository->createQueryBuilder('acpwed');
$query = $qb
->where('acpwed.storedObject = :storedObject')
->setParameter('storedObject', $storedObject)
->getQuery();
return $query->getOneOrNullResult();
}
} }

View File

@ -11,8 +11,6 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Repository\AccompanyingPeriod; namespace Chill\PersonBundle\Repository\AccompanyingPeriod;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
@ -24,7 +22,7 @@ use Doctrine\ORM\Query\ResultSetMappingBuilder;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ObjectRepository; use Doctrine\Persistence\ObjectRepository;
final readonly class AccompanyingPeriodWorkRepository implements ObjectRepository, AssociatedEntityToStoredObjectInterface final readonly class AccompanyingPeriodWorkRepository implements ObjectRepository
{ {
private EntityRepository $repository; private EntityRepository $repository;
@ -253,17 +251,4 @@ final readonly class AccompanyingPeriodWorkRepository implements ObjectRepositor
return $qb; return $qb;
} }
public function findAssociatedEntityToStoredObject(StoredObject $storedObject): ?AccompanyingPeriodWork
{
$qb = $this->repository->createQueryBuilder('acpw');
$query = $qb
->join('acpw.accompanyingPeriodWorkEvaluations', 'acpwe')
->join('acpwe.documents', 'acpwed')
->where('acpwed.storedObject = :storedObject')
->setParameter('storedObject', $storedObject)
->getQuery();
return $query->getOneOrNullResult();
}
} }

View File

@ -24,13 +24,14 @@ use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter
{ {
final public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_DOCUMENT_SHOW'; final public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_DOCUMENT_SHOW';
final public const SEE_AND_EDIT = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_DOCUMENT_EDIT';
public function __construct(private readonly AccessDecisionManagerInterface $accessDecisionManager) {} public function __construct(private readonly AccessDecisionManagerInterface $accessDecisionManager) {}
public function supports($attribute, $subject): bool public function supports($attribute, $subject): bool
{ {
return $subject instanceof AccompanyingPeriodWorkEvaluationDocument return $subject instanceof AccompanyingPeriodWorkEvaluationDocument
&& self::SEE === $attribute; && (self::SEE === $attribute || self::SEE_AND_EDIT === $attribute);
} }
/** /**
@ -47,6 +48,11 @@ class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter
[AccompanyingPeriodWorkEvaluationVoter::SEE], [AccompanyingPeriodWorkEvaluationVoter::SEE],
$subject->getAccompanyingPeriodWorkEvaluation() $subject->getAccompanyingPeriodWorkEvaluation()
), ),
self::SEE_AND_EDIT => $this->accessDecisionManager->decide(
$token,
[AccompanyingPeriodWorkEvaluationVoter::SEE_AND_EDIT],
$subject->getAccompanyingPeriodWorkEvaluation()
),
default => throw new \UnexpectedValueException("The attribute {$attribute} is not supported"), default => throw new \UnexpectedValueException("The attribute {$attribute} is not supported"),
}; };
} }

View File

@ -21,11 +21,14 @@ class AccompanyingPeriodWorkEvaluationVoter extends Voter implements ChillVoterI
{ {
final public const ALL = [ final public const ALL = [
self::SEE, self::SEE,
self::SEE_AND_EDIT,
self::STATS, self::STATS,
]; ];
final public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_SHOW'; final public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_SHOW';
final public const SEE_AND_EDIT = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_EDIT';
final public const STATS = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_STATS'; final public const STATS = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_STATS';
public function __construct(private readonly Security $security) {} public function __construct(private readonly Security $security) {}
@ -45,6 +48,7 @@ class AccompanyingPeriodWorkEvaluationVoter extends Voter implements ChillVoterI
return match ($attribute) { return match ($attribute) {
self::STATS => $this->security->isGranted(AccompanyingPeriodVoter::STATS, $subject), self::STATS => $this->security->isGranted(AccompanyingPeriodVoter::STATS, $subject),
self::SEE => $this->security->isGranted(AccompanyingPeriodWorkVoter::SEE, $subject->getAccompanyingPeriodWork()), self::SEE => $this->security->isGranted(AccompanyingPeriodWorkVoter::SEE, $subject->getAccompanyingPeriodWork()),
self::SEE_AND_EDIT => $this->security->isGranted(AccompanyingPeriodWorkVoter::UPDATE, $subject->getAccompanyingPeriodWork()),
default => throw new \UnexpectedValueException("attribute {$attribute} is not supported"), default => throw new \UnexpectedValueException("attribute {$attribute} is not supported"),
}; };
} }