1

I'm trying to validate a read in firestore, based on another document.

The data structure consists of 2 collections: "execution" and "test" .

In the test collection there is only 1 document, with the following id: SRJKCxU4HVDBdB3qyfzG, and theese values:

admin true id: "SRJKCxU4HVDBdB3qyfzG" test: 1

My security rules look like this:

service cloud.firestore {
  match /databases/{database}/documents {

    function testFunction(testId) {
      // return exists(/databases/$(database)/documents/test/$(testId));
      return get(/databases/$(database)/documents/test/$(testId)).data.id == "SRJKCxU4HVDBdB3qyfzG";
    }

    match /execution/{exeid} {
      allow read, write: if testFunction("SRJKCxU4HVDBdB3qyfzG");
    }

  }
}

If I use return exists(/databases/$(database)/documents/test/$(testId)); everything work's as expected. But no matter what I can't get this line to work return get(/databases/$(database)/documents/test/$(testId)).data.id == "SRJKCxU4HVDBdB3qyfzG".

I really hope that I am missing simple and obvious? Any help is very common. I have also created a demo firebase project and stackblitz if necessary.

Thanks for the help.

Update - temporary solution Because of a firestore security rule bug, the data property is not populated. This will be fixed. The temporary solution for get() to work is the following:

get(path).data.prop || get(path).prop

DauleDK
  • 3,313
  • 11
  • 55
  • 98
  • I'm curious as to why you wouldn't just use `exists`? – Dan McGrath Oct 10 '17 at 15:18
  • the code is simplified. The real use case is to lookup a value on `get(/databases/$(database)/documents/test/$(testId))` and use this for validating. – DauleDK Oct 11 '17 at 07:14
  • 1
    Ah, okay. Using id as the example is likely misleading then since you should always be using exists for checking if a document exists. You can do both exists and get on the same document in a rule without it doing extra lookups (our system dedup these requests) – Dan McGrath Oct 11 '17 at 08:09

2 Answers2

5

resource.id doesn't exist yet, which is why you cannot do this.

Dan McGrath
  • 41,220
  • 11
  • 99
  • 130
  • I am not sure I follow you here? This document: `/databases/$(database)/documents/test/SRJKCxU4HVDBdB3qyfzG` certainly exists? – DauleDK Oct 11 '17 at 07:11
  • As a feature of the system. Get() returns a `resource` and we don't support id on this yet. – Dan McGrath Oct 11 '17 at 08:04
  • Ok sure enough. But I'm trying to retrieve a data property on the resource, called id. And this code `return get(/databases/$(database)/documents/test/$(testId)).data.id == "SRJKCxU4HVDBdB3qyfzG"` does not work as expected. – DauleDK Oct 11 '17 at 08:12
  • I'll have check our system tomorrow morning to see what's up there – Dan McGrath Oct 11 '17 at 08:16
  • I can add you to the test-firebase projected I created if you like? This test project and the stackblitz are the only moving parts :) – DauleDK Oct 11 '17 at 08:19
  • Thanks! I realized that I can use if(resource == null) to check if the resource exists or not in the firestore – Rodrigo João Bertotti Jun 24 '20 at 14:21
4

According to this Stack Overflow question, there is currently a bug in Firebase security rules:

Because the bug is that data object isn't populated, you should check both properties. There's no ETA for launching a solution on this bug..

The temporary solution is to change the code to this:

return get(/databases/$(database)/documents/test/$(testId)).id == "SRJKCxU4HVDBdB3qyfzG" || get(/databases/$(database)/documents/test/$(testId)).data.id == "SRJKCxU4HVDBdB3qyfzG"

DauleDK
  • 3,313
  • 11
  • 55
  • 98
  • .id and data.id are different fields, so this is incorrect. data.id is a user defined field named id in a document rather than the id of a document. – Dan McGrath Oct 11 '17 at 08:06
  • let me just check this. – DauleDK Oct 11 '17 at 08:07
  • You can test it in the console. Create a new document, then add a field named id with a different value. – Dan McGrath Oct 11 '17 at 08:10
  • I follow you. But I can just observe that `get(path).data.prop` is not working as expected. I need this in the rule for it to work `get(path).prop || get(path).data.prop` – DauleDK Oct 11 '17 at 08:17
  • 1
    as noted in the other question, this is a bug that accords if you only use `get()` and don't have any other reference to `resource.data` or `request.resource.data` in your ruleset. We're working to fix it. – Dan McGrath Oct 13 '17 at 13:48