首页 > 解决方案 > 如何制定允许身份验证用户阅读所有文档但只创建自己的用户文档而不赋予自己管理员权限的 Firebase 规则?

问题描述

我正在努力解决 firebase 安全规则,我可以让它的一部分工作,但是当我尝试将它们连接在一起时,我遇到了问题。
我想让我的规则执行以下操作:

  1. 如果经过身份验证,则允许读取所有文档

  2. 允许通过仅在文档 /databases/$(database)/documents/users/$(request.auth.uid) 进行身份验证来创建或更新用户文档,但不允许将管理员添加到角色数组!(getAfter中的“admin”(/databases/) $(数据库)/documents/users/$(request.auth.uid)).data.roles)

  3. 仅允许 getRole(“admin”) == true 创建、编辑或删除任何用户文档和任何其他文档

function getRole(role) {
    return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles.hasAny([role]);
  }

这是我所拥有的不包括能够创建自己的用户帐户的用户。它只允许管理员编写任何文档。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  function getRole(role) {
    return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles.hasAny([role]);
  }
    match /{document=**} {
      allow read: if true;
      allow write: if getRole('admin') == true;
    }
  }
}

这是我尝试添加的内容,以允许用户创建他们的用户文档。它似乎没有级联到下一条规则,它尝试match /{document=**}路径中的 getRole 并发现用户不是管理员,所以它失败了。我尝试重新排序并将 /users/ 路径放在上面,它通过该路径很好,然后做同样的事情并/{document=**}再次在路径中的 getRole 上失败。我还尝试指定文档名称而不是使用通配符,这似乎不允许任何获取或写入。你能指出我正确的方向吗?

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  function getRole(role) {
    return exists(/databases/$(database)/documents/users/$(request.auth.uid)) && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles.hasAny([role]);
  }
    match /{document=**} {
      allow read: if true;
      allow write: if getRole('admin') == true;
    }
    match /users/{userId}{
      allow read: if  request.auth.uid != null;
      allow create: if getRole('admin') == true ||  request.auth.uid == userId  &&
            !(getAfter(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles.hasAny(["admin"]));
      allow update: if getRole('admin') == true ||  request.auth.uid == userId  && exists(/databases/$(database)/documents/users/$(request.auth.uid)) == true && !(getAfter(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles.hasAny(["admin"]));
      }
  }
}

标签: firebasegoogle-cloud-firestorefirebase-security

解决方案


事实证明,我不能允许管理员动态创建未在安全规则中定义的集合,除非我使用match /{document=**}将这些规则应用于每个路径并且不是所需结果的集合。我能够很容易地设置规则来完成其他部分,如下所示:

service cloud.firestore {
  match /databases/{database}/documents {
   function getRole(role) {
    return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles.hasAny([role]);
  }
    match /users/{userId} {
      allow read: if request.auth.uid != null;
      allow create: if request.auth.uid == userId && request.resource.data.roles.hasAny(["admin"]) == false;
    }
    match /collectionName/{collectionNameId} {
      allow read: if request.auth.uid != null;
      allow write: if request.auth.uid != null && getRole('admin') == true;
    }
  }
}

推荐阅读