Interpreting the get(/databases/) call

34 views
Skip to first unread message

M Mathems

unread,
May 5, 2023, 1:05:11 PMMay 5
to google-cloud-firestore-discuss

Hi

I am looking at some writing authored by Rachel Myers of the Firebase team, and I trust what she has written.  You can notice the full writing here.

I am interested in a confirmation of what some code actually means, and it's to do with the get(/databases/) call for Firestore's security rules.

The exert of Rachel's code is:

match /categories/{category} {
      allow read: if true;
      allow write: if (exists(/databases/$(database)/documents/admins/$(request.auth.uid))
      || exists(/databases/$(database)/documents/product/owner/$(request.auth.uid)))
      && get(/databases/$(database)/documents/users/$(request.auth.uid))
         .data.passChallenge == true
      && get(/databases/$(database)/documents/users/$(request.auth.uid))
         .data.karma > 5;
    }

The question I have is, does the code highlighted in blue mean that the field 'passChallenge' is being sought within documents that are in the collection (or sub-collection) called 'users'?

Impliedly, the question is also, is the map of fields and their values created by the '.data' attribute of the get(/databases/) function, regarding the 'users' collection exclusively?

With thanks.

Denver Coneybeare

unread,
May 12, 2023, 11:54:16 PMMay 12
to google-cloud-firestore-discuss
I'm not sure that I fully understand your question, but I'll try to respond as best I can.

The call to get(/databases/$(database)/documents/users/$(request.auth.uid))  will load a single document in the Cloud Firestore database (not a collection, or a sub-collection). The given path is an "absolute path" and must begin with  /databases/$(database)/documents. The value of $(request.auth.uid) will be replaced by the UID of the currently-logged in user. For example, if the UID of the currently-logged in user is "user123" then the get(...) call will load the document at the path users/user123. Then, .data.passChallenge will load the value of the passChallenge field in the users/user123 document and compare it to true.

So in English, this security rule means, first of all, that any user can read any document in the /categories collection. However, write operations are denied unless some specific criteria are met. Again, let's assume that the UID of the currently-logged in user is "user123". Then, first, one of these two documents must exist: admins/user123 or owner/user123. If neither of those documents exist then the write operation will be denied. If, however, one (or both) of those documents exist then the request will be denied unless the passChallenge field of the document users/user123 is true and the karma field of that same document has a value greater than 5.

I hope this helps clarify things.

M Mathems

unread,
May 15, 2023, 8:51:26 AMMay 15
to google-cloud-firestore-discuss
Hi

Thank you for your response and your clear and thorough explanations.  Very helpful.

I can understand everything you have explained, but in mind I have an alternate understanding on one point you touched on, and that's the meaning of the $(request.auth.uid) part of the call.

So, I agree with you that the $(request.auth.uid) part of the call is to match the current-user, but I have recently understood that the call has a scope that is limited to the collection (or sub-collection, as the case may be) above it.  For example, in Rachel's code, the collection/sub-collection above the $(request.auth.uid) call was 'users', and it was 'admins' and it was 'owner'.  So, the check for the current-user's ID (to my understanding) would be limited to the relevant collection/sub-collection.  Firstly, would this be accurate please?

The point on which my alternate understanding sits, is that the $(request.auth.uid) variable would not be the document-id of the document, or it needn't be, that, the call would check for a document within the relevant collection/sub-collection which features a field holding a field-value that is equal to the current user's UID.  So, for example, if the 'users' collection of Rachel's code has documents in it, and a field of those documents is called 'authorID', and then in one of those documents the value of 'authorID' is that of the current user's ID, then that is the document that get() shall get, and it would be the value of the same document's 'passChallenge' field that must be 'true' for the allow-write condition.  Please comment on the accuracy of this view.

If the $(request.auth.uid) part of the get(/databases/) call is only seeking a document with an ID that is equal to the ID of the current user, then, under what circumstances would Firestore produce a document with an ID that is equal to the current user's ID please?

M Mathems

unread,
May 15, 2023, 10:17:56 AMMay 15
to google-cloud-firestore-discuss

Hi

Is it at all possible that your explanation highlighted below is incorrect please?  Because thinking about it, it amounts to an admission that Firestore's get(/databases/) function call will never ever work?

"The call to get(/databases/$(database)/documents/users/$(request.auth.uid))  will load a single document in the Cloud Firestore database (not a collection, or a sub-collection). The given path is an "absolute path" and must begin with  /databases/$(database)/documents. The value of $(request.auth.uid) will be replaced by the UID of the currently-logged in user. For example, if the UID of the currently-logged in user is "user123" then the get(...) call will load the document at the path users/user123. Then, .data.passChallenge will load the value of the passChallenge field in the users/user123 document and compare it to true."

On Saturday, 13 May 2023 at 04:54:16 UTC+1 dcon...@google.com wrote:

Denver Coneybeare

unread,
May 26, 2023, 3:00:01 AMMay 26
to google-cloud-firestore-discuss
Yes, it will work. You have to incorporate the UID of the currently-logged-in user in the document's path. 
Reply all
Reply to author
Forward
0 new messages