skip to Main Content

I am using @angular/fire and I have a temples collection with below schema:

{
 name: 'Sri Chamundeshwari temple',
 address: 'Chamundi hills, Mysore',
 roles: {
  '[email protected]': 'owner',
  '[email protected]': 'admin',
  '[email protected]': 'member',
  '[email protected]': 'viewer'
 }
}

I want only the 4 users in the roles object to be able to access the temple document. Other users should be denied access.

I followed the guide in this link:
https://firebase.google.com/docs/firestore/solutions/role-based-access
and structured my security rules as below:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    
    match /temples/{temple} {
    
      function isSignedIn() {
        return request.auth != null;
      }
    
      function getRole(rsc) {
        return rsc.data.roles[request.auth.token.email];
      }

      function isOneOfRoles(rsc, array) {
        return isSignedIn() && getRole(rsc) in array;
      }

      allow read: if isOneOfRoles(resource, ['owner', 'admin', 'member', 'viewer']);
    }
  }
}

How should I write a suitable query to get all temple documents which is accessible to logged in user?

The guide does not describe anything about queries.

I tried the below queries and they are giving permission errors.

ERROR FirebaseError: Missing or insufficient permissions.

Let’s assume there are 10 temples in the collection.

User A has a role as viewer in 3 temples.

I am expecting that the below queries should return only 3 temples accessible to user A.

const q = query(
     collectionGroup(this.fireStore, "temples"), 
     where(`roles.${this.auth.currentUser?.email}`, 'array-contains', ['owner', 'administrator', 'member', 'viewer'])
);
const q = query(
        collection(this.fireStore, "temples"),
        where(`roles.${this.auth.currentUser?.email}`, 'array-contains', ['owner', 'administrator', 'member', 'viewer'])
);

firestore db screenshot

Update: As per @Frank van Puffelen’s answer, replaced the array-contains with in operator because in is the right one to use in this scenario and still receiving permission errors.

1

Answers


  1. You’re using the array-contains operator on the roles.${this.auth.currentUser?.email}, but that field isn’t an array.

    To filter in whether a non-array field has one of a number of values, use the in operator.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search