如果一个firebase规则检查资源值,当文档不存在时,它是否总是给予拒绝的权限?

5m1hhzi4  于 2023-03-31  发布在  其他
关注(0)|答案(2)|浏览(106)

我正在为我的“用户”集合编写一个规则,看起来像这样:

match /users/{userId} {

      // Returns true if auth's email is empty and user's 
      // insensitiveEmail is empty or non-existent
      function emailDoesNotExist(resource) {
        return request.auth.token.email.size() == 0 && 
        (!fieldExists(resource, "insensitiveEmail") || resource.data.insensitiveEmail.size() == 0);
      }
    
      // Returns true if auth's email matches user's email
      function emailMatches(resource) {
          return request.auth.token.email == resource.data.insensitiveEmail;
      }
    
      // Returns true if the auth uid matches the resource's uid 
      function uidMatchesResource(resource) {
          return request.auth.uid == resource.data.uid && request.auth.uid == resource.id;
      }

      allow get: if request.auth != null
        && request.auth.uid == userId
        && uidMatchesResource(resource)
        && (emailDoesNotExist(resource) || emailMatches(resource))

在数据库中不存在所请求的用户ID的情况下,我得到[firestore/permission-denied] The caller does not have permission to execute the specified operation.错误。
这是因为我试图与resource进行比较,而resource不存在吗?
如果是这样,有没有一种方法可以验证返回文档中的数据,而不阻止导致0个返回文档的请求?

eyh26e7m

eyh26e7m1#

要允许查询访问不存在的文档,请对resource执行null检查,并在其他检查得到解决之前将结果短路。
此外,使用Map#get()可以大大简化电子邮件检查。

match /users/{userId} {
  // ...

  // Returns true if auth's email matches the stored
  // insensitiveEmail value (if any).
  // - has an email that matches stored value? true
  // - has no email and stored value is missing? true
  // - has no email and stored value is ""? true
  // - otherwise? false
  // note: while request.auth.token.get("email", "") could also be used,
  //       the token should probably always have the "email" claim and
  //       throw an error when it doesn't.
  function emailMatches(resource) {
    return request.auth.token.email == resource.data.get("insensitiveEmail", "")
  }
    
  // Returns true if the auth uid matches the resource's uid 
  function uidMatchesResource(resource) {
    return request.auth.uid == resource.data.uid
        && request.auth.uid == resource.id; // <- this line could be removed because of request.auth.uid == userId check
  }

  // note spread out for clarity, will need flattening
  allow get: if request.auth != null
        && request.auth.uid == userId
        && (
          resource == null // permit read when document does not exist
          || (
            uidMatchesResource(resource) // or when the uid & email match in existing document
            && emailMatches(resource)
          )
        )
}
mzaanser

mzaanser2#

通常你不应该得到:
缺少权限或权限不足。
即使文档不存在。但是,以下规则:

// Returns true if the auth uid matches the resource's uid 
function uidMatchesResource(resource) {
    return request.auth.uid == resource.data.uid && request.auth.uid == resource.id;
}

如果文档不存在,则无法将其评估为true,因此Firebase服务器将拒绝该操作,并且当您在不存在的文档上设置侦听器时,您确实会收到“缺少或权限不足”。
因此,在您的示例中,您应该使用exists检查文档是否存在,而不是直接检查UID。

相关问题