Jomy
Jomy

Reputation: 558

Firebase Firestore Database Rules: using arrays from another document

I am trying to make a web app that displays different elements based on what permissions I give to a user.

All the permissions are stored in the the Cloud Firestore database at /users/{userId} in the field "permissions", which is an array containing the permissionId's.

In /photo_libraries/{libraryId} I have a field called permissionId, which is a string.

I now want to give users that have the right permissionId to be able to read the document in /photo_libraries/{libraryId} that has that permissionId.

I've tried this:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {    
    
    match /users/{userId} {
        allow read: if request.auth.uid == userId;
    }
    
    match /photo_libraries/{libraryId} {
        allow read: if get(/database/$(database)/documents/photo_libraries/$(libraryId)).data.permissionId in get(/databases/$(database)/documents/users/$(request.auth.uid)).data.permissions;
    }
  }
}

But this doesn't seem to work, I'm quite new to the Firestore rules. Can anyone help me out?

P.S. This is how my database looks like: users

photo_libraries

This is the code I try to run:

const db = firebase.firestore(); const auth = firebase.auth();
auth.onAuthStateChanged(user => {
    if (user) {
        db.collection('photo_libraries').get().then(snapshot => {
            // set up the UI
        }, err => {
            console.log(err.message);
        });
    } else {
        // Logging out stuff
    };
});

In the console I get the error message:

Missing or insufficient permissions.

Thank you,

Jonas

Upvotes: 0

Views: 87

Answers (1)

l1b3rty
l1b3rty

Reputation: 3660

Try this:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {    
    
    match /users/{userId} {
        allow read: if request.auth.uid == userId;
    }
    
    match /photo_libraries/{libraryId} {
        allow read: if resource.data.permissionId in get(/databases/$(database)/documents/users/$(request.auth.uid)).data.permissions;
    }
  }
}

But a better solution would be to add the persmissions array as a custom claim, then you dont need to call get.

When querying Firestore make sure you are only querying the documents you can actually access. Look for "rules are not filter" on google and you will get plenty of hits on SO and in the official Firebase documentation.

Upvotes: 1

Related Questions