Loops available in rules for firestore?

2019-05-07 05:49发布

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');
}

1条回答
等我变得足够好
2楼-- · 2019-05-07 06:32

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.
查看更多
登录 后发表回答