Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loops available in rules for firestore?

I wonder if there is any simpler way to achieve this rule. Just started to experiment with firestore.

match /emails/{emailId} {

    allow write: if request.resource.data.attachments.size() == 0
    || request.resource.data.attachments.size() == 1 && request.resource.data.attachments[0].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[0].filetype == 'image/png' || request.resource.data.attachments[0].filetype == 'image/jpg' || request.resource.data.attachments[0].filetype == 'application/vnd.ms-excel')
    || request.resource.data.attachments.size() == 2 && request.resource.data.attachments[0].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[0].filetype == 'image/png' || request.resource.data.attachments[0].filetype == 'image/jpg' || request.resource.data.attachments[0].filetype == 'application/vnd.ms-excel') && request.resource.data.attachments[1].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[1].filetype == 'image/png' || request.resource.data.attachments[1].filetype == 'image/jpg' || request.resource.data.attachments[1].filetype == 'application/vnd.ms-excel')
    || request.resource.data.attachments.size() == 3 && request.resource.data.attachments[0].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[0].filetype == 'image/png' || request.resource.data.attachments[0].filetype == 'image/jpg' || request.resource.data.attachments[0].filetype == 'application/vnd.ms-excel') && request.resource.data.attachments[1].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[1].filetype == 'image/png' || request.resource.data.attachments[1].filetype == 'image/jpg' || request.resource.data.attachments[1].filetype == 'application/vnd.ms-excel') && request.resource.data.attachments[2].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[2].filetype == 'image/png' || request.resource.data.attachments[2].filetype == 'image/jpg' || request.resource.data.attachments[2].filetype == 'application/vnd.ms-excel')
    || request.resource.data.attachments.size() == 4 && request.resource.data.attachments[0].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[0].filetype == 'image/png' || request.resource.data.attachments[0].filetype == 'image/jpg' || request.resource.data.attachments[0].filetype == 'application/vnd.ms-excel') && request.resource.data.attachments[1].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[1].filetype == 'image/png' || request.resource.data.attachments[1].filetype == 'image/jpg' || request.resource.data.attachments[1].filetype == 'application/vnd.ms-excel') && request.resource.data.attachments[2].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[2].filetype == 'image/png' || request.resource.data.attachments[2].filetype == 'image/jpg' || request.resource.data.attachments[2].filetype == 'application/vnd.ms-excel') && request.resource.data.attachments[3].fileSize < 3 * 1024 * 1024 && (request.resource.data.attachments[3].filetype == 'image/png' || request.resource.data.attachments[3].filetype == 'image/jpg' || request.resource.data.attachments[3].filetype == 'application/vnd.ms-excel');
}
like image 683
Mugetsu Avatar asked Mar 11 '18 22:03

Mugetsu


People also ask

What language are firestore rules written?

Cloud Firestore and Cloud Storage rules use a language based on the Common Expression Language (CEL), that builds on CEL with match and allow statements that support conditionally granted access.

What firestore rules?

Cloud Firestore Security Rules allow you to control access to documents and collections in your database. The flexible rules syntax allows you to create rules that match anything, from all writes to the entire database to operations on a specific document.

How do I add rules to firestore?

To set up and deploy your first set of rules, open the Rules tab in the Cloud Firestore section of the Firebase console. Write your rules in the online editor, then click Publish.


1 Answers

We don't allow loop constructs in Rules because we rely upon several optimization techniques that are much harder with more complex structures. We also don't charge compute time for Rules execution, which means we don't want them getting too complex and potentially abusive.

With the repetition in your rules, I'd highly encourage using the function() feature to simplify. For example this is < 1/3 the size:

match /emails/{emailId} {
    function attachments (){
      return request.resource.data.attachments();
    }

    function attach_cnt () {
      return attachments().size();
    }

    function valid_size(attach) {
      return attachments()[attach].fileSize < 3 * 1024 * 1024;
    }

    function valid_type(attach) {
      return (attachments()[attach].filetype == 'image/png' 
         || attachments()[attach].filetype == 'image/jpg'
         || attachments()[attach].filetype == 'application/vnd.ms-excel');
    }

    allow write: (attach_cnt() < 1 || (valid_size(0) && valid_type(0)))
    && (attach_cnt() < 2 || (valid_size(1) && valid_type(1)))
    && (attach_cnt() < 3 || (valid_size(2) && valid_type(2)))
    && (attach_cnt() < 4 || (valid_size(3) && valid_type(3)))
}

Here's how I simplified it (worth double-checking as I might have mistyped).

  1. I made a function attachments for the request data being accessed since it's used a bunched - this made it a lot easy skim the rules.
  2. I made a function attach_cnt for the number of attachments since that was checked a lot.
  3. Now I saw each attachment had a file size constraint, so I made a function valid_size for that test, using a parameter attach that I could pass it.
  4. Next up was function valid_type which worked the same way, but did the check to make sure it was a valid type.
  5. Now it was obvious that the same checks where being performed for attachment 0 for requests that had 2-4 items, etc. Reordering some of the logic enables you to only ever check each attachment once.
like image 99
Dan McGrath Avatar answered Sep 23 '22 02:09

Dan McGrath