mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Restrict export filters and aggregators for limited users
Added restrictions on export filters and aggregators based on user permissions. Introduced `ExportConfigProcessor` to handle allowed configurations and updated form components to respect these restrictions. Enhanced validation to enforce access control for unauthorized filter editing.
This commit is contained in:
parent
a6e523ee0a
commit
8c5a7ac3e1
@ -16,6 +16,7 @@ use Chill\MainBundle\Entity\SavedExport;
|
|||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
use Chill\MainBundle\Export\DirectExportInterface;
|
use Chill\MainBundle\Export\DirectExportInterface;
|
||||||
use Chill\MainBundle\Export\ExportConfigNormalizer;
|
use Chill\MainBundle\Export\ExportConfigNormalizer;
|
||||||
|
use Chill\MainBundle\Export\ExportConfigProcessor;
|
||||||
use Chill\MainBundle\Export\ExportFormHelper;
|
use Chill\MainBundle\Export\ExportFormHelper;
|
||||||
use Chill\MainBundle\Export\ExportInterface;
|
use Chill\MainBundle\Export\ExportInterface;
|
||||||
use Chill\MainBundle\Export\ExportManager;
|
use Chill\MainBundle\Export\ExportManager;
|
||||||
@ -24,6 +25,7 @@ use Chill\MainBundle\Form\Type\Export\ExportType;
|
|||||||
use Chill\MainBundle\Form\Type\Export\FormatterType;
|
use Chill\MainBundle\Form\Type\Export\FormatterType;
|
||||||
use Chill\MainBundle\Form\Type\Export\PickCenterType;
|
use Chill\MainBundle\Form\Type\Export\PickCenterType;
|
||||||
use Chill\MainBundle\Repository\SavedExportOrExportGenerationRepository;
|
use Chill\MainBundle\Repository\SavedExportOrExportGenerationRepository;
|
||||||
|
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
||||||
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
|
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
@ -64,6 +66,7 @@ class ExportController extends AbstractController
|
|||||||
private readonly ClockInterface $clock,
|
private readonly ClockInterface $clock,
|
||||||
private readonly ExportConfigNormalizer $exportConfigNormalizer,
|
private readonly ExportConfigNormalizer $exportConfigNormalizer,
|
||||||
private readonly SavedExportOrExportGenerationRepository $savedExportOrExportGenerationRepository,
|
private readonly SavedExportOrExportGenerationRepository $savedExportOrExportGenerationRepository,
|
||||||
|
private readonly ExportConfigProcessor $exportConfigProcessor,
|
||||||
) {
|
) {
|
||||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||||
}
|
}
|
||||||
@ -114,11 +117,19 @@ class ExportController extends AbstractController
|
|||||||
/** @var ExportManager $exportManager */
|
/** @var ExportManager $exportManager */
|
||||||
$exportManager = $this->exportManager;
|
$exportManager = $this->exportManager;
|
||||||
$isGenerate = str_starts_with($step, 'generate_');
|
$isGenerate = str_starts_with($step, 'generate_');
|
||||||
|
$canEditFull = $this->security->isGranted(ChillExportVoter::COMPOSE_EXPORT);
|
||||||
|
|
||||||
|
if (!$canEditFull && null === $savedExport) {
|
||||||
|
throw new AccessDeniedHttpException('The user is not allowed to edit all filter, it should edit only SavedExport');
|
||||||
|
}
|
||||||
|
|
||||||
$options = match ($step) {
|
$options = match ($step) {
|
||||||
'export', 'generate_export' => [
|
'export', 'generate_export' => [
|
||||||
'export_alias' => $alias,
|
'export_alias' => $alias,
|
||||||
'picked_centers' => $this->exportFormHelper->getPickedCenters($data),
|
'picked_centers' => $this->exportFormHelper->getPickedCenters($data),
|
||||||
|
'can_edit_full' => $canEditFull,
|
||||||
|
'allowed_filters' => $canEditFull ? null : $this->exportConfigProcessor->retrieveUsedFilters($savedExport->getOptions()['filters']),
|
||||||
|
'allowed_aggregators' => $canEditFull ? null : $this->exportConfigProcessor->retrieveUsedAggregators($savedExport->getOptions()['aggregators']),
|
||||||
],
|
],
|
||||||
'formatter', 'generate_formatter' => [
|
'formatter', 'generate_formatter' => [
|
||||||
'export_alias' => $alias,
|
'export_alias' => $alias,
|
||||||
|
@ -32,6 +32,7 @@ class AggregatorType extends AbstractType
|
|||||||
->add(self::ENABLED_FIELD, CheckboxType::class, [
|
->add(self::ENABLED_FIELD, CheckboxType::class, [
|
||||||
'value' => true,
|
'value' => true,
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'disabled' => $options['disable_enable_field'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$aggregatorFormBuilder = $builder->create('form', FormType::class, [
|
$aggregatorFormBuilder = $builder->create('form', FormType::class, [
|
||||||
@ -55,6 +56,7 @@ class AggregatorType extends AbstractType
|
|||||||
{
|
{
|
||||||
$resolver->setRequired('aggregator_alias')
|
$resolver->setRequired('aggregator_alias')
|
||||||
->setRequired('export_manager')
|
->setRequired('export_manager')
|
||||||
|
->setDefault('disable_enable_field', false)
|
||||||
->setDefault('compound', true)
|
->setDefault('compound', true)
|
||||||
->setDefault('error_bubbling', false);
|
->setDefault('error_bubbling', false);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ class ExportType extends AbstractType
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ExportManager $exportManager,
|
private readonly ExportManager $exportManager,
|
||||||
private readonly SortExportElement $sortExportElement,
|
private readonly SortExportElement $sortExportElement,
|
||||||
protected ParameterBagInterface $parameterBag,
|
ParameterBagInterface $parameterBag,
|
||||||
) {
|
) {
|
||||||
$this->personFieldsConfig = $parameterBag->get('chill_person.person_fields');
|
$this->personFieldsConfig = $parameterBag->get('chill_person.person_fields');
|
||||||
}
|
}
|
||||||
@ -43,6 +43,8 @@ class ExportType extends AbstractType
|
|||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
$export = $this->exportManager->getExport($options['export_alias']);
|
$export = $this->exportManager->getExport($options['export_alias']);
|
||||||
|
/** @var bool $canEditFull */
|
||||||
|
$canEditFull = $options['can_edit_full'];
|
||||||
|
|
||||||
$exportOptions = [
|
$exportOptions = [
|
||||||
'compound' => true,
|
'compound' => true,
|
||||||
@ -59,8 +61,18 @@ class ExportType extends AbstractType
|
|||||||
|
|
||||||
if ($export instanceof \Chill\MainBundle\Export\ExportInterface) {
|
if ($export instanceof \Chill\MainBundle\Export\ExportInterface) {
|
||||||
// add filters
|
// add filters
|
||||||
|
$filterAliases = $options['allowed_filters'];
|
||||||
|
$filters = [];
|
||||||
|
if (is_iterable($filterAliases)) {
|
||||||
|
foreach ($filterAliases as $alias => $filter) {
|
||||||
|
$filters[$alias] = $filter;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
$filters = $this->exportManager->getFiltersApplyingOn($export, $options['picked_centers']);
|
$filters = $this->exportManager->getFiltersApplyingOn($export, $options['picked_centers']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->sortExportElement->sortFilters($filters);
|
$this->sortExportElement->sortFilters($filters);
|
||||||
|
|
||||||
$filterBuilder = $builder->create(self::FILTER_KEY, FormType::class, ['compound' => true]);
|
$filterBuilder = $builder->create(self::FILTER_KEY, FormType::class, ['compound' => true]);
|
||||||
|
|
||||||
foreach ($filters as $alias => $filter) {
|
foreach ($filters as $alias => $filter) {
|
||||||
@ -70,15 +82,26 @@ class ExportType extends AbstractType
|
|||||||
'constraints' => [
|
'constraints' => [
|
||||||
new ExportElementConstraint(['element' => $filter]),
|
new ExportElementConstraint(['element' => $filter]),
|
||||||
],
|
],
|
||||||
|
'disable_enable_field' => !$canEditFull,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$builder->add($filterBuilder);
|
$builder->add($filterBuilder);
|
||||||
|
|
||||||
// add aggregators
|
// add aggregators
|
||||||
|
$aggregatorsAliases = $options['allowed_aggregators'];
|
||||||
|
$aggregators = [];
|
||||||
|
if (is_iterable($aggregatorsAliases)) {
|
||||||
|
foreach ($aggregatorsAliases as $alias => $aggregator) {
|
||||||
|
$aggregators[$alias] = $aggregator;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
$aggregators = $this->exportManager
|
$aggregators = $this->exportManager
|
||||||
->getAggregatorsApplyingOn($export, $options['picked_centers']);
|
->getAggregatorsApplyingOn($export, $options['picked_centers']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->sortExportElement->sortAggregators($aggregators);
|
$this->sortExportElement->sortAggregators($aggregators);
|
||||||
|
|
||||||
$aggregatorBuilder = $builder->create(
|
$aggregatorBuilder = $builder->create(
|
||||||
self::AGGREGATOR_KEY,
|
self::AGGREGATOR_KEY,
|
||||||
FormType::class,
|
FormType::class,
|
||||||
@ -96,11 +119,11 @@ class ExportType extends AbstractType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$aggregatorBuilder->add($alias, AggregatorType::class, [
|
$aggregatorBuilder->add($alias, AggregatorType::class, [
|
||||||
'aggregator_alias' => $alias,
|
'aggregator_alias' => $alias,
|
||||||
'export_manager' => $this->exportManager,
|
'export_manager' => $this->exportManager,
|
||||||
'label' => $aggregator->getTitle(),
|
'label' => $aggregator->getTitle(),
|
||||||
|
'disable_enable_field' => !$canEditFull,
|
||||||
'constraints' => [
|
'constraints' => [
|
||||||
new ExportElementConstraint(['element' => $aggregator]),
|
new ExportElementConstraint(['element' => $aggregator]),
|
||||||
],
|
],
|
||||||
@ -125,8 +148,13 @@ class ExportType extends AbstractType
|
|||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
$resolver->setRequired(['export_alias', 'picked_centers'])
|
$resolver->setRequired(['export_alias', 'picked_centers', 'can_edit_full'])
|
||||||
->setAllowedTypes('export_alias', ['string'])
|
->setAllowedTypes('export_alias', ['string'])
|
||||||
|
->setAllowedValues('can_edit_full', [true, false])
|
||||||
|
->setDefault('allowed_filters', null)
|
||||||
|
->setAllowedTypes('allowed_filters', ['iterable', 'null'])
|
||||||
|
->setDefault('allowed_aggregators', null)
|
||||||
|
->setAllowedTypes('allowed_aggregators', ['iterable', 'null'])
|
||||||
->setDefault('compound', true)
|
->setDefault('compound', true)
|
||||||
->setDefault('constraints', [
|
->setDefault('constraints', [
|
||||||
// new \Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint()
|
// new \Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint()
|
||||||
|
@ -34,6 +34,7 @@ class FilterType extends AbstractType
|
|||||||
->add(self::ENABLED_FIELD, CheckboxType::class, [
|
->add(self::ENABLED_FIELD, CheckboxType::class, [
|
||||||
'value' => true,
|
'value' => true,
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'disabled' => $options['disable_enable_field'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$filterFormBuilder = $builder->create('form', FormType::class, [
|
$filterFormBuilder = $builder->create('form', FormType::class, [
|
||||||
@ -58,6 +59,7 @@ class FilterType extends AbstractType
|
|||||||
$resolver
|
$resolver
|
||||||
->setRequired('filter')
|
->setRequired('filter')
|
||||||
->setAllowedTypes('filter', [FilterInterface::class])
|
->setAllowedTypes('filter', [FilterInterface::class])
|
||||||
|
->setDefault('disable_enable_field', false)
|
||||||
->setDefault('compound', true)
|
->setDefault('compound', true)
|
||||||
->setDefault('error_bubbling', false);
|
->setDefault('error_bubbling', false);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ services:
|
|||||||
|
|
||||||
Chill\MainBundle\Export\ExportConfigNormalizer: ~
|
Chill\MainBundle\Export\ExportConfigNormalizer: ~
|
||||||
|
|
||||||
|
Chill\MainBundle\Export\ExportConfigProcessor: ~
|
||||||
|
|
||||||
chill.main.export_element_validator:
|
chill.main.export_element_validator:
|
||||||
class: Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraintValidator
|
class: Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraintValidator
|
||||||
tags:
|
tags:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user