通过Flutter查询具有基于角色的安全性的Firestore文档

时间:2018-12-31 14:47:00

标签: flutter google-cloud-firestore

我在Google的建议下,在Firestore上有一个基于角色的数据模型https://firebase.google.com/docs/firestore/solutions/role-based-access

安全规则已正确设置并且可以正常工作。但是现在我遇到了有关如何查询角色的问题。

这是我的数据模型(一个示例文档):

id: "1234-5678-91234",
roles:
    userId_1:"owner",
    userId_2:"editor
title: "This is a sample document"

这是我在Flutter中的 Firestore查询,如果用户为文档分配了角色“所有者” ,则该ID通过其ID获取特定用户的所有文档:

return firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots().map((snapshot) {
  return snapshot.documents.map((catalog) {
    return SomeDocumentObject(...);
  }).toList();
});

现在我的问题是,我需要某种“ OR”子句-据我所知,该子句不存在。上面的查询仅为角色为“所有者”的用户检索文档< strong>但是我需要一个查询,如果userId与角色“编辑者”相关联,它也可以检索文档。

我尝试过“ arrayContains:”,它似乎也不起作用(因为它是一张地图)。

我已经阅读了有关带有两个独立查询的解决方案,由于开销很大,这听起来不是一个好的解决方案。

也许有人对我有暗示? :)

谢谢! 迈克尔

2 个答案:

答案 0 :(得分:1)

Firestore当前没有任何逻辑或操作。您将必须执行两个查询,每个条件一个,然后在客户端应用程序中合并两个查询的结果。

答案 1 :(得分:0)

这是使用 RxDart Observables .combineLatest()最终解决方案-也许它可以帮助某人在那里:

@override
Stream<List<Catalog>> catalogs(User user) {

    // Retrieve all catalogs where user is owner
    Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
        .collection(path)
        .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
        .snapshots());

    // Retrieve all catalogs where user is editor
    Observable<QuerySnapshot> editorCatalogs = Observable(firestore
        .collection(path)
        .where("roles.${user.firebaseUserId}", isEqualTo: "editor")
        .snapshots());

    // Convert merged stream to list of catalogs
    return Observable.combineLatest([ownerCatalogs, editorCatalogs],
        (List<QuerySnapshot> snapshotList) {
      List<Catalog> catalogs = [];

      snapshotList.forEach((snapshot) {
        snapshot.documents.forEach((DocumentSnapshot catalog) {
          catalogs.add(Catalog(
            id: catalog.documentID,
            title: catalog.data['title'],
            roles: catalog.data['roles'],
          ));
        });
      });
      return catalogs;
    }).asBroadcastStream();
  }