mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-21 15:13:50 +00:00
upgrade voter and acl for activities and implement autoconfiguration for
ChillProvideRole interface
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
@@ -33,9 +35,10 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
|
||||
final class ActivityACLAwareRepository
|
||||
final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface
|
||||
{
|
||||
private AuthorizationHelper $authorizationHelper;
|
||||
|
||||
@@ -45,16 +48,63 @@ final class ActivityACLAwareRepository
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private CenterResolverDispatcher $centerResolverDispatcher;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
CenterResolverDispatcher $centerResolverDispatcher,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
ActivityRepository $repository,
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
Security $security
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->repository = $repository;
|
||||
$this->em = $em;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person $person
|
||||
* @param string $role
|
||||
* @param int|null $start
|
||||
* @param int|null $limit
|
||||
* @param array $orderBy
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($person);
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$reachableScopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start);
|
||||
;
|
||||
}
|
||||
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($period);
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$scopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy);
|
||||
}
|
||||
|
||||
public function queryTimelineIndexer(string $context, array $args = []): array
|
||||
@@ -81,7 +131,7 @@ final class ActivityACLAwareRepository
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$associationMapping = $metadataActivity->getAssociationMapping('person');
|
||||
|
||||
|
||||
return $metadataActivity->getTableName().' JOIN '
|
||||
.$metadataPerson->getTableName().' ON '
|
||||
.$metadataPerson->getTableName().'.'.
|
||||
@@ -95,7 +145,7 @@ final class ActivityACLAwareRepository
|
||||
{
|
||||
$where = '';
|
||||
$parameters = [];
|
||||
|
||||
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name'];
|
||||
@@ -105,20 +155,20 @@ final class ActivityACLAwareRepository
|
||||
|
||||
// acls:
|
||||
$role = new Role(ActivityVoter::SEE);
|
||||
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
|
||||
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
|
||||
$role);
|
||||
|
||||
|
||||
if (count($reachableCenters) === 0) {
|
||||
// insert a dummy condition
|
||||
return 'FALSE = TRUE';
|
||||
}
|
||||
|
||||
if ($context === 'person') {
|
||||
// we start with activities having the person_id linked to person
|
||||
if ($context === 'person') {
|
||||
// we start with activities having the person_id linked to person
|
||||
$where .= sprintf('%s = ? AND ', $activityToPerson);
|
||||
$parameters[] = $person->getId();
|
||||
}
|
||||
|
||||
|
||||
// we add acl (reachable center and scopes)
|
||||
$where .= '('; // first loop for the for centers
|
||||
$centersI = 0; // like centers#i
|
||||
@@ -131,7 +181,7 @@ final class ActivityACLAwareRepository
|
||||
$reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center);
|
||||
// we get the ids for those scopes
|
||||
$reachablesScopesId = array_map(
|
||||
function(Scope $scope) { return $scope->getId(); },
|
||||
function(Scope $scope) { return $scope->getId(); },
|
||||
$reachableScopes
|
||||
);
|
||||
|
||||
@@ -162,7 +212,7 @@ final class ActivityACLAwareRepository
|
||||
}
|
||||
// close loop for centers
|
||||
$where .= ')';
|
||||
|
||||
|
||||
return [$where, $parameters];
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
interface ActivityACLAwareRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
|
||||
/**
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
}
|
@@ -23,6 +23,8 @@
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
@@ -39,15 +41,22 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, Activity::class);
|
||||
}
|
||||
|
||||
public function findByPersonImplied($person, array $scopes, $orderBy = [ 'date' => 'DESC'], $limit = 100, $offset = 0)
|
||||
/**
|
||||
* @param $person
|
||||
* @param array $scopes
|
||||
* @param string[] $orderBy
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = [ 'date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
$qb
|
||||
// TODO add acl
|
||||
//->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
//->setParameter('scopes', $scopes)
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('a.person', ':person'),
|
||||
@@ -61,7 +70,56 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriod $period
|
||||
* @param array $scopes
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @param array|string[] $orderBy
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
if (!$allowNullScope) {
|
||||
$qb
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
} else {
|
||||
$qb
|
||||
->where(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->in('a.scope', ':scopes'),
|
||||
$qb->expr()->isNull('a.scope')
|
||||
)
|
||||
)
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->eq('a.accompanyingPeriod', ':period')
|
||||
)
|
||||
->setParameter('period', $period)
|
||||
;
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user