Firestore 查询角色?

leh*_*htu 7 javascript firebase google-cloud-firestore

文档中指出,您可以通过将字符串与另一个字符串值进行比较来进行查询,例如:

citiesRef.where('name', '>=', 'San Francisco');
citiesRef.where('state', '>=', 'CA').where('state', '<=', 'IN');
Run Code Online (Sandbox Code Playgroud)

然后文档中的角色部分展示了如何在 Firestore 文档中应用角色。然而,它没有显示如何查询这个..但如上面的示例所示,这应该像下面这样工作:

citiesRef.where(`roles.${user.uid}`, '>', '');
Run Code Online (Sandbox Code Playgroud)

所以上面的查询应该返回所有大于空字符串的值的文档,对吧?

在我的代码中,我有包含一个文档的组织集合:

{
  "name": "MyAmazingCompany",
  "roles": {
    "my-user-uid": "owner"
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我尝试查询我担任以下角色的组织:

organizationsRef.where(`roles.${user.uid}`, '>', '');
Run Code Online (Sandbox Code Playgroud)

我将Uncaught Error in onSnapshot: Error: Missing or insufficient permissions.进入浏览器控制台(使用 firebase npm 包版本 5.1.0 并尝试使用 5.0.3)。

只是为了确保我应该有权访问该文档,测试了以下查询,它有效并且返回该组织。

organizationsRef.where(`roles.${user.uid}`, '==', 'owner');
Run Code Online (Sandbox Code Playgroud)

那么有什么问题吗?

还有人声称它应该有效:Firestore select where is not null

这是我的规则:

service cloud.firestore {
  match /databases/{database}/documents {
    function isSignedIn() {
      return request.auth != null;
    }

    function getRole(rsc) {
      // Read from the "roles" map in the resource (rsc).
      return rsc.data.roles[request.auth.uid];
    }

    function isOneOfRoles(rsc, array) {
      // Determine if the user is one of an array of roles
      return isSignedIn() && (getRole(rsc) in array);
    }

    match /organizations/{organizationId} {
      allow read: if isOneOfRoles(resource, ['owner']);
      allow write: if isOneOfRoles(resource, ['owner']);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

就像我说的,如果我比较角色是否是所有者,它就有效,但如果用户的 uid 存在于角色数组中,我想获得结果,无论她拥有什么角色。

Gra*_*mbo 1

您的规则的一个问题可能是您如何检查角色映射。如果您尝试访问不存在的映射键,它将引发异常。

function getRole(rsc) {
  // Read from the "roles" map in the resource (rsc).
  return rsc.data.roles[request.auth.uid]; // this will throw an exception if the uid isn't in the map
}
Run Code Online (Sandbox Code Playgroud)

在规则语言中,地图有一种get("key", "default-value")方法可以帮助您安全地完成正在做的事情。所以这可能有帮助:

function getRole(rsc) {
  // Read from the "roles" map in the resource (rsc).
  return rsc.data.roles.get(request.auth.uid, null);
}

function isOneOfRoles(rsc, array) {
  // Determine if the user is one of an array of roles
  return isSignedIn() && getRole(rsc) != null && (getRole(rsc) in array);
}
Run Code Online (Sandbox Code Playgroud)

我还没有在 firebase 中运行您的代码来验证是否没有其他问题,但这至少是您可能遇到的一个问题。