提问人:rkeet 提问时间:5/5/2023 最后编辑:rkeet 更新时间:5/22/2023 访问量:130
使用 PATCH 端点时,未使用 Api-Platform 触发 ChoiceValidator
ChoiceValidator not triggered using Api-Platform when using PATCH endpoint
问:
在 ApiPlatform 的 Github 上交叉发布,现在标记为“错误”:https://github.com/api-platform/api-platform/issues/2443
我正在为自己设置一个包含基础知识的骨架。其中一部分是可以具有角色的用户。角色不是实体,它仅以字符串形式存在,并且它们作为用户记录的一部分存储为列 (Postgres)。json
我面临的麻烦:用于创建和更新用户的 POST 和 PATCH 端点具有相同的约束。但是,PATCH 端点在尝试使用传入数据之前无法验证传入数据。
& 端点的配置如下:POST /api/users
PATCH /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
但是,永远不会调用该函数。我在该函数的第一行设置了一个断点,但它从未到达那里。(在使用 POST 终结点时调用它。Symfony\Component\Validator\Constraints\ChoiceValidator::validate
)
它没有使用验证器,而是继续,就好像内容有效一样,并尝试向 User 对象添加无效的“角色”值 ()。它甚至尝试这样做意味着它已经通过了验证阶段。INVALID
观察
- 对终结点使用相同的代码,其中 as 值失败,并按预期显示
POST /api/users
INVALID
422 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
输出消息来自该消息,用于检查已知角色数组 () 中是否存在提供的角色字符串值。detail
Role::addRole
INVALID
['ROLE_USER', 'ROLE_ADMIN']
答: 暂无答案
评论