API Platform version(s) affected: 4.3.5
Description
When a resource is behind a voter on Patch operation and custom logic is called with a Voter using securityPostDenormalize, the incoming document is still persisted and therefore is written in the database if a flush comes after.
AgentRole.php
#[ApiResource(operations: [
new Patch(
securityPostDenormalize: "is_granted('ROLE_UPDATE', object)",
extraProperties: ['throw_on_access_denied' => true],
),
])]
AgentRoleVoter.php
protected function supports(string $attribute, mixed $subject): bool
{
$supportAttributes = $attribute == 'ROLE_UPDATE';
$supportSubject = $subject instanceof AgentRole;
return $supportAttributes && $supportSubject;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
// some false logic
}
AgentRoleTest.php
use ResetDatabase;
public function testChangeAgentRoleToDev()
{
$client = static::createClientWithCredentials();
$dm = $this->getContainer()->get(DocumentManager::class);
$agentRoles = AgentRoleFactory::createSequence([
['agentId' => '1', 'roles' => ['ROLE_USER']],
['agentId' => '2', 'roles' => ['ROLE_USER']]
]);
$client->request('PATCH', '/agent_roles/1', [
'headers' => ['Content-Type' => 'application/merge-patch+json'],
'json' => [
'roles' => ['ROLE_USER', 'ROLE_DEV']
]
]);
$this->assertResponseStatusCodeSame(403); // OK
// I would need to use $dm->clear() to flush previous operation without persisting
// $dm->clear();
$currentUserRole = $dm->getRepository(AgentRole::class)->findOneBy([
'agentId' => 'user' // current logged user
]);
$currentUserRole->setRoles(['ROLE_ADMIN']);
$dm->persist($currentUserRole);
$dm->flush(); // <-------- this persist also the request operation which wasn't persisted on request execution
}
Before flush:

After:

API Platform version(s) affected: 4.3.5
Description
When a resource is behind a voter on Patch operation and custom logic is called with a Voter using
securityPostDenormalize, the incoming document is still persisted and therefore is written in the database if a flush comes after.AgentRole.php
#[ApiResource(operations: [ new Patch( securityPostDenormalize: "is_granted('ROLE_UPDATE', object)", extraProperties: ['throw_on_access_denied' => true], ), ])]AgentRoleVoter.php
AgentRoleTest.php
Before flush:

After:
