Firestore Rules For Admin

Viewed 147

Good day! Wrote rules for Firestore:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    function isSignIn() {
        return request.auth.uid != null
    }
  
    function isAdmin() {
        return exists(/databases/$(database)/documents/admins/$(request.auth.uid))
    }
    
    function isPublished() {
        return resource.data.published == true
    }

    match /instructions/{instructionId} {
      allow list:
        if isSignIn()
            &&  (isPublished() || isAdmin())
            &&  request.query.limit <= 10
    }
  }
}

I know that rules are not filters. I want to achieve a condition under which an administrator can view both published posts and unpublished posts, while regular users can only see published posts. The presence of a check for published forces the condition to be set at the application level.

firestore.collection("instructions")
   .whereEqualTo("published", true)
   .limit(10)
   .get()

Which, in principle, is logical if we want to show only published posts to ordinary users.

How can I make the administrator see all records? I have only one option - to remove the condition isPublished () || isAdmin () and make a separate view for the administrator without a publication condition. In this case, verification will have to be done on the client side, which is not good.

What can you advise?

1 Answers

=> You can save yourself some costs by using custom claims on the user account to identify privileged users (they come in on the context.auth object), rather than reading from a document. It requires some backend/cloud function code (custom claims can only be added to the user token from privileged/secure environments), but this is the approach I use extensively - no trusting of the client at all. Works best with a "login" style approach to privileges, relatively long lasting, so you don't invoke Cloud Functions too often.

=> the .whereEqualTo("published", true) is actually zero cost for the client - and since any request for documents that do NOT have published set will fail, there is no security risk - properly formed requests will succeed; poorly formed/deliberately malformed requests will fail (hence, "rules are not filters").

=> a separate rule for isAdmin() is perfectly reasonable and expected - if ANY rule matches, permission is granted; it doesn't have to be in the SAME rule.

Related