如何避免函数调用深度限制?

时间:2019-01-03 13:17:58

标签: firebase google-cloud-firestore firebase-security firebase-security-rules

我想知道是否有可能为我的以下代码避免Firestore安全规则的函数调用深度限制。

什么算作功能?只是我自己创建的还是size()之类的东西?

  function isValidItem(data, item) {
    return 
        ( // Person
          data.items[item].keys().hasAll(['image','type','name','job','age','party','experience'])
          && data.items[item].image.size() >= 1 && data.items[item].image.size() <= 200
          && data.items[item].type.size() >= 5 && data.items[item].type.size() <= 10
          && data.items[item].name.size() >= 1 && data.items[item].name.size() <= 50
          && data.items[item].job.size() >= 1 && data.items[item].job.size() <= 50
          && data.items[item].party.size() >= 1 && data.items[item].party.size() <= 50
          && data.items[item].experience.size() >= 1 && data.items[item].experience.size() <= 50
          && data.items[item].age.matches('^[0-9]+$')
        )
        || 
        ( // Party
            data.items[item].keys().hasAll(['image','type','name','orientation','experience','promi'])
          && data.items[item].image.size() >= 1 && data.items[item].image.size() <= 200
          && data.items[item].type.size() >= 5 && data.items[item].type.size() <= 10
          && data.items[item].name.size() >= 1 && data.items[item].name.size() <= 50
          && data.items[item].orientation.size() >= 1 && data.items[item].orientation.size() <= 50
          && data.items[item].experience.size() >= 1 && data.items[item].experience.size() <= 50
          && data.items[item].promi.size() >= 1 && data.items[item].promi.size() <= 50
        );
  }

  function itemsAreValid(data) {
    return data.items.size() >= 1
        && data.items.size() <= 10
        && isValidItem(data, 0)
        && (data.items.size() < 2 || isValidItem(data, 1))
        && (data.items.size() < 3 || isValidItem(data, 2))
        && (data.items.size() < 4 || isValidItem(data, 3))
        && (data.items.size() < 5 || isValidItem(data, 4))
        && (data.items.size() < 6 || isValidItem(data, 5))
        && (data.items.size() < 7 || isValidItem(data, 6))
        && (data.items.size() < 8 || isValidItem(data, 7))
        && (data.items.size() < 9 || isValidItem(data, 8))
        && (data.items.size() < 10 || isValidItem(data, 9));
  }

  function isValidTitle(data) {
    return data.title.size() >= 1 
        && data.title.size() <= 200
  }

  function isAuthed() {
    return request.auth.uid != null
        && request.auth.token.email_verified == true;
  }

  allow create, update:
    if isAuthed()
    && request.resource.data.user == request.auth.uid
    && request.resource.data.status == "review"
    && isValidTitle(request.resource.data)
    && itemsAreValid(request.resource.data);

2 个答案:

答案 0 :(得分:2)

我与Firebase安全规则小组进行了检查,我们发现您超出的限制几乎可以肯定是允许的表达式总数。现在记录为10,000,但该数字实际上是不正确的。应记录为1,000。这就是为什么当您减少一些规则时,它就可以开始工作的原因。那时您可能进入了1000个限制以下。

您可以采取的改善状况的方法是不必要地停止重复调用函数。例如,您可以只写isValidItem(map, key)

来代替map[key]然后反复调用isValidItem(value)

不幸的是,目前尚无可用于安全规则的日志或调试信息,因此有时出问题时您需要猜测一下。

我们将修复文档,并在内部进行更多讨论。

答案 1 :(得分:1)

每次调用data()->文档参考。

限制是文档访问,在此调用中data()是问题所在。您通过多次调用数据来引用文档。为了避免这种情况,您可以将data()传递给函数并验证其中的所有内容。

Access call limits
There is a limit on document access calls per rule set evaluation:

10 for single-document requests and query requests.
20 for multi-document reads, transactions, and batched writes. The previous limit of 10 also applies to each operation.

For example, imagine you create a batched write request with 3 write operations and that your security rules use 2 document access calls to validate each write. In this case, each write uses 2 of its 10 access calls and the batched write request uses 6 of its 20 access calls.

Exceeding either limit results in a permission denied error. Some document access calls may be cached, and cached calls do not count towards the limits

https://firebase.google.com/docs/firestore/security/rules-conditions