feat(api): add V2 JSON:API relationship endpoint for user game list entry resources#5041
Conversation
Confidence Score: 5/5Safe to merge. Auth logic is correctly layered and all access paths are covered by tests. The authorization design is sound: the top-level policy gate requires authentication, and relatableQuery enforces per-kind access before handing off to the framework filter pipeline. The default-to-Play fallback and the Develop self-only change are both tested end-to-end. No missing guards or logic gaps found. No files require special attention. Reviews (4): Last reviewed commit: "Merge branch 'master' into v2-user-game-..." | Re-trigger Greptile |
| 'code' => 'invalid_filter', | ||
| 'title' => 'Invalid Filter', | ||
| 'detail' => "Unknown user game list kind [{$normalizedValue}].", | ||
| ]); |
There was a problem hiding this comment.
Non-blocking question: Why 400 and not 422?
400 Bad Request: The server cannot understand the request because the syntax is broken (e.g., a missing comma in your JSON, or malformed text format).
422 Unprocessable Content: The JSON is structurally flawless and can be parsed, but the values inside fail server validation.
The Connect API uses 422 for invalid parameter values:
RAWeb/app/Connect/Support/BaseApiAction.php
Lines 65 to 73 in 2b1eee4
There was a problem hiding this comment.
Good question. I think we should keep a 400 here, mainly because it follows the JSON:API spec's documented pattern. The spec never uses a 422 anywhere, and whenever it mentions a query param the server can't handle, it consistently calls for throwing a 400:
If a server is unable to identify a relationship path or does not support inclusion of resources from a path, it MUST respond with 400 Bad Request.
If the server does not support sorting as specified in the query parameter sort, it MUST return 400 Bad Request.
If a server encounters a query parameter that does not follow the naming conventions above, or the server does not know how to process it as a query parameter from this specification, it MUST return 400 Bad Request.
laravel-json-api's query validation also defaults to a 400. This seems to be a consistent theme with JSON:API endpoints in particular.
There was a problem hiding this comment.
I asked AI:
The JSON:API specification requires 400 Bad Request for invalid filter values instead of 422 Unprocessable Entity. This is because 422 is reserved strictly for semantically invalid request bodies (data payload errors), whereas filters are treated as query parameters and fall under URL syntax or protocol errors.
I wonder if we should update the connect API. While most of the parameters are sent as POST data, they're still just URI query parameters.
There was a problem hiding this comment.
No strong feeling from me on the Connect API. If you think the 422 makes more sense for the Connect API, I think we should keep it. It's a custom RPC-style API, non-RESTful, that we can shape however we want.
This PR adds a V2 JSON:API relationship endpoint for
UserGameListEntryresources.The resource is accessible through a user relationship route:
GET /api/v2/users/{user}/user-game-list-entriesThings worth noting:
typecolumn is exposed askindto avoid colliding with JSON:API's top-level resourcetype.filter[kind]andfilter[gameId].filter[kind]acceptsplay,achievement_set_request,develop, orall. Unknown kinds return a 400.UserGameListEntryPolicy.playentries are visible to self+friends.achievement_set_requestentries are visible to all auth'd callers.developentries are not currently exposed through this endpoint (thoughfilter[kind]does recognize the value).-createdAt, and thegamerelationship can be included with?include=game.UserGameListEntryPolicy::view()dispatch.V1 to V2 mapping:
How to test this PR: