From d6ca50d627887274f4550f2a2d4e296d230bcf17 Mon Sep 17 00:00:00 2001 From: Daniel Subiabre Date: Fri, 30 Jan 2026 14:51:04 +0100 Subject: [PATCH] Update visibility of charges and checkout owner and targets based on accounting voters --- src/ApiResource/Gateway/ChargeApiResource.php | 2 +- src/ApiResource/Gateway/CheckoutApiResource.php | 5 +---- src/Security/Voter/AccountingVoter.php | 11 +++++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ApiResource/Gateway/ChargeApiResource.php b/src/ApiResource/Gateway/ChargeApiResource.php index efcd4b9..9627bcb 100644 --- a/src/ApiResource/Gateway/ChargeApiResource.php +++ b/src/ApiResource/Gateway/ChargeApiResource.php @@ -38,7 +38,6 @@ class ChargeApiResource /** * The Checkout to which this Charge item belongs to. */ - #[API\ApiProperty(writable: false, security: 'is_granted("IS_AUTHENTICATED_FULLY")')] #[API\ApiFilter(GatewayFilter::class, properties: ['checkout.gateway'])] #[API\ApiFilter(Filter\SearchFilter::class, properties: ['checkout.trackings.value'])] public CheckoutApiResource $checkout; @@ -70,6 +69,7 @@ class ChargeApiResource * The Accounting receiving the money after a successful payment. */ #[Assert\NotBlank()] + #[API\ApiProperty(security: 'is_granted("ACCOUNTING_VIEW", object.target)')] #[API\ApiFilter(Filter\SearchFilter::class, strategy: 'exact')] public AccountingApiResource $target; diff --git a/src/ApiResource/Gateway/CheckoutApiResource.php b/src/ApiResource/Gateway/CheckoutApiResource.php index fdf1623..8d4a1e8 100644 --- a/src/ApiResource/Gateway/CheckoutApiResource.php +++ b/src/ApiResource/Gateway/CheckoutApiResource.php @@ -50,10 +50,7 @@ class CheckoutApiResource /** * The Accounting paying for the charges. */ - #[API\ApiProperty( - security: 'is_granted("ACCOUNTING_VIEW", object.origin)', - securityPostDenormalize: 'is_granted("ACCOUNTING_EDIT", previous_object.origin)' - )] + #[API\ApiProperty(security: 'is_granted("ACCOUNTING_VIEW", object.origin)')] #[Assert\NotBlank()] public AccountingApiResource $origin; diff --git a/src/Security/Voter/AccountingVoter.php b/src/Security/Voter/AccountingVoter.php index 343f1df..d8f1af3 100644 --- a/src/Security/Voter/AccountingVoter.php +++ b/src/Security/Voter/AccountingVoter.php @@ -6,8 +6,10 @@ use ApiPlatform\Metadata\IriConverterInterface; use App\ApiResource\Accounting\AccountingApiResource; use App\ApiResource\User\UserApiResource; use App\Entity\User\User; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; +use Symfony\Component\Security\Core\User\UserInterface; class AccountingVoter extends Voter { @@ -17,6 +19,7 @@ class AccountingVoter extends Voter public const VIEW = 'ACCOUNTING_VIEW'; public function __construct( + private Security $security, private IriConverterInterface $iriConverter, ) {} @@ -44,11 +47,11 @@ class AccountingVoter extends Voter return false; } - private function voteOn(string $attribute, mixed $subject, ?User $user): bool + private function voteOn(string $attribute, mixed $subject, ?UserInterface $user): bool { switch ($attribute) { case self::EDIT: - return $user->hasRoles(['ROLE_ADMIN']) + return $this->security->isGranted('ROLE_ADMIN', $user) || $this->isOwnerOf($subject, $user); case self::VIEW: return true; @@ -57,7 +60,7 @@ class AccountingVoter extends Voter return false; } - private function voteOnUser(string $attribute, UserApiResource $owner, ?User $user): bool + private function voteOnUser(string $attribute, UserApiResource $owner, ?UserInterface $user): bool { if (!$user instanceof User) { return false; @@ -66,7 +69,7 @@ class AccountingVoter extends Voter switch ($attribute) { case self::EDIT: case self::VIEW: - return $user->hasRoles(['ROLE_ADMIN']) + return $this->security->isGranted('ROLE_ADMIN', $user) || $this->isOwnerOf($owner, $user); }