Reguły zabezpieczeń dotyczące operacji w potoku

Operacje potoku oferują wiele funkcji , ale silnik reguł może rozpoznawać tylko filtry porównania (np. >) i logiczne (np. or), aby zapewnić spełnienie ograniczeń i bezpieczeństwo.

Obsługiwane wyrażenia filtra

Aby operacje potoku były ograniczone do granic określonych przez reguły, muszą używać operatorów logicznych i porównania w odniesieniu do stałych. Silnik reguł rozpoznaje te typy filtrów:

  • Porównania: eq, neq, gt, gte, lt, lte, in, arrayContains.
  • Logiczne: and, or.

Oto przykłady:

  • where(eq("foo", 2))
  • where(lt("foo", 2))
  • documents("/user/1", "/user/2").where(...)

Właściwości żądania

Nadal możesz używać obiektu request do weryfikowania autentykacji i kontekstu zapytania, chociaż niektóre właściwości dostępne w standardowych zapytaniach nie są obsługiwane w operacjach potoku.

Obsługiwane właściwości

Nowy silnik nadal obsługuje te właściwości:

  • request.auth: dostęp do identyfikatora użytkownika i danych tokena.
  • request.method: identyfikuje operację (np. get, list).
  • request.path: ścieżka do zasobu, do którego uzyskiwany jest dostęp.
  • request.time: sygnatura czasowa żądania po stronie serwera.

Nieobsługiwane właściwości

Właściwości request.query, takie jak limit, offset i orderBy, nie są obsługiwane w przypadku sprawdzania reguł operacji potoku ze względu na złożoność określania tych wartości w zapytaniach wieloetapowych.

Obsługa etapów potoku i uprawnienia

Istnieją różne etapy potoku, które odpowiadają konkretnym operacjom szczegółowym w regułach bezpieczeństwa:

  • Uprawnienia allow list: wywoływane przez etapy collection(), collectionGroup() i database().
  • allow get uprawnienia: wywoływane przez etap documents(), który jest traktowany podobnie jak operacja get w trybie wsadowym.
  • Etap literałów: etap literals() nie odczytuje danych z bazy danych, ale może generować koszty. Aby zapobiec nadużyciom, musi być połączony z innym etapem (np. collection()), który można zweryfikować za pomocą reguł.

Etapy modyfikacji pól

Reguły działają tylko na przechowywanych danych, a nie na wartościach pochodnych. Jeśli potok zawiera etapy, które modyfikują pola (np. add_fields(...), replace_with(...), select(...), remove_fields(...)), silnik reguł przestaje stosować ograniczenia filtra po napotkaniu tego etapu. Aby reguły działały zgodnie z oczekiwaniami, umieść etapy filtra (np. where) przed etapami, które mogą modyfikować oryginalne przechowywane dokumenty.

Na przykład rozważ tę regułę bezpieczeństwa:

match /databases/{database}/documents {
  match /cities/{city} {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    allow read: if resource.data.visibility == 'public';
  }
}

Odmowa: ta reguła odrzuca ten potok, ponieważ etap addFields występuje przed filtrowaniem dokumentów, w których visibility ma wartość public:

const results = await db.pipeline()
  .collection("/cities")
  // Filters after a modification stage are ignored by Rules.
  .addFields(constant(1000).as("population"))
  .where(eq(field("visibility"), constant("public")))
  .execute();

Zezwolenie: ta reguła zezwala na ten potok, ponieważ etap where(eq(field("visibility"), constant("public"))) występuje przed etapami modyfikacji:

const results = await db.pipeline()
  .collection("/cities")
  .where(eq(field("visibility"), constant("public")))
  .addFields(constant(1000).as("population"))
  .execute();