-
Notifications
You must be signed in to change notification settings - Fork 233
Description
Encountering an issue where running a transaction with 2 operations fails with a read permission denied error which if split into 2 separate transactions succeeds.
Expected Behavior
There shouldn't be a difference in outcome if the 2 separate operations in 2 separate transactions succeeds but the same 2 operations in a single transaction fails.
Current Behavior
This is happening partially because relationships are updated in a separate step.
I have a sample project where I have defined 3 models.
- Author -> AuthorBook -> Book
where AuthorBook is an entity and has a one to one relationship with Author and Book.
Author has a read permission that allows read if the user has access to Book. (The sample hardcodes this to allow access if the Book has id 1 or 2)
After the setup the state looks like this
- Book(b1)
- Book(b2)
- Author(a1) with AuthorBook(a1,b1)
The operations executed essentially adds AuthorBook(a1,b2) to Author and remove AuthorBook(a1,b1). When executing the transaction the failure occurs when the post processing of the relationships are being performed when Author needs to be read to apply the relationships.
The state of Author at the point of time the expression is evaluated is
- Author(a1) with AuthorBook(a1,null) which fails because the user doesn't have access to either b1 or b2 at this point in time
This is because AuthorBook(a1,b1) was already removed. In the prior step when AuthorBook(a1,b2) was to be set on Author what was set was AuthorBook(a1,null) because it was split into the 2 phases.
Possible Solution
I don't really know enough of how the permission evaluation works but if all inline checks are deferred, similarly to what's happening for newly created resources, when performing postProcessRelationships
then it should work. I don't know if this is a proper design or will break anything else though.
Steps to Reproduce (for bugs)
I have committed a project at https://github.com/justin-tay/elide-spring-boot-example/tree/permission-issue_elide-7.x which demonstrates the issue. The queries are in the README.md but I have reproduced them below.
Setup
curl --location --request PATCH 'http://localhost:8080/api/v1' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--data '[
{
"op": "add",
"path": "/author",
"value": {
"type": "author",
"id": "7f14b0c3-d0ed-436c-9843-6bfbf7342df6",
"attributes": {
"name": "Ernest Hemingway"
}
}
},
{
"op": "add",
"path": "/book",
"value": {
"type": "book",
"id": "1",
"attributes": {
"title": "The Old Man and the Sea"
},
"relationships": {}
}
},
{
"op": "add",
"path": "/book",
"value": {
"type": "book",
"id": "2",
"attributes": {
"title": "For Whom the Bell Tolls"
},
"relationships": {}
}
},
{
"op": "add",
"path": "/author/7f14b0c3-d0ed-436c-9843-6bfbf7342df6/authorBooks",
"value": {
"type": "authorBook",
"id": "e2d0e822-d94d-4e36-a592-ef4f2af89f75",
"attributes": {},
"relationships": {
"book": {
"data": {
"type": "book",
"id": "1"
}
}
}
}
}
]'
Operation with issue
curl --location --request PATCH 'http://localhost:8080/api/v1' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--data '[
{
"op": "add",
"path": "/author/1/authorBooks",
"value": {
"type": "authorBook",
"id": "bd71bc1a-dc41-4adb-bf17-610149429f68",
"attributes": {},
"relationships": {
"book": {
"data": {
"type": "book",
"id": "2"
}
}
}
}
},
{
"op": "remove",
"path": "/author/1/authorBooks",
"value": {
"type": "authorBook",
"id": "1",
"attributes": {},
"relationships": {}
}
}
]'