mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
adapt UI and controller for Person without centers
This commit is contained in:
parent
2450655452
commit
5b70fb2ee5
@ -95,9 +95,12 @@ class CenterType extends AbstractType
|
|||||||
public function configureOptions(OptionsResolver $resolver)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
if (count($this->reachableCenters) > 1) {
|
if (count($this->reachableCenters) > 1) {
|
||||||
$resolver->setDefault('class', Center::class);
|
$resolver->setDefault('class', Center::class)
|
||||||
$resolver->setDefault('choices', $this->reachableCenters);
|
->setDefault('choices', $this->reachableCenters)
|
||||||
|
->setDefault('placeholder', 'Pick a center')
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Security\Resolver;
|
||||||
|
|
||||||
|
class CenterResolverDispatcher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var iterabble|CenterResolverInterface[]
|
||||||
|
*/
|
||||||
|
private iterable $resolvers = [];
|
||||||
|
|
||||||
|
private CenterResolverInterface $defaultResolver;
|
||||||
|
|
||||||
|
public function __construct(iterable $resolvers)
|
||||||
|
{
|
||||||
|
$this->resolvers = $resolvers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $entity
|
||||||
|
* @param array|null $options
|
||||||
|
* @return null|Center|Center[]
|
||||||
|
*/
|
||||||
|
public function resolveCenter($entity, ?array $options = [])
|
||||||
|
{
|
||||||
|
foreach($this->resolvers as $priority => $resolver) {
|
||||||
|
if ($resolver->supports($entity, $options)) {
|
||||||
|
return $resolver->resolveCenter($entity, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Security\Resolver;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
|
||||||
|
interface CenterResolverInterface
|
||||||
|
{
|
||||||
|
public function supports($entity, ?array $options = []): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $entity
|
||||||
|
* @param array|null $options
|
||||||
|
* @return Center|array|Center[]
|
||||||
|
*/
|
||||||
|
public function resolveCenter($entity, ?array $options = []);
|
||||||
|
|
||||||
|
public static function getDefaultPriority(): int;
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Security\Resolver;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\MainBundle\Entity\HasCenterInterface;
|
||||||
|
|
||||||
|
class DefaultCenterResolver implements CenterResolverInterface
|
||||||
|
{
|
||||||
|
public function supports($entity, ?array $options = []): bool
|
||||||
|
{
|
||||||
|
return $entity instanceof HasCenterInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*
|
||||||
|
* @param HasCenterInterface $entity
|
||||||
|
* @param array $options
|
||||||
|
*/
|
||||||
|
public function resolveCenter($entity, ?array $options = [])
|
||||||
|
{
|
||||||
|
return $entity->getCenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getDefaultPriority(): int
|
||||||
|
{
|
||||||
|
return -256;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Security\Resolver;
|
||||||
|
|
||||||
|
use Twig\TwigFilter;
|
||||||
|
|
||||||
|
final class ResolverTwigExtension extends \Twig\Extension\AbstractExtension
|
||||||
|
{
|
||||||
|
private CenterResolverDispatcher $centerResolverDispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param CenterResolverDispatcher $centerResolverDispatcher
|
||||||
|
*/
|
||||||
|
public function __construct(CenterResolverDispatcher $centerResolverDispatcher)
|
||||||
|
{
|
||||||
|
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilters()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new TwigFilter('chill_resolve_center', [$this, 'resolveCenter'])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $entity
|
||||||
|
* @param array|null $options
|
||||||
|
* @return Center|Center[]|null
|
||||||
|
*/
|
||||||
|
public function resolveCenter($entity, ?array $options = [])
|
||||||
|
{
|
||||||
|
return $this->centerResolverDispatcher->resolveCenter($entity, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -177,6 +177,7 @@ Exports list: Liste des exports
|
|||||||
Create an export: Créer un export
|
Create an export: Créer un export
|
||||||
#export creation step 'center' : pick a center
|
#export creation step 'center' : pick a center
|
||||||
Pick centers: Choisir les centres
|
Pick centers: Choisir les centres
|
||||||
|
Pick a center: Choisir un centre
|
||||||
The export will contains only data from the picked centers.: L'export ne contiendra que les données des centres choisis.
|
The export will contains only data from the picked centers.: L'export ne contiendra que les données des centres choisis.
|
||||||
This will eventually restrict your possibilities in filtering the data.: Les possibilités de filtrages seront adaptées aux droits de consultation pour les centres choisis.
|
This will eventually restrict your possibilities in filtering the data.: Les possibilités de filtrages seront adaptées aux droits de consultation pour les centres choisis.
|
||||||
Go to export options: Vers la préparation de l'export
|
Go to export options: Vers la préparation de l'export
|
||||||
|
@ -230,13 +230,16 @@ final class PersonController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function newAction(Request $request)
|
public function newAction(Request $request)
|
||||||
{
|
{
|
||||||
$defaultCenter = $this->security
|
$person = new Person();
|
||||||
->getUser()
|
|
||||||
->getGroupCenters()[0]
|
|
||||||
->getCenter();
|
|
||||||
|
|
||||||
$person = (new Person(new \DateTime('now')))
|
if (1 === count($this->security->getUser()
|
||||||
->setCenter($defaultCenter);
|
->getGroupCenters())) {
|
||||||
|
$person->setCenter(
|
||||||
|
$this->security->getUser()
|
||||||
|
->getGroupCenters()[0]
|
||||||
|
->getCenter()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$form = $this->createForm(CreationPersonType::class, $person, [
|
$form = $this->createForm(CreationPersonType::class, $person, [
|
||||||
'validation_groups' => ['create']
|
'validation_groups' => ['create']
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Form;
|
namespace Chill\PersonBundle\Form;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Form\Event\CustomizeFormEvent;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
@ -33,6 +35,7 @@ use Chill\PersonBundle\Form\Type\GenderType;
|
|||||||
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||||
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
||||||
|
use Chill\MainBundle\Form\Type\Export\PickCenterType;
|
||||||
|
|
||||||
final class CreationPersonType extends AbstractType
|
final class CreationPersonType extends AbstractType
|
||||||
{
|
{
|
||||||
@ -40,10 +43,6 @@ final class CreationPersonType extends AbstractType
|
|||||||
// TODO: See if this is still valid and update accordingly.
|
// TODO: See if this is still valid and update accordingly.
|
||||||
const NAME = 'chill_personbundle_person_creation';
|
const NAME = 'chill_personbundle_person_creation';
|
||||||
|
|
||||||
const FORM_NOT_REVIEWED = 'not_reviewed';
|
|
||||||
const FORM_REVIEWED = 'reviewed' ;
|
|
||||||
const FORM_BEING_REVIEWED = 'being_reviewed';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @var CenterTransformer
|
* @var CenterTransformer
|
||||||
@ -56,12 +55,16 @@ final class CreationPersonType extends AbstractType
|
|||||||
*/
|
*/
|
||||||
protected $configPersonAltNamesHelper;
|
protected $configPersonAltNamesHelper;
|
||||||
|
|
||||||
|
private EventDispatcherInterface $dispatcher;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
CenterTransformer $centerTransformer,
|
CenterTransformer $centerTransformer,
|
||||||
ConfigPersonAltNamesHelper $configPersonAltNamesHelper
|
ConfigPersonAltNamesHelper $configPersonAltNamesHelper,
|
||||||
|
EventDispatcherInterface $dispatcher
|
||||||
) {
|
) {
|
||||||
$this->centerTransformer = $centerTransformer;
|
$this->centerTransformer = $centerTransformer;
|
||||||
$this->configPersonAltNamesHelper = $configPersonAltNamesHelper;
|
$this->configPersonAltNamesHelper = $configPersonAltNamesHelper;
|
||||||
|
$this->dispatcher = $dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,7 +82,9 @@ final class CreationPersonType extends AbstractType
|
|||||||
->add('gender', GenderType::class, array(
|
->add('gender', GenderType::class, array(
|
||||||
'required' => true, 'placeholder' => null
|
'required' => true, 'placeholder' => null
|
||||||
))
|
))
|
||||||
->add('center', CenterType::class)
|
->add('center', CenterType::class, [
|
||||||
|
'required' => false
|
||||||
|
])
|
||||||
;
|
;
|
||||||
|
|
||||||
if ($this->configPersonAltNamesHelper->hasAltNames()) {
|
if ($this->configPersonAltNamesHelper->hasAltNames()) {
|
||||||
@ -87,6 +92,11 @@ final class CreationPersonType extends AbstractType
|
|||||||
'by_reference' => false
|
'by_reference' => false
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->dispatcher->dispatch(
|
||||||
|
new CustomizeFormEvent(static::class, $builder),
|
||||||
|
CustomizeFormEvent::NAME
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,10 +146,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% if options['addCenter'] %}
|
{% if options['addCenter'] and person|chill_resolve_center is not null %}
|
||||||
<li>
|
<li>
|
||||||
<i class="fa fa-li fa-long-arrow-right"></i>
|
<i class="fa fa-li fa-long-arrow-right"></i>
|
||||||
{{ person.center }}
|
{{ person|chill_resolve_center.name }}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-md-end">
|
<div class="text-md-end">
|
||||||
{%- if chill_person.fields.spoken_languages == 'visible' -%}
|
{% if person|chill_resolve_center is not null%}
|
||||||
<span class="open_sansbold">
|
<span class="open_sansbold">
|
||||||
{{ 'Center'|trans|upper}} :
|
{{ 'Center'|trans|upper}} :
|
||||||
</span>
|
</span>
|
||||||
{{ person.center.name|upper }}
|
{{ person|chill_resolve_center.name|upper }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,10 +76,9 @@
|
|||||||
|
|
||||||
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
|
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
|
||||||
|
|
||||||
<div style="display: none">
|
{% if form.center is defined %}
|
||||||
{# TODO remove this field (vendee) #}
|
{{ form_row(form.center) }}
|
||||||
{{ form_row(form.center, { 'label' : 'Center'|trans }) }}
|
{% endif %}
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
@ -153,7 +153,7 @@ class PersonSearch extends AbstractSearch implements ContainerAwareInterface,
|
|||||||
protected function search(array $terms, $start, $limit, array $options = array())
|
protected function search(array $terms, $start, $limit, array $options = array())
|
||||||
{
|
{
|
||||||
$qb = $this->createQuery($terms, 'search');
|
$qb = $this->createQuery($terms, 'search');
|
||||||
|
|
||||||
if ($options['simplify'] ?? false) {
|
if ($options['simplify'] ?? false) {
|
||||||
$qb->select(
|
$qb->select(
|
||||||
'p.id',
|
'p.id',
|
||||||
@ -176,7 +176,7 @@ class PersonSearch extends AbstractSearch implements ContainerAwareInterface,
|
|||||||
$qb
|
$qb
|
||||||
->orderBy('p.firstName')
|
->orderBy('p.firstName')
|
||||||
->addOrderBy('p.lastName');
|
->addOrderBy('p.lastName');
|
||||||
|
|
||||||
if ($options['simplify'] ?? false) {
|
if ($options['simplify'] ?? false) {
|
||||||
return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
|
return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
|
||||||
} else {
|
} else {
|
||||||
@ -291,10 +291,15 @@ class PersonSearch extends AbstractSearch implements ContainerAwareInterface,
|
|||||||
//restraint center for security
|
//restraint center for security
|
||||||
$reachableCenters = $this->helper->getReachableCenters($this->user,
|
$reachableCenters = $this->helper->getReachableCenters($this->user,
|
||||||
new Role('CHILL_PERSON_SEE'));
|
new Role('CHILL_PERSON_SEE'));
|
||||||
$qb->andWhere($qb->expr()
|
$qb->andWhere(
|
||||||
->in('p.center', ':centers'))
|
$qb->expr()->orX(
|
||||||
->setParameter('centers', $reachableCenters)
|
$qb->expr()
|
||||||
;
|
->in('p.center', ':centers'),
|
||||||
|
$qb->expr()
|
||||||
|
->isNull('p.center')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$qb->setParameter('centers', $reachableCenters);
|
||||||
|
|
||||||
$this->_cacheQuery[$cacheKey] = $qb;
|
$this->_cacheQuery[$cacheKey] = $qb;
|
||||||
|
|
||||||
|
@ -23,16 +23,12 @@ use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
|||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||||
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
||||||
|
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\MainBundle\Entity\Center;
|
use Chill\MainBundle\Entity\Center;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
use Symfony\Component\Security\Core\Role\Role;
|
use Symfony\Component\Security\Core\Role\Role;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
|
||||||
*/
|
|
||||||
class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||||
{
|
{
|
||||||
const CREATE = 'CHILL_PERSON_CREATE';
|
const CREATE = 'CHILL_PERSON_CREATE';
|
||||||
@ -41,18 +37,19 @@ class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInte
|
|||||||
const STATS = 'CHILL_PERSON_STATS';
|
const STATS = 'CHILL_PERSON_STATS';
|
||||||
const LISTS = 'CHILL_PERSON_LISTS';
|
const LISTS = 'CHILL_PERSON_LISTS';
|
||||||
const DUPLICATE = 'CHILL_PERSON_DUPLICATE';
|
const DUPLICATE = 'CHILL_PERSON_DUPLICATE';
|
||||||
|
|
||||||
/**
|
protected AuthorizationHelper $helper;
|
||||||
*
|
|
||||||
* @var AuthorizationHelper
|
protected CenterResolverDispatcher $centerResolverDispatcher;
|
||||||
*/
|
|
||||||
protected $helper;
|
public function __construct(
|
||||||
|
AuthorizationHelper $helper,
|
||||||
public function __construct(AuthorizationHelper $helper)
|
CenterResolverDispatcher $centerResolverDispatcher
|
||||||
{
|
) {
|
||||||
$this->helper = $helper;
|
$this->helper = $helper;
|
||||||
|
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supports($attribute, $subject)
|
protected function supports($attribute, $subject)
|
||||||
{
|
{
|
||||||
if ($subject instanceof Person) {
|
if ($subject instanceof Person) {
|
||||||
@ -69,23 +66,30 @@ class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInte
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||||
{
|
{
|
||||||
if (!$token->getUser() instanceof User) {
|
if (!$token->getUser() instanceof User) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($subject === null) {
|
if ($subject === null) {
|
||||||
$centers = $this->helper->getReachableCenters($token->getUser(),
|
$centers = $this->helper->getReachableCenters($token->getUser(),
|
||||||
new Role($attribute));
|
new Role($attribute));
|
||||||
|
|
||||||
return count($centers) > 0;
|
return count($centers) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$center = $this->centerResolverDispatcher->resolveCenter($subject);
|
||||||
|
|
||||||
|
if (NULL === $center && $subject instanceof Person) {
|
||||||
|
// person without any center are seen by everybody
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
|
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getAttributes()
|
private function getAttributes()
|
||||||
{
|
{
|
||||||
return array(self::CREATE, self::UPDATE, self::SEE, self::STATS, self::LISTS, self::DUPLICATE);
|
return array(self::CREATE, self::UPDATE, self::SEE, self::STATS, self::LISTS, self::DUPLICATE);
|
||||||
@ -100,7 +104,7 @@ class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInte
|
|||||||
{
|
{
|
||||||
return $this->getAttributes();
|
return $this->getAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRolesWithHierarchy()
|
public function getRolesWithHierarchy()
|
||||||
{
|
{
|
||||||
return [ 'Person' => $this->getRoles() ];
|
return [ 'Person' => $this->getRoles() ];
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
chill.person.security.authorization.person:
|
chill.person.security.authorization.person:
|
||||||
|
autowire: true
|
||||||
class: Chill\PersonBundle\Security\Authorization\PersonVoter
|
class: Chill\PersonBundle\Security\Authorization\PersonVoter
|
||||||
arguments:
|
|
||||||
- "@chill.main.security.authorization.helper"
|
|
||||||
tags:
|
tags:
|
||||||
- { name: security.voter }
|
- { name: security.voter }
|
||||||
- { name: chill.role }
|
- { name: chill.role }
|
||||||
@ -13,4 +12,4 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: security.voter }
|
- { name: security.voter }
|
||||||
- { name: chill.role }
|
- { name: chill.role }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user