1

Imagine a User Document which holds a property "restaurants" witch again holds keys for all restaurant he is responsible for. I want to implement a security rule which only allows updating the property "restaurants" if the changed restaurant-id in the update, references a restaurant owned by the user. Therefore in security rules i want to detect the changed-restaurant-id, load corresponding restaurant-doc and check if the field "owner" inside the restaurant-doc is equal the user-id.

I was already able to implement a rule to check only 1 Id was modified by implmenting something like this:

function hasSingleChange(){
    let changedKeys = request.resource.data.diff(resource.data).affectedKeys()
    return changedKeys.size() == 0;
}

Now I wanted to get the the specific Id that changed and use it for building the query for the restaurant:

function getChangedKeys() {
    let changedKeys = request.resource.data.diff(resource.data).affectedKeys()
    return changedKeys[0]
}

But unfortunately "return changedKeys[0]" will not work as affectedKeys returns a Set with limited operations available.

Is there an other way around to load a document in security-rules, based on changed property to be able to apply checks on this changed, referenced document?


Edit

Let me explain you what i actually want to solve with this. I have a Domain consisting of graphs, nodes and users as shown here: enter image description here What I want to accomplish is that users can access read/update/delete a node if the node is in a at least one graph which the user is the owner for. In the example above the user should have acess to node "n1" but not to node "n2". My idea was to check the permission on the node as following:

match /nodes/{nodeId} {
    allow read: if resource.data.graphs.keys().hasAny(get(/databases/$(database)/documents/users/$(request.auth.uid)).data.graphs.keys());

I guess this would work (?). But I need somehow to protect the user-Document to allow only writes to the "graphs" field if the user is listed as owner in the graph. Thats why I want to add another security-rule, something like this:

match /users/{userId} {
    allow update: if request.auth.uid == userId && hasSingleChange() && get(/databases/$(database)/documents/graphs/getChangedKey()).data.owner).keys().hasAny($(userId))
}

function hasSingleChange(){
    let changedKeys = request.resource.data.diff(resource.data).affectedKeys()
    return changedKeys.size() == 0;
}

//To get the id of the changed graph
function getChangedKey() {
    let changedKeys = request.resource.data.diff(resource.data).affectedKeys()
    return changedKeys[0];
}

But as mentioned this is not working as I am unable to extract the changed graph-Id to lookup the document (getChangedKey not working). Maybe there is another way arround to fullfill my requirements? What I try to avoid is to entitle the userId directly on the node, as I would have to update a lot of nodes if someone entitles a new user to a specific graph.

KindaOk
  • 21
  • 3

1 Answers1

0

As you want an end-user to be able to modify only a document's field. You can check the section “Preventing some fields from being changed ” by referencing the documentation. You can try with the permission below.

 allow update: if (!request.resource.data.diff(resource.data).affectedKeys()
        .hasAny(['A', 'B']));

You check the discussion on stackoverflow link & Stackoverflow url.

Monali Ghotekar
  • 359
  • 1
  • 7
  • I have already looked through the documentation up and down and also seen the section you have pointed out. Unfortunately this does not help me, as I do not have 'A' or 'B' hardcoded in advance. If I would be able to read those values dynamically out of DB I could solve my issue. F.e. hasAny(get('documentID').owner). But this seems not to be possible. – KindaOk Sep 24 '22 at 07:49
  • Have you checked the article https://articles.wesionary.team/all-you-need-to-know-about-cloud-firestore-security-rules-d00af7a65bfd in section Access documents in the database, describe the similar use case. Please refer to Firebase documents for Access other documents https://firebase.google.com/docs/firestore/security/rules-conditions?authuser=0#access_other_document for details – Monali Ghotekar Sep 27 '22 at 07:15