delegates the acl for fetching person documents to an ACLAwareREpository

This commit is contained in:
Julien Fastré 2022-02-10 00:37:24 +01:00
parent a387305ef8
commit 6fa99655b2
4 changed files with 106 additions and 16 deletions

View File

@ -13,6 +13,7 @@ namespace Chill\DocStoreBundle\Controller;
use Chill\DocStoreBundle\Entity\PersonDocument;
use Chill\DocStoreBundle\Form\PersonDocumentType;
use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface;
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
@ -44,6 +45,8 @@ class DocumentPersonController extends AbstractController
private PaginatorFactory $paginatorFactory;
private PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository;
/**
* DocumentPersonController constructor.
*/
@ -51,12 +54,14 @@ class DocumentPersonController extends AbstractController
TranslatorInterface $translator,
EventDispatcherInterface $eventDispatcher,
AuthorizationHelper $authorizationHelper,
PaginatorFactory $paginatorFactory
PaginatorFactory $paginatorFactory,
PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository
) {
$this->translator = $translator;
$this->eventDispatcher = $eventDispatcher;
$this->authorizationHelper = $authorizationHelper;
$this->paginatorFactory = $paginatorFactory;
$this->personDocumentACLAwareRepository = $personDocumentACLAwareRepository;
}
/**
@ -152,21 +157,10 @@ class DocumentPersonController extends AbstractController
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
$reachableScopes = $this->authorizationHelper
->getReachableScopes(
$this->getUser(),
PersonDocumentVoter::SEE,
$person->getCenter()
);
$documents = $this->personDocumentACLAwareRepository->findByPerson($person);
$documents = $em
->getRepository('ChillDocStoreBundle:PersonDocument')
->findBy(
['person' => $person, 'scope' => $reachableScopes],
['date' => 'DESC']
);
$total = count($documents);
// wrong: count documents in database and retrieve document for this page.
$total = $this->personDocumentACLAwareRepository->countByPerson($person);
$pagination = $this->paginatorFactory->create($total);
$event = new PrivacyEvent($person, [

View File

@ -0,0 +1,85 @@
<?php
namespace Chill\DocStoreBundle\Repository;
use Chill\DocStoreBundle\Entity\PersonDocument;
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Security\Core\Security;
class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareRepositoryInterface
{
private EntityManagerInterface $em;
private AuthorizationHelperInterface $authorizationHelper;
private CenterResolverDispatcher $centerResolverDispatcher;
private Security $security;
public function __construct(EntityManagerInterface $em, AuthorizationHelperInterface $authorizationHelper, CenterResolverDispatcher $centerResolverDispatcher, Security $security)
{
$this->em = $em;
$this->authorizationHelper = $authorizationHelper;
$this->centerResolverDispatcher = $centerResolverDispatcher;
$this->security = $security;
}
public function findByPerson(Person $person, array $orderBy = [], int $limit = 20, int $offset = 0): array
{
$qb = $this->buildQueryByPerson($person)->select('d');
$this->addACL($qb, $person);
foreach ($orderBy as list($field, $order)) {
$qb->addOrderBy($field, $order);
}
$qb->setFirstResult($offset)->setMaxResults($limit);
return $qb->getQuery()->getResult();
}
public function countByPerson(Person $person): int
{
$qb = $this->buildQueryByPerson($person)->select('COUNT(d)');
$this->addACL($qb, $person);
return $qb->getQuery()->getSingleScalarResult();
}
public function buildQueryByPerson(Person $person): QueryBuilder
{
$qb = $this->em->getRepository(PersonDocument::class)->createQueryBuilder('d');
$qb
->where($qb->expr()->eq('d.person', ':person'))
->setParameter('person', $person)
;
return $qb;
}
private function addACL(QueryBuilder $qb, Person $person): void
{
$center = $this->centerResolverDispatcher->resolveCenter($person);
$reachableScopes = $this->authorizationHelper
->getReachableScopes(
$this->security->getUser(),
PersonDocumentVoter::SEE,
$center
);
$qb->andWhere($qb->expr()->in('d.scope', ':scopes'))
->setParameter('scopes', $reachableScopes)
;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Chill\DocStoreBundle\Repository;
use Chill\PersonBundle\Entity\Person;
interface PersonDocumentACLAwareRepositoryInterface
{
public function findByPerson(Person $person, array $orderBy = [], int $limit = 20, int $offset = 0): array;
public function countByPerson(Person $person): int;
}

View File

@ -6,7 +6,6 @@ services:
autowire: true
autoconfigure: true
resource: "../Repository/"
tags: ["doctrine.repository_service"]
Chill\DocStoreBundle\Form\DocumentCategoryType:
class: Chill\DocStoreBundle\Form\DocumentCategoryType