使用 PATCH 端点时,未使用 Api-Platform 触发 ChoiceValidator

ChoiceValidator not triggered using Api-Platform when using PATCH endpoint

提问人:rkeet 提问时间:5/5/2023 最后编辑:rkeet 更新时间:5/22/2023 访问量:130

问:

在 ApiPlatform 的 Github 上交叉发布,现在标记为“错误”:https://github.com/api-platform/api-platform/issues/2443


我正在为自己设置一个包含基础知识的骨架。其中一部分是可以具有角色的用户。角色不是实体,它仅以字符串形式存在,并且它们作为用户记录的一部分存储为列 (Postgres)。json

我面临的麻烦:用于创建和更新用户的 POST 和 PATCH 端点具有相同的约束。但是,PATCH 端点在尝试使用传入数据之前无法验证传入数据。

& 端点的配置如下:POST /api/usersPATCH /api/users/:uuid

ApiPlatform\Metadata\Post:
    processor: App\User\PasswordHasher
    normalizationContext:
        groups:
            - user:item
    denormalizationContext:
        groups:
            - user:post
    validationContext:
        groups:
            - user:post
ApiPlatform\Metadata\Patch:
    processor: App\User\PasswordHasher
    normalizationContext:
        groups:
            - user:item
    denormalizationContext:
        groups:
            - user:patch
    validationContext:
        groups:
            - user:patch

对此的验证配置如下:

roles:
    - Choice:
        #  callback: [ App\Role\Role, getRoles ]     # <-- Alternative, same result
        choices: [ 'ROLE_USER', 'ROLE_ADMIN' ]  
        multiple: true
        message: 'The role "{{ value }}" is not a valid role.'
        min: 0
        minMessage: 'You must select at least {{ limit }} choice(s).'
        groups:
            - user:post
            - user:patch

调试时,我发现该类被实例化并且存在正确的选项:Symfony\Component\Validator\Constraint\Choice

Instantiated Choice Constraint object

但是,永远不会调用该函数。我在该函数的第一行设置了一个断点,但它从未到达那里。(使用 POST 终结点时调用它。Symfony\Component\Validator\Constraints\ChoiceValidator::validate)

它没有使用验证器,而是继续,就好像内容有效一样,并尝试向 User 对象添加无效的“角色”值 ()。它甚至尝试这样做意味着它已经通过了验证阶段。INVALID


观察

  • 对终结点使用相同的代码,其中 as 值失败,并按预期显示POST /api/usersINVALID422 Unprocessable Content
  • 由于 POST 和 PATCH 端点对资源(实体)和约束具有相同的配置,因此我希望处理上的差异是由于 HTTP 方法造成的
    • POST调用函数ChoiceValidator::validate
    • PATCH 不调用函数ChoiceValidator::validate

上下文的其他代码

Behat 是流程和数据验证的首选功能测试框架。以下是 2 个测试,一个用于 POST,另一个用于 PATCH,用于验证尝试保存是否应该失败。INVALID

POST /api/users- 这个通过

    # Purpose: validate that an administrator cannot create a user with an invalid role
    Scenario Outline: An administrator cannot create a user with an invalid role
        Given there is no user with email "[email protected]"
        And add "Accept" header equal to "<accept>"
        When a POST request is sent to "/api/users" with body:
        """
        {
            "email": "[email protected]",
            "plainPassword": "SuperSecretPassword@123!",
            "roles": <roles>
        }
        """
        Then the response status code should be 422
        And the response should be in JSON
        And a user with email "[email protected]" should not exist
        And the header "Content-Type" should contain "application/problem+json"
        And the header "Content-Type" should contain "charset=utf-8"
        And the JSON should be a valid item according to the schema "exception.schema.json"

        Examples:
            | accept              | roles                     |
            | application/json    | ["INVALID"]               |
            | application/ld+json | ["INVALID", "ROLE_ADMIN"] |

PATCH /api/users/:uuid- 这个失败了

    # Purpose: validate that an administrator cannot patch a user with an invalid role
    Scenario Outline: An administrator cannot patch a user with an invalid role
        Given there is no user with email "[email protected]"
        And there is no user with uuid "1a2b3c4d-1a2b-1a2b-1a2b-1a2b3c4d5e6f"
        And there is a user with email "[email protected]" and uuid "1a2b3c4d-1a2b-1a2b-1a2b-1a2b3c4d5e6f"
        And add "Content-Type" header equal to "application/merge-patch+json"
        When a PATCH request is sent to "/api/users/1a2b3c4d-1a2b-1a2b-1a2b-1a2b3c4d5e6f" with body:
        """
        {
            "roles": <roles>
        }
        """
        Then the response status code should be 422
        And the response should be in JSON
        And the stored value for roles of user with email "[email protected]" should not contain roles:
            | <roles> |
        And the header "Content-Type" should contain "application/problem+json"
        And the header "Content-Type" should contain "charset=utf-8"
        And the JSON should be a valid item according to the schema "exception.schema.json"

        Examples:
            | roles                          |
            | ["INVALID"]                    |
            | ["INVALID", "ANOTHER_INVALID"] |

失败步骤的输出:

    Examples:
      | roles       |
      | ["INVALID"] |
        Failed step: Then the response status code should be 422
        Current response status code is 404, but 422 expected. (Behat\Mink\Exception\ExpectationException)
        │
        │  JSON body:
        │  {
        │      "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10",
        │      "title": "An error occurred",
        │      "detail": "The role 'INVALID' does not exist.",
        │      "trace": [
        │          // THE STACK TRACE HERE

输出消息来自该消息,用于检查已知角色数组 () 中是否存在提供的角色字符串值。detailRole::addRoleINVALID['ROLE_USER', 'ROLE_ADMIN']

symfony 验证 api-platform.com symfony6

评论


答: 暂无答案