diff --git a/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php index 2679993c4..239b88b90 100644 --- a/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php +++ b/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Repository; use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument; +use Chill\DocStoreBundle\Entity\StoredObject; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -45,6 +46,17 @@ class AccompanyingCourseDocumentRepository implements ObjectRepository return $qb->getQuery()->getSingleScalarResult(); } + public function findLinkedCourseDocument(int $storedObjectId): ?AccompanyingCourseDocument { + + $qb = $this->repository->createQueryBuilder('d'); + $query = $qb->leftJoin('d.storedObject', 'do') + ->where('do.id = :storedObjectId') + ->setParameter('storedObjectId', $storedObjectId) + ->getQuery(); + + return $query->getResult(); + } + public function find($id): ?AccompanyingCourseDocument { return $this->repository->find($id); @@ -69,4 +81,5 @@ class AccompanyingCourseDocumentRepository implements ObjectRepository { return AccompanyingCourseDocument::class; } + } diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentStoredObjectVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentStoredObjectVoter.php new file mode 100644 index 000000000..db1499a99 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/AccompanyingCourseDocumentStoredObjectVoter.php @@ -0,0 +1,50 @@ +repository->findLinkedCourseDocument($subject->getId())); + } + + public function voteOnAttribute(string $attribute, StoredObject $subject, TokenInterface $token): bool + { + if (!$token->getUser() instanceof User) { + return false; + } + + // Retrieve the related accompanying course document + $accompanyingCourseDocument = $this->repository->findLinkedCourseDocument($subject->getId()); + + // Determine the attribute to pass to AccompanyingCourseDocumentVoter + $voterAttribute = ($attribute === self::SEE_AND_EDIT) ? AccompanyingCourseDocumentVoter::UPDATE : AccompanyingCourseDocumentVoter::SEE_DETAILS; + + // Check access using AccompanyingCourseDocumentVoter + if ($this->accompanyingCourseDocumentVoter->voteOnAttribute($voterAttribute, $accompanyingCourseDocument, $token)) { + // TODO implement logic to check for associated workflow + return true; + } else { + return false; + } + } +} diff --git a/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodWorkEvaluationDocumentVoter.php b/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodWorkEvaluationDocumentVoter.php index 77c131cd9..8f4a1b995 100644 --- a/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodWorkEvaluationDocumentVoter.php +++ b/src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodWorkEvaluationDocumentVoter.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Security\Authorization; +use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoterInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; @@ -21,13 +22,13 @@ use Symfony\Component\Security\Core\Authorization\Voter\Voter; * * Delegates to the sames authorization than for Evalution */ -class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter +class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter implements StoredObjectVoterInterface { final public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_DOCUMENT_SHOW'; public function __construct(private readonly AccessDecisionManagerInterface $accessDecisionManager) {} - protected function supports($attribute, $subject) + public function supports($attribute, $subject): bool { return $subject instanceof AccompanyingPeriodWorkEvaluationDocument && self::SEE === $attribute; @@ -39,7 +40,7 @@ class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter * * @return bool|void */ - protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool + public function voteOnAttribute($attribute, $subject, TokenInterface $token): bool { return match ($attribute) { self::SEE => $this->accessDecisionManager->decide(