Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[Security] Document is persisted before voters result on securityPostDenormalize

已关闭
#8,429 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
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
派生
989
平均合并
1 天 23 小时
30 天内合并 PR
102

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

api-platform/core 的其他 Issue

查看 api-platform/core 的全部 Issue

相似的 Issue

更多 PHP Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。