0
votes

I'm trying to write a rule in firebase security console with get() but I can't get resource data anyhow... I want documents and their subcollections to be readable to user, if user uid is in document field, array or map.

My collection structure: /boards/(boardId)/...much more

Fields in (boardId) document:

  • name: "Board name"
  • ownerId: "MYID12345"
  • guestsId(array): ["MYID12345"]
  • guestsMap(map): [MYID12345: true]

Security rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {   
    match /boards/{boardId=**} {
      // rules here
    }
  }
}

What I have tried so far:

allow read: if get(/databases/$(database)/documents/boards/$(boardId)).data.guestsMap[request.auth.uid] == true;
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsMap;
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsMap[true];

allow read: if get(/databases/$(database)/documents/boards/$(boardId)).request.data.guestsId[request.auth.uid];
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsId;
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).request.data.guestsId;

allow read: if get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId == request.auth.uid;
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId == "MYID12345";
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).resource.data.ownerId == request.auth.uid;
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).request.data.ownerId == request.auth.uid;

None of these worked, always getting:

ERROR FirebaseError: Missing or insufficient permissions.

allow read: if true, makes the application run normally. I'm sticking to the documentation but it's not working for me...

@update

match /boards/{boardId=**} {
  allow read: if resource.data.ownerId == request.auth.uid;
}

Also can't use it like this, because then, every subcollection is looking for ownerId field in it's documents, and ownerId or friend list array are only in board document.

@update

I tried to do like so, but it didn't help:

match /boards/{boardId} {
    allow read, write: if request.auth.uid in resource.data.guestsId  || request.auth.uid == resource.data.ownerId;
    allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid));

    function passResource() {
        return request.auth.uid in resource.data.guestsId  || request.auth.uid == resource.data.ownerId;
    }

    match /categoryList/{categoryId} {
        allow read, write: if passResource();
    }

    ...
}

What am I missing here?

1

1 Answers

0
votes

Okay I found a working solution:

  match /databases/{database}/documents {  
    match /boards/{boardId} {
      allow read: if request.auth.uid in resource.data.guestsId  || request.auth.uid == resource.data.ownerId;
      allow write: if request.auth.uid == resource.data.ownerId;
      allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid));

      function isAllowed() {
        return request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsId || request.auth.uid == get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId;
      }
      match /categoryList/{category} {
        allow read, write: if isAllowed();

        match /taskList/{task} {
            allow read, write: if isAllowed();
        }
      }
      ...
  }

Also funny it didn't want to work like this:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {  
    match /boards/{boardId=**} {
      allow read, write: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsId || request.auth.uid == get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId;
      allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid));
    }
 }

because:

Error: simulator.rules line [5], column [49]. Property guestsId is undefined on object.