Firestore получить несколько документов правил безопасности - PullRequest
1 голос
/ 24 марта 2020

У меня в приложении есть утилита просмотра, которая с помощью get получает все документы в коллекции. Каждый документ содержит идентификатор пользователя, который его создал. Я хотел бы реализовать правило безопасности, в котором вы получаете только документы, совпадающие с идентификатором владельца. Это выглядит довольно тривиально, но я не могу заставить его работать.

База данных имеет такую ​​структуру

cars
|
|-documentA
|-documentB
|-documentC

каждый документ:

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

Правила безопасности в пожарном депо

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)

Адаптер 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 ]

2 голосов
/ 24 марта 2020

Вы должны заметить, что правила безопасности не являются фильтрами , как описано в документации :

Как только вы защитите свои данные и начнете писать запросы, имейте в виду, что правила безопасности не являются фильтрами. Вы не можете написать запрос для всех документов в коллекции и ожидать, что 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 голос
/ 24 марта 2020

Основываясь на комментариях, я думаю, что это может быть решением. Согласно ОП, все пользователи должны иметь возможность зарегистрировать автомобиль, но только пользователь, который создал автомобиль, должен видеть его.

Правильные разрешения в этом случае будут выглядеть следующим образом:

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'.

...