Firestore检索多个文档的安全规则

时间:2020-03-24 07:17:20

标签: firebase google-cloud-firestore firebase-security

我的应用程序中有一个recyclerview,它带有一个get,它检索集合中的所有文档。每个文档都包含创建它的人的uid。我想实现一个安全规则,在该规则中,您仅检索与所有者的uid相匹配的文档。看起来很琐碎,但我无法使其正常工作。

数据库具有这样的结构

cars
|
|-documentA
|-documentB
|-documentC

每个文档

documentA
|
|
|-fieldA: aaa
|-fieldB: bbb
|-userId: aklsjdaosjfpasf

firestore的安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{cars=**}/{carId}  {
    allow read: if request.auth.uid == resource.data.userId;
    allow write: if request.auth.uid != null;
  }
  }
}

编辑 查询:

query = firestore.collection("cars").limit(10L)

用于对recyclerview进行查询的Firestore适配器

public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<VH> {

    private static final String TAG = "Firestore Adapter";

    private Query mQuery;
    private ListenerRegistration mRegistration;

    private ArrayList<DocumentSnapshot> mSnapshots = new ArrayList<>();

    public FirestoreAdapter(Query query) {
        mQuery = query;
    }

    public void startListening() {
        // TODO(developer): Implement
    }

    public void stopListening() {
        if (mRegistration != null) {
            mRegistration.remove();
            mRegistration = null;
        }

        mSnapshots.clear();
        notifyDataSetChanged();
    }

    public void setQuery(Query query) {
        // Stop listening
        stopListening();

        // Clear existing data
        mSnapshots.clear();
        notifyDataSetChanged();

        // Listen to new query
        mQuery = query;
        startListening();
    }

    @Override
    public int getItemCount() {
        return mSnapshots.size();
    }

    protected DocumentSnapshot getSnapshot(int index) {
        return mSnapshots.get(index);
    }

    protected void onError(FirebaseFirestoreException e) {};

    protected void onDataChanged() {}
}

2 个答案:

答案 0 :(得分:2)

您必须注意,安全规则不是过滤器,如documentation所述:

一旦保护好数据并开始编写查询,请记住 安全规则不是过滤器。 您无法为以下内容编写查询 集合中的所有文档,并期望Cloud Firestore能够 仅返回当前客户有权访问的文档 访问

使用

query = firestore.collection("cars").limit(10L)

您要独立于userId查询,因此出现了问题。

您需要使用whereEqualTo()修改查询,如下所示:

//get the value of uid
query = firestore.collection("cars").whereEqualTo("userId", uid).limit(10L)

答案 1 :(得分:1)

根据评论,我认为这可能是解决方案。根据OP,所有用户都应该能够注册汽车,但是只有创建汽车的用户才能看到汽车。

在这种情况下,正确的权限应如下所示:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /cars/{carId}  {
      allow read, write: if request.auth.uid == resource.data.userId;
      allow create: if request.auth.uid != null;
    }
  }
}

对于2版之前的规则,

许可URL也存在问题,您可以使用以下语法来匹配集合中的所有文档:/cars/{documemts=**}/,但是您的路径/{cars=**}/{carId}无效,因此该规则永远不会为您的查询强制执行。

路径/cars/{carId}将引用集合'cars'中的任何文档,并将该文档的名称存储为'carId'。