-
-
Notifications
You must be signed in to change notification settings - Fork 158
Add equivalent of AttrCapabilities for relationships #1187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Design updateIn the proposal above, Splitting AllowSetThe used terminology is becoming non-intuitive and requires explanation. That's not a good sign. HTTP status codeAs it turns out, Generally, failures during write operations return 422, while blocked query string parameters return 400. The latter is required by JSON:API. AllowView / CanIncludeTurning off Hiding a relationship should hide the entire relationship, not just its data. Rendering links to something you're trying to hide is counterproductive. Regarding hiding related resources when
However, note that blocking I've obsoleted So there's no interaction between |
Is your feature request related to a problem?
This design is based on the community request at https://gitter.im/json-api-dotnet-core/Lobby?at=63199f777ccf6b6d45c52943.
Describe the solution you'd like
Currently, developers can control which operations are allowed declaratively per JSON:API attribute in the following way:
If no capabilities are set in
[Attr]
, what's set inIJsonApiOptions.DefaultAttrCapabilities
(which defaults toAttrCapabilities.All
) is used.The proposal here is to add a similar feature for relationships. It would enable the next example:
The effective relationship capabilities would likewise be determined by falling back to what's set on
IJsonApiOptions
, defaulting toAll
. When an incoming request violates these constraints, an appropriate HTTP error is returned for one of the violations (the order is undefined and we won't aggregate all violations; I'm assuming that's howAttrCapabilities
works today). Similarly to howAttrCapabilities
is implemented, custom logic in resource definitions is not constrained by relationship capabilities. In caseAllowView
is blocked, we need to take precautions to never return the relationship in any response bodies.Proposed capabilities to add:
Alternative solutions and open questions
List of capabilities
We could split
Has[One|Many]Capabilities.AllowSet
into.Clear
and.Assign
, or add these while keepingSet
(which implies both)..Clear
for a to-one relationship means assigningnull
and for a to-many relationship it means assigning an empty array..Assign
for a to-one relationship means assigning a non-null value and for a to-many relationship it means assigning a non-empty array.We can't further distinguish between "assign from empty" vs "replace the existing value" for a to-one relationship, because it would require fetching the currently stored value first, which we're trying to avoid for performance reasons.
The split could be done at a later time by adding the Clear/Assign members next to the existing Set member. On the other hand, there's no good reason to postpone it if it's considered useful to have them today. I can't think of a reason why the need for them would increase in the future.
HTTP status code
Today JsonApiDotNetCore returns 400 for bad requests, but 422 when the problem is in the request body. Because setting a relationship could be done from:
adhering to the existing rule means to return 422 in the first two cases, but 400 in the last one. The alternative is to break with the rule and always return HTTP 400 on capabilities violations. I'm not sure what the right choice is here.
Meaning of
AllowView
When blocked, this could either mean hiding the relationship data (type + id), or the relationship itself (data + links). And this raises the question of how it interacts with includes from query strings. Today we have the boolean
CanInclude
property on HasOne/HasMany relationships, which determines whether?include=
can contain the relationship. Should blockingAllowView
implicitly mean to also block?include=
, or should we leave this up to the user? The latter means more flexibility, but at the cost of unintentionally forgetting to setCanInclude = false
in addition to blockingAllowView
, resulting in the wrong outcome. And should we deprecateCanInclude
in favor of adding.AllowInclude
to the enumerations?The text was updated successfully, but these errors were encountered: