Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Security] Document is persisted before voters result on securityPostDenormalize

オープン
#8,429 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
52/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
静か
技術スタック
php

調査の方向性

securityPostDenormalize の処理と AgentRoleTest.php の再現ケースから始め、次に DocumentManager が拒否された PATCH オブジェクトをどのように処理するかを追跡します。示されているテストシナリオを実行し、後続の flush では失敗したリクエストによる変更が永続化されない一方で、明示的に変更された現在のユーザーのロールは引き続き永続化されることを確認します。

索引モデルが issue の本文から書いたものです。

説明

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:
Image

After:
Image

主要言語
PHP
スター
2.6k
フォーク
982
平均マージ
1日 16時間
マージ済み PR(30日)
59

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

api-platform/core のほかの issue

api-platform/core の issue をすべて見る

似ている issue

PHP の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。