在Firebase Firestore安全规则中进行多字段验证。

huangapple go评论62阅读模式
英文:

Multiple field validation in Firebase Firestore security rules

问题

I have written the following security rule for the GameAdmins collection of my Firestore database:

    match /GameAdmins/{adminId} {
      function validAdminData() {
      	let keys = request.resource.data.keys().toSet();
        let allowedKeys = ['admin', 'superAdmin'].toSet();
        let data = request.resource.data;
        
        return (keys == allowedKeys) && (data.admin is bool) && (data.superAdmin is bool);
      }
      
      allow create, update: if isSuperAdmin() && validAdminData();
      allow delete: if isSuperAdmin();
    }

So it allows only two boolean fields admin and superAdmin while creating or updating a document. This method was easy to write since it has only two fields. It gets difficult when I want to write the same method for a different collection that has a lot of fields since I would have to write the list of keys and check the type of each field.

I thought of keeping dummy data in the database so that I can get the list of allowed keys from there. But I still have to check each of their types separately.

Is there a better way to check the list of keys and their types with less amount of codes?

英文:

I have written the following security rule for the GameAdmins collection of my Firestore database:

    match /GameAdmins/{adminId} {
      function validAdminData() {
      	let keys = request.resource.data.keys().toSet();
        let allowedKeys = ['admin', 'superAdmin'].toSet();
        let data = request.resource.data;
        
        return (keys == allowedKeys) && (data.admin is bool) && (data.superAdmin is bool);
      }
      
      allow create, update: if isSuperAdmin() && validAdminData();
      allow delete: if isSuperAdmin();
    }

So it allows only two boolean fields admin and superAdmin while creating or updating a document. This method was easy to write since it has only two fields. It gets difficult when I want to write the same method for a different collection that has a lot of fields since I would have to write the list of keys and check the type of each field.

I thought of keeping dummy data in the database so that I can get the list of allowed keys from there. But I still have to check each of their types separately.

Is there a better way to check the list of keys and their types with less amount of codes?

答案1

得分: 1

我写了一些功能,它们虽然不是完全动态的,但目前可以使用。

    function validateType(data, type) {
      return (
        (type == 'string' && data is string) ||
        (type == 'int' && data is int) ||
        (type == 'bool' && data is bool) ||
        (type == 'timestamp' && data is timestamp) ||
        (type == 'list' && data is list)
      );
    }
    
    function validateEachField(data, model) {
      let keys = model.keys();
      let n = keys.size() - 1;
      
      return (
        (n <= 0 || validateType(data[keys[0]], model[keys[0]])) &&
        (n <= 1 || validateType(data[keys[1]], model[keys[1])) &&
        (n <= 2 || validateType(data[keys[2]], model[keys[2])) &&
        (n <= 3 || validateType(data[keys[3]], model[keys[3])) &&
        (n <= 4 || validateType(data[keys[4]], model[keys[4])) &&
        (n <= 5 || validateType(data[keys[5]], model[keys[5])) &&
        (n <= 6 || validateType(data[keys[6]], model[keys[6])) &&
        (n <= 7 || validateType(data[keys[7]], model[keys[7])) &&
        (n <= 8 || validateType(data[keys[8]], model[keys[8])) &&
        (n <= 9 || validateType(data[keys[9]], model[keys[9]))
      );
    }
    
    function validateData(collection) {
      let model = get(/databases/$(database)/documents/DataModels/$(collection)/$(collection)).data;
      let keys = request.resource.data.keys().toSet();
      let allowedKeys = model.keys().toSet();
      return keys == allowedKeys && validateEachField(request.resource.data, model);
    }

唯一的问题似乎是当字段数量增加时,可能需要在 validateEachField 函数中添加更多行,以及在未来为 validateType 函数添加更多类型的支持。

英文:

I wrote some functions that are not completely dynamic but work for now.

    function validateType(data, type) {
      return (
        (type == &#39;string&#39; &amp;&amp; data is string) ||
      	(type == &#39;int&#39; &amp;&amp; data is int) ||
      	(type == &#39;bool&#39; &amp;&amp; data is bool) ||
      	(type == &#39;timestamp&#39; &amp;&amp; data is timestamp) ||
      	(type == &#39;list&#39; &amp;&amp; data is list)
      );
    }
    
    function validateEachField(data, model) {
      let keys = model.keys();
      let n = keys.size() - 1;
      
      return (
      	(n &lt;= 0 || validateType(data[keys[0]], model[keys[0]])) &amp;&amp;
        (n &lt;= 1 || validateType(data[keys[1]], model[keys[1]])) &amp;&amp;
        (n &lt;= 2 || validateType(data[keys[2]], model[keys[2]])) &amp;&amp;
        (n &lt;= 3 || validateType(data[keys[3]], model[keys[3]])) &amp;&amp;
        (n &lt;= 4 || validateType(data[keys[4]], model[keys[4]])) &amp;&amp;
        (n &lt;= 5 || validateType(data[keys[5]], model[keys[5]])) &amp;&amp;
        (n &lt;= 6 || validateType(data[keys[6]], model[keys[6]])) &amp;&amp;
        (n &lt;= 7 || validateType(data[keys[7]], model[keys[7]])) &amp;&amp;
        (n &lt;= 8 || validateType(data[keys[8]], model[keys[8]])) &amp;&amp;
        (n &lt;= 9 || validateType(data[keys[9]], model[keys[9]]))
      );
    }
    
    function validateData(collection) {
      let model = get(/databases/$(database)/documents/DataModels/$(collection)/$(collection)).data;
      let keys = request.resource.data.keys().toSet();
      let allowedKeys = model.keys().toSet();
      return keys == allowedKeys &amp;&amp; validateEachField(request.resource.data, model);
    }

The only problem seems to be I might have to add more lines in the validateEachField function when the number of fields increases and add support for more types in the validateType function in the future.

huangapple
  • 本文由 发表于 2023年4月11日 14:24:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75982946.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定