adapt UI and controller for Person without centers

This commit is contained in:
Julien Fastré 2021-09-03 12:41:41 +02:00
parent 2450655452
commit 5b70fb2ee5
14 changed files with 196 additions and 53 deletions

View File

@ -95,9 +95,12 @@ class CenterType extends AbstractType
public function configureOptions(OptionsResolver $resolver)
{
if (count($this->reachableCenters) > 1) {
$resolver->setDefault('class', Center::class);
$resolver->setDefault('choices', $this->reachableCenters);
$resolver->setDefault('class', Center::class)
->setDefault('choices', $this->reachableCenters)
->setDefault('placeholder', 'Pick a center')
;
}
}
/**

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -177,6 +177,7 @@ Exports list: Liste des exports
Create an export: Créer un export
#export creation step 'center' : pick a center
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.
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

View File

@ -230,13 +230,16 @@ final class PersonController extends AbstractController
*/
public function newAction(Request $request)
{
$defaultCenter = $this->security
->getUser()
->getGroupCenters()[0]
->getCenter();
$person = new Person();
$person = (new Person(new \DateTime('now')))
->setCenter($defaultCenter);
if (1 === count($this->security->getUser()
->getGroupCenters())) {
$person->setCenter(
$this->security->getUser()
->getGroupCenters()[0]
->getCenter()
);
}
$form = $this->createForm(CreationPersonType::class, $person, [
'validation_groups' => ['create']

View File

@ -21,7 +21,9 @@
namespace Chill\PersonBundle\Form;
use Chill\MainBundle\Form\Event\CustomizeFormEvent;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@ -33,6 +35,7 @@ use Chill\PersonBundle\Form\Type\GenderType;
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Form\Type\PersonAltNameType;
use Chill\MainBundle\Form\Type\Export\PickCenterType;
final class CreationPersonType extends AbstractType
{
@ -40,10 +43,6 @@ final class CreationPersonType extends AbstractType
// TODO: See if this is still valid and update accordingly.
const NAME = 'chill_personbundle_person_creation';
const FORM_NOT_REVIEWED = 'not_reviewed';
const FORM_REVIEWED = 'reviewed' ;
const FORM_BEING_REVIEWED = 'being_reviewed';
/**
*
* @var CenterTransformer
@ -56,12 +55,16 @@ final class CreationPersonType extends AbstractType
*/
protected $configPersonAltNamesHelper;
private EventDispatcherInterface $dispatcher;
public function __construct(
CenterTransformer $centerTransformer,
ConfigPersonAltNamesHelper $configPersonAltNamesHelper
ConfigPersonAltNamesHelper $configPersonAltNamesHelper,
EventDispatcherInterface $dispatcher
) {
$this->centerTransformer = $centerTransformer;
$this->configPersonAltNamesHelper = $configPersonAltNamesHelper;
$this->dispatcher = $dispatcher;
}
/**
@ -79,7 +82,9 @@ final class CreationPersonType extends AbstractType
->add('gender', GenderType::class, array(
'required' => true, 'placeholder' => null
))
->add('center', CenterType::class)
->add('center', CenterType::class, [
'required' => false
])
;
if ($this->configPersonAltNamesHelper->hasAltNames()) {
@ -87,6 +92,11 @@ final class CreationPersonType extends AbstractType
'by_reference' => false
]);
}
$this->dispatcher->dispatch(
new CustomizeFormEvent(static::class, $builder),
CustomizeFormEvent::NAME
);
}
/**

View File

@ -146,10 +146,10 @@
{% endif %}
{% endif %}
</li>
{% if options['addCenter'] %}
{% if options['addCenter'] and person|chill_resolve_center is not null %}
<li>
<i class="fa fa-li fa-long-arrow-right"></i>
{{ person.center }}
{{ person|chill_resolve_center.name }}
</li>
{% endif %}
</ul>

View File

@ -17,11 +17,11 @@
{%- endif -%}
</div>
<div class="text-md-end">
{%- if chill_person.fields.spoken_languages == 'visible' -%}
{% if person|chill_resolve_center is not null%}
<span class="open_sansbold">
{{ 'Center'|trans|upper}} :
</span>
{{ person.center.name|upper }}
{{ person|chill_resolve_center.name|upper }}
{%- endif -%}
</div>
</div>

View File

@ -76,10 +76,9 @@
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
<div style="display: none">
{# TODO remove this field (vendee) #}
{{ form_row(form.center, { 'label' : 'Center'|trans }) }}
</div>
{% if form.center is defined %}
{{ form_row(form.center) }}
{% endif %}
<ul class="record_actions sticky-form-buttons">
<li class="dropdown">

View File

@ -291,10 +291,15 @@ class PersonSearch extends AbstractSearch implements ContainerAwareInterface,
//restraint center for security
$reachableCenters = $this->helper->getReachableCenters($this->user,
new Role('CHILL_PERSON_SEE'));
$qb->andWhere($qb->expr()
->in('p.center', ':centers'))
->setParameter('centers', $reachableCenters)
;
$qb->andWhere(
$qb->expr()->orX(
$qb->expr()
->in('p.center', ':centers'),
$qb->expr()
->isNull('p.center')
)
);
$qb->setParameter('centers', $reachableCenters);
$this->_cacheQuery[$cacheKey] = $qb;

View File

@ -23,16 +23,12 @@ use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
use Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Entity\Center;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\Role;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
const CREATE = 'CHILL_PERSON_CREATE';
@ -42,15 +38,16 @@ class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInte
const LISTS = 'CHILL_PERSON_LISTS';
const DUPLICATE = 'CHILL_PERSON_DUPLICATE';
/**
*
* @var AuthorizationHelper
*/
protected $helper;
protected AuthorizationHelper $helper;
public function __construct(AuthorizationHelper $helper)
{
protected CenterResolverDispatcher $centerResolverDispatcher;
public function __construct(
AuthorizationHelper $helper,
CenterResolverDispatcher $centerResolverDispatcher
) {
$this->helper = $helper;
$this->centerResolverDispatcher = $centerResolverDispatcher;
}
protected function supports($attribute, $subject)
@ -83,6 +80,13 @@ class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInte
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);
}

View File

@ -1,8 +1,7 @@
services:
chill.person.security.authorization.person:
autowire: true
class: Chill\PersonBundle\Security\Authorization\PersonVoter
arguments:
- "@chill.main.security.authorization.helper"
tags:
- { name: security.voter }
- { name: chill.role }