api-platform / api-platform/core
[Security] Document is persisted before voters result on securityPostDenormalize
- 主要語言
- PHP
- 星號
- 2.6k
- 分支
- 980
- 平均合併
- 2 天 4 小時
- 30 天內合併 PR
- 49
描述
**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
```php
#[ApiResource(operations: [
new Patch(
securityPostDenormalize: "is_granted('ROLE_UPDATE', object)",
extraProperties: ['throw_on_access_denied' => true],
),
])]
```
AgentRoleVoter.php
```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
```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:
貢獻指南
研究方向
Start with the securityPostDenormalize processing and the AgentRoleTest.php reproduction, then trace how the DocumentManager handles the denied PATCH object. Run the shown test scenario and verify that a later flush does not persist changes from the failed request while still persisting the explicitly changed current-user role.
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- php
- 領域
- authorization, databases
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 52/100