在Firestore文档中实现粒度数据验证

时间:2018-08-19 10:43:42

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

假设我的数据库中有一个字符文档,即/characters/{characterID}

此文档的形状可以如下:

{
  username: "Username",
  race: "ORC or ELF",
  gender: "FEMALE or MALE",
  gold: 1000,
  equipement: {
    helmet: "null or string",
    boots: "null or string"
  } 
}

我想允许以下用例:

  1. 用户创建角色后,可以通过提供有效的username, race, gender来为自己创建角色,这些字段不可编辑
  2. 用户可以一次全部,一次一次或任意混合使用字段来更新其余字段。 (一旦更新,就会触发firebase函数来对此进行验证,但根据规则,我们要确保用户发送有效值)

我通过使用以下规则找出了步骤1,validCreateCharacterData验证了username, race and gender

service cloud.firestore {
  match /databases/{database}/documents {

    // Characters
    match /characters/{characterID} {
      allow create: if isOwner(characterID)
                    && validCreateCharacterData();
    }
  }
}

但是我很难弄清楚如何验证其余的数据更新,因为它们可以为null或字段的各种混合。我想制定精细的规则,但是下面的方法不起作用:/

service cloud.firestore {
  match /databases/{database}/documents {

    // Characters
    match /characters/{characterID} {
      allow create: if isOwner(characterID)
                    && validCreateCharacterData();

      match /gold {
         allow update: if request.resource.data.gold is number
      }
    }
  }
}

1 个答案:

答案 0 :(得分:4)

使用match时,实际上是朝collection / document方向迈出了又一步。因此update实际上是无效的,因为它是在collection而非document上执行的。

您的规则应如下所示:

service cloud.firestore {
  match /databases/{database}/documents {

    // Characters
    match /characters/{characterID} {
      allow create: if isOwner(characterID)
                && validCreateCharacterData();
      function isValidEquipment(val) {
        return val is string
          || val == null;
      }
      // don't allow a write request that includes updates to username, race, or gender
      allow update: if !request.writeFields.hasAny(['username','race','gender'])
                && request.resource.data.gold is number
                && isValidEquipment(request.resource.data.equipment.helmet)
                && isValidEquipment(request.resource.data.equipment.boots);
    }
  }
}