Hi everyone!
Before describing my issue I’d like to give you a bit of context. I am working on a GraphQL server coded in Rust that uses MongoDB Rust crate as a Database driver. One of the main goals of this project is to have a very safe permissions system.
My problem is related to write permissions.
Let’s say I have the following object:
{
"_id" : ObjectId("5ed0d70c009dab1100a6209c"),
"name" : "toto",
"permissions" : {
"read" : [
"read1"
],
"write" : [
"write1"
],
},
}
When a user tries to update this type of object, before the server actually updates it, it needs to make sure that:
- It exists => return a “not found” error if it doesn’t
- The user has the required permissions to update it, in this case “write1” => return “insufficient permissions” if it doesn’t
Now the problem with this is that it requires 2 Database interactions, a find_one
for step 1 (to match the object itself) and a find_one_and_update
for step 2 (to match its permissions to the user permissions and update if they are correct).
But this means that if user A is trying to update an object, and user B is trying to delete the same object, user B delete request might go off between user A step 1 and step 2 of its update. And that would lead to an “insufficient permissions” error when in reality the object does not exist.
So what I wanted to do was generating a guid
before making the update, and then adding it to the updated object to check the result and ensure that the update went through (this would remove step 1 from the process and allow use to avoid mutex in our code since it is a big performance decrease). But this requires to be able to make a conditional update based on the field value and from what I’ve read there is no way to do that ($cond
is not available as an update operator: https://docs.mongodb.com/manual/reference/operator/update-field/).
So my question is would there be a way to have some sort of field-based conditional object update using MongoDB? I also wonder if there would be a way to find a solution to my problem using aggregation pipelines but I haven’t found much success in that either.