Firestore rule succeeds in Playground and client but returns Permissions Denied using get method

走远了吗. 提交于 2021-01-07 02:56:54

问题


I have only one match statement and it is set to pass if the collection or document path is in the the user's permissions.read array. I'm only testing user u1 which has a permissions.read property.

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

I get the following responses when requesting the collection /companies/c1/departments/d1/employee or the document /companies/c1/departments/d1/employees/e1

  1. Success when tested in the Firestore rules playground
  2. Fails but returns correct response when tested locally using Flutter app on android emulator
  3. Fails and no results using Postman and Firestore REST API

This may have something to do with the way I'm using the get method since the match itself is not dependent on a where clause in the request or data contained in the resource itself. However, it seems that the data I've provided the match should be enough to determine if a single document or all documents in a collection requested will pass or fail since it is based solely on the resource requested and the permissions.read property for the requesting user.

Any help would be appreciated.

Here's more info:

My database has the following collections and documents:

users/u1
companies/c1/departments/d1/employees/(e1, e2)

User u1 has the following property:

{
  permissions: {
    read: [
      'companies/c1/departments/d1/employees',
      '/companies/c1/departments/d1/employees',
      'companies/c1/departments/d1/employees/e1',
      '/companies/c1/departments/d1/employees/e1'
    ]
  }
} 

Here's the Playground result:

Playground Result

Here's the Flutter request which is returning the correct data:

Firestore.instance
.collection('companies/c1/departments/d1/employees')
.document('e1')
.snapshots()

And the error:

W/Firestore(28552): (21.3.0) [Firestore]: Listen for Query(companies/c1/departments/d1/employees/e1) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}

Here's the Postman request which does not return any data:

https://firestore.googleapis.com/v1beta1/projects/my-project/databases/(default)/documents/companies/c1/departments/d1/employees/e1

And the error:

{
    "error": {
        "code": 403,
        "message": "Missing or insufficient permissions.",
        "status": "PERMISSION_DENIED"
    }
}

The errors seem to be the same.

It's also worth mentioning that authentication is working and simply changing the match statement to the following works fine on both Flutter and Postman with no errors:

match /{document=**} {
    allow read, write: if request.auth != null;
}

回答1:


SOLVED

You can not compare a path (document) to a string (values in permissions.read) which I'm doing here:

allow read: if document in get(/databases/$(database)/documents/users/$(request.auth.uid)).data.permissions.read;

FYI, while you can convert a string to a path, currently, there is no way to convert a path to a string. Even request.path is of type path so no luck there. If you want to compare the resource path to a value stored in a map or array you can store the path as a reference. However there is a limitation, you can only store references to documents not collections.



来源:https://stackoverflow.com/questions/63621376/firestore-rule-succeeds-in-playground-and-client-but-returns-permissions-denied

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!