Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
333 views
in Technique[技术] by (71.8m points)

Why does a Firestore security rule using get() not work while another rule using resource.data works?

I've been working on a chat app in order to get used to Cloud Firestore.
Below is the structure of its database.

rooms
  ├ xxxxxx
  │  ├ messages
  │  │  ├ xxxxxx
  │  │  └ xxxxxx
  │  └ private
  │      └ allowed - members [xxxxxxxx, xxxxxxxx]
  └ xxxxxx
      ├ messages
      │  ├ xxxxxx
      │  └ xxxxxx
      └ private
          └ allowed - members [xxxxxxxx, xxxxxxxx]

The private subcollection under each chat room document has a single document with allowed as its ID.
allowed has members, which is an array field holding IDs of users allowed to use the chat room.

What I have to do first to fetch a particular chat room is to get the allowed document, as follows:

db.collectionGroup('private')
  .where('members', 'array-contains', userId)
  .get()
  .then(...)

I've already created an index on private for collection group queries, so the above code works.

However, if I add the following security rule, it fails with the error message of 'Uncaught (in promise) FirebaseError: Missing or insufficient permissions.'

match /{path=**}/private/{document} {
  allow read: if request.auth.uid
    in get(/databases/$(database)/documents/$(path)/private/$(document)).data.members;
}

This rule is for forbidding a user from accessing allowed if not a member of the room.
A query without .where(...) results in the same error.

On the other hand, the rule below works as expected.

match /{path=**}/private/{document} {
  allow read: if request.auth.uid in resource.data.members;
}

I know this rule is by far better, so I'll definitely use it, but I still wonder why the previous rule didn't work.
Would anyone clarify the cause please?


image

Is this possibly related in any way?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your security rule was written for a collectionGroup /{path=**}/private, for one thing - this rule, as written, applies to any collection named "private", regardless of where it is. Also, you try to use the variable $(rule), which I see no definition for.

Security rules only work with matching queries - you have to make sure your query explicity cannot result in a un-allowed document. IF the query could result in an un-allowed document (i.e. as specified by the security rule), then the ENTIRE query will be rejected - not just the un-allowed document. Security rules are all-or-nothing - that's why they scale.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...