本文介绍了带角色的Firestore查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

文档中,您可以通过比较来进行查询字符串转换为另一个字符串值,例如:

In the documentation it's stated that you can query by comparing string to another string value e.g:

citiesRef.where('name', '>=', 'San Francisco');
citiesRef.where('state', '>=', 'CA').where('state', '<=', 'IN');

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

Then there is this roles part in the documentation that shows how to apply roles in Firestore documents. However it's not shown how to query this.. But as shown in above example, this should work like following:

citiesRef.where(`roles.${user.uid}`, '>', '');

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

so this query above, should return all documents where is any value bigger than empty string, right?

在我的代码中,我拥有一个文档收集的组织:

In my code I have organizations collection with one document:

{
  "name": "MyAmazingCompany",
  "roles": {
    "my-user-uid": "owner"
  }
}

如果我尝试查询具有以下角色的组织:

And if I try to query organizations where I have some role like this:

organizationsRef.where(`roles.${user.uid}`, '>', '');

我将在我的浏览器控制台中使用onSnapshot捕获 Uncaught错误:错误:缺少权限或权限不足.(使用firebase npm软件包版本5.1.0,也尝试了5.0.3).

I'll just get Uncaught Error in onSnapshot: Error: Missing or insufficient permissions. in my browser console (using firebase npm package version 5.1.0 and tried also 5.0.3).

只是为了确保我有权访问该文档,下面的查询经过测试,它可以正常工作并返回一个组织.

Just to make sure that I should have access to that document, following query is tested, it works and it returns that one organization.

organizationsRef.where(`roles.${user.uid}`, '==', 'owner');

那怎么了?

还有一个人声称它应该可以工作: Firestore选择哪里不为空

Also here is someone claiming it should work: 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']);
    }
  }
}

就像我说的那样,如果我比较角色是否是所有者,这是可行的,但是如果用户的uid存在于角色数组中,无论她具有什么角色,我都想获得结果.

Like I said, it works if I compare if the role is owner, but I want to get results if user's uid exists in the roles array, no matter what role she is having.

推荐答案

我还发现文档的这一部分令人困惑(或者缺少非常重要的细节).Firestore安全性要求您遵循有关数据结构的非常特定的设计模式.这是因为,Firebase安全规则语言在表达规则时的功能比可以对数据运行的简单查询和复合查询表达式要少.

I've also found this part of the documentation confusing (or rather, lacking in quite essential details). Firestore security requires that you follow very specific design patterns regarding you data structure. This comes from the fact that Firebase Security Rules language has less capabilities when expressing rules than simple and compound query expressions you can run against your data.

当试图保护数据库安全时,我逐渐不得不放弃原始的数据抽象思想,并从安全语言所施加的限制重新开始.而不是Firestore文档中建议的角色表示形式( https://firebase.google.com/docs/firestore/solutions/role-based-access ),我开始应用以下模式.您的用例采用的代码.

When trying to secure my database, I gradually had to give up my original data abstraction ideas, and start again from the limitations that the security language imposes. Instead of the proposed roles representation in Firestore documentation (https://firebase.google.com/docs/firestore/solutions/role-based-access), I started to apply the following pattern. Code adopted to your use case.

{
  "name": "MyAmazingCompany",
  "roles": {
    "anyRole": ["user-id-1", "user-id-2", "user-id-3", "user-id-4"],
    "owners": ["user-id-1"],
    "editors": ["user-id-2"],
    "readers": ["user-id-3", "user-id-4"],
  }
}

因此,从本质上讲,角色对象的属性是不同的角色级别,属于给定角色的用户以id数组的形式存储在角色属性下.还有一个名为 anyRole 的附加元角色,它用作方便集合,使查询更容易.

So, in essence, different role levels are the properties of the role object, and users belonging to a given role stored as an array of ids under the role property. There is an additional meta role called anyRole, which serves as a convenience collection to make queries easier.

Firebase安全规则如下:

Firebase security rules are as follows:

rules_version = '2';

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

      function hasReadPermission(res) {
        let anyRole = request.auth.uid in res.data.accessors.anyRole;
        return anyRole;
      }

      function hasWritePermission(res) {
        let owner = request.auth.uid in res.data.accessors.owners;
        let editor = request.auth.uid in res.data.accessors.editors;
        return owner || editor;
      }

      allow read: if hasReadPermission(resource);
      allow write: if hasWritePermission(resource);
    }
  }
}

最后,使用 roles.anyRole

获取用户有权访问的所有文档

Get all documents the user has access to:

organizationsRef.where(`roles.anyRole`, 'array-contains', user.uid);

获取用户拥有的所有文档:

Get all documents owned by the user:

organizationsRef.where(`roles.owner`, 'array-contains', user.uid);

这篇关于带角色的Firestore查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 10:57