diff --git a/src/Bundle/ChillMainBundle/Controller/SavedExportController.php b/src/Bundle/ChillMainBundle/Controller/SavedExportController.php
index cb9d89215..22e4a6ba7 100644
--- a/src/Bundle/ChillMainBundle/Controller/SavedExportController.php
+++ b/src/Bundle/ChillMainBundle/Controller/SavedExportController.php
@@ -120,15 +120,15 @@ final readonly class SavedExportController
#[Route(path: '/exports/saved/duplicate-from-saved-export/{id}/new', name: 'chill_main_export_saved_duplicate')]
public function duplicate(SavedExport $previousSavedExport, Request $request): Response
{
- if (!$this->security->isGranted(SavedExportVoter::GENERATE, $previousSavedExport)) {
- throw new AccessDeniedHttpException('Not allowed to see this saved export');
- }
-
$user = $this->security->getUser();
if (!$user instanceof User) {
throw new AccessDeniedHttpException('only regular user can create a saved export');
}
+ if (!$this->security->isGranted(SavedExportVoter::EDIT, $previousSavedExport)) {
+ throw new AccessDeniedHttpException('Not allowed to edit this saved export');
+ }
+
$savedExport = new SavedExport();
$savedExport
->setExportAlias($previousSavedExport->getExportAlias())
@@ -209,7 +209,7 @@ final readonly class SavedExportController
#[Route(path: '/{_locale}/exports/saved/{savedExport}/edit-options/{exportGeneration}', name: 'chill_main_export_saved_options_edit')]
public function updateOptionsFromGeneration(SavedExport $savedExport, ExportGeneration $exportGeneration, Request $request): Response
{
- if (!$this->security->isGranted(SavedExportVoter::EDIT, $savedExport)) {
+ if (!$this->security->isGranted(SavedExportVoter::DUPLICATE, $savedExport)) {
throw new AccessDeniedHttpException('You are not allowed to access this saved export');
}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig
index 4a9b9490e..40257a996 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig
@@ -30,6 +30,10 @@
{% if app.user is same as saved.user %}{{ 'saved_export.Owner'|trans }}{% endif %}
+ {% else %}
+
+ Partagé par {{ saved.user|chill_entity_render_box }}
+
{% endif %}
{{ saved.description|chill_markdown_to_html }}
@@ -63,7 +67,9 @@
{% endif %}
{# reminder: the controller already checked that the user can generate saved exports #}
{{ 'saved_export.update_filters_aggregators_and_execute'|trans }}
- {{ 'saved_export.Duplicate'|trans }}
+ {% if is_granted('CHILL_MAIN_EXPORT_SAVED_DUPLICATE', saved) %}
+ {{ 'saved_export.Duplicate'|trans }}
+ {% endif %}
{% if is_granted('CHILL_MAIN_EXPORT_SAVED_DELETE', saved) %}
{{ 'Delete'|trans }}
{% endif %}
diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php
index 1d686dee4..aaf8b8010 100644
--- a/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php
+++ b/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php
@@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\SavedExport;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\ExportManager;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
final class SavedExportVoter extends Voter
@@ -25,6 +26,8 @@ final class SavedExportVoter extends Voter
final public const GENERATE = 'CHILL_MAIN_EXPORT_SAVED_GENERATE';
+ final public const DUPLICATE = 'CHILL_MAIN_EXPORT_SAVED_DUPLICATE';
+
final public const SHARE = 'CHILL_MAIN_EXPORT_SAVED_SHARE';
private const ALL = [
@@ -32,9 +35,10 @@ final class SavedExportVoter extends Voter
self::EDIT,
self::GENERATE,
self::SHARE,
+ self::DUPLICATE,
];
- public function __construct(private readonly ExportManager $exportManager) {}
+ public function __construct(private readonly ExportManager $exportManager, private readonly AccessDecisionManagerInterface $accessDecisionManager) {}
protected function supports($attribute, $subject): bool
{
@@ -52,6 +56,7 @@ final class SavedExportVoter extends Voter
return match ($attribute) {
self::DELETE, self::EDIT, self::SHARE => $subject->getUser() === $token->getUser(),
+ self::DUPLICATE => $this->accessDecisionManager->decide($token, [ChillExportVoter::COMPOSE_EXPORT]) && $this->accessDecisionManager->decide($token, [self::EDIT], $subject) ,
self::GENERATE => $this->canUserGenerate($user, $subject),
default => throw new \UnexpectedValueException('attribute not supported: '.$attribute),
};