Reguły zabezpieczeń dotyczące operacji w potoku

Operacje potoku oferują bogaty zestaw funkcji, ale silnik reguł jest ograniczony do rozpoznawania filtrów porównania (np. >) i logicznych (np. or), aby zapewnić spełnienie ograniczeń i bezpieczeństwo.

Obsługiwane wyrażenia filtra

Aby operacje potoku były ograniczone do zakresu określonego 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 uwierzytelniania 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: wskazuje operację (np. get, list).
  • request.path: ścieżka zasobu, do którego uzyskuje się 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, offsetorderBy, 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 są powiązane z określonymi szczegółowymi operacjami w regułach zabezpieczeń:

  • Uprawnienia allow list: wywoływane na etapach collection(), collectionGroup()database().
  • allow get uprawnienia: wywoływane przez etap documents(), który jest traktowany podobnie jak operacja wsadowa get.
  • 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 pola

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 mieć pewność, że reguły działają zgodnie z oczekiwaniami, umieść etapy filtrowania (np. where) przed etapami, które mogą modyfikować oryginalne zapisane dokumenty.

Rozważmy na przykład tę regułę zabezpieczeń:

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';
  }
}

Odrzucono: 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();

Dozwolone: 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();