API reguł bezpieczeństwa bazy danych Firebase

Zasada: Typy

.Czytać

Przyznaje klientowi dostęp do odczytu lokalizacji bazy danych Firebase Realtime Database.

Reguła .read to rodzaj reguły bezpieczeństwa, która przyznaje klientowi dostęp do odczytu lokalizacji bazy danych Firebase Realtime Database. Na przykład:

 ".read": "auth != null && auth.provider == 'twitter'"

Wartością reguły .read jest ciąg znaków, który jest oceniany jako podzbiór składni wyrażeń JavaScript z kilkoma zmianami w zachowaniu w celu zwiększenia przejrzystości i poprawności. Reguła .read , która przyznaje pozwolenie na odczyt lokalizacji, pozwoli także na odczyt dowolnych elementów podrzędnych tej lokalizacji, nawet jeśli elementy podrzędne mają własne reguły .read , które zawodzą.

Reguła .read ma dostęp do wszystkich zmiennych reguł bazy danych Firebase Realtime Database z wyjątkiem newData .

.pisać

Przyznaje klientowi dostęp do zapisu w lokalizacji bazy danych Firebase Realtime Database.

Reguła .write to rodzaj reguły bezpieczeństwa, która przyznaje klientowi dostęp do zapisu w lokalizacji bazy danych Firebase Realtime Database. Na przykład:

".write": "auth != null && auth.token.isAdmin == true"

Wartością reguły .write jest ciąg znaków, który jest oceniany jako podzbiór składni wyrażeń JavaScript z kilkoma zmianami w zachowaniu w celu zwiększenia przejrzystości i poprawności. Reguła .write , która przyznaje pozwolenie na zapis w lokalizacji, pozwoli także na zapis do dowolnych elementów podrzędnych tej lokalizacji, nawet jeśli elementy podrzędne mają własne reguły .write , które zawodzą.

Reguła .write ma dostęp do wszystkich zmiennych reguł bazy danych Firebase Realtime Database.

.uprawomocnić

Używane, gdy reguła .write przyznała dostęp, aby upewnić się, że zapisywane dane są zgodne z określonym schematem.

Reguła .validate jest używana, gdy reguła .write przyznała dostęp, aby upewnić się, że zapisywane dane są zgodne z określonym standardem. Oprócz .write przyznającego dostęp, wszystkie odpowiednie reguły .validate muszą zakończyć się pomyślnie, zanim zapis będzie dozwolony. Na przykład:

".validate": "newData.hasChildren(['name', 'age'])"

Wartością reguły .validate jest ciąg znaków, który jest oceniany jako podzbiór składni wyrażeń JavaScript z kilkoma zmianami w zachowaniu w celu zwiększenia przejrzystości i poprawności.

Reguła .validate ma dostęp do wszystkich zmiennych reguł bazy danych Firebase Realtime Database.

.indeksWł

Poprawia wydajność zapytań, informując bazę danych Firebase Realtime Database, które klucze mają być indeksowane.

Reguła .indexOn nakazuje serwerom bazy danych Firebase Realtime Database indeksowanie określonych kluczy w danych w celu poprawy wydajności zapytań. Na przykład, mając bazę danych zawierającą zbiór danych o dinozaurach, możemy nakazać bazie danych Firebase Realtime Database optymalizację pod kątem zapytań, zanim zostaną one zwrócone z serwerów, dodając następującą regułę:

{
  "rules": {
    "dinosaurs": {
      ".indexOn": ["height", "length"]
    }
  }
}

Więcej informacji na temat reguły .indexOn znajdziesz w rozdziale poradnika bezpieczeństwa dotyczącym indeksowania Twoich danych .

Reguła: Zmienne

autoryzacja

Zmienna zawierająca ładunek tokenu, jeśli klient jest uwierzytelniony, lub null , jeśli klient nie jest uwierzytelniony.

Baza danych Firebase Realtime pozwala łatwo uwierzytelnić się u kilku wbudowanych dostawców i wygenerować dla nich tokeny uwierzytelniające. Po uwierzytelnieniu użytkownika za pomocą jednego z wbudowanych dostawców zmienna auth będzie zawierać następujące informacje:

Pole Opis
provider Stosowana metoda uwierzytelniania (np. „hasło”, „anonimowy”, „facebook”, „github”, „google” lub „twitter”).
uid Unikalny identyfikator użytkownika, który gwarantuje unikalność u wszystkich dostawców.
token Zawartość tokena identyfikatora uwierzytelniania Firebase. Zobacz auth.token .

Na przykład moglibyśmy mieć następującą regułę, która zezwalałaby użytkownikom na tworzenie komentarzy, pod warunkiem, że przechowują swój identyfikator użytkownika wraz z komentarzem:

{
  "rules": {
    ".read": true,
    "$comment": {
      ".write": "!data.exists() && newData.child('user_id').val() == auth.uid"
    }
  }
}

Moglibyśmy również stworzyć regułę podobną do poniższej, aby umożliwić użytkownikom tworzenie komentarzy, o ile są zalogowani za pomocą Facebooka:

{
  "rules": {
    ".read": true,
    "$comment": {
      ".write": "!data.exists() && auth.provider == 'facebook'"
    }
  }
}

token uwierzytelnienia

Zmienna zawierająca zawartość tokena identyfikatora uwierzytelniania Firebase.

Token zawiera niektóre lub wszystkie z następujących kluczy:

Pole Opis
email Adres e-mail powiązany z kontem, jeśli istnieje.
email_verified true , jeśli użytkownik potwierdził, że ma dostęp do adresu email . Niektórzy dostawcy automatycznie weryfikują posiadane adresy e-mail.
phone_number Numer telefonu powiązany z kontem, jeśli jest obecny.
name Nazwa wyświetlana użytkownika, jeśli jest ustawiona.
sub Identyfikator UID Firebase użytkownika. Jest to unikalne rozwiązanie w ramach projektu.
firebase.identities Słownik wszystkich tożsamości powiązanych z kontem tego użytkownika. Kluczami słownika mogą być dowolne z następujących: email , phone , google.com , facebook.com , github.com , twitter.com . Wartości słownika to tablice unikalnych identyfikatorów dla każdego dostawcy tożsamości powiązanego z kontem. Na przykład auth.token.firebase.identities["google.com"][0] zawiera pierwszy identyfikator użytkownika Google powiązany z kontem.
firebase.sign_in_provider Dostawca logowania używany do uzyskania tego tokenu. Może to być jeden z następujących ciągów: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com .
firebase.tenant Identyfikator najemcy powiązany z kontem, jeśli istnieje. np. tenant2-m6tyz

W przypadku korzystania z uwierzytelniania niestandardowego auth.token zawiera również wszelkie niestandardowe oświadczenia określone przez dewelopera.

Wszystkie te wartości mogą być używane w regułach. Na przykład, aby ograniczyć dostęp do kont Google powiązanych z adresem gmail.com, możemy dodać regułę:

{
  "rules": {
    ".read": "auth != null",
    "gmailUsers": {
      "$uid": {
        ".write": "auth.token.email_verified == true && auth.token.email.matches(/.*@gmail.com$/)"
      }
    }
  }
}

Aby zapewnić kompletność, w auth.token uwzględniono także następujące pola, ale jest mało prawdopodobne, że będą one przydatne w przypadku reguł.

Pole Opis
iss Wydawca tokena.
aud Odbiorcy tokenu.
auth_time Ostatni raz użytkownik uwierzytelnił się przy użyciu poświadczeń przy użyciu urządzenia odbierającego token.
iat Godzina wystawienia tokenu.
exp Czas wygaśnięcia tokenu.

$lokalizacja

Zmienna, której można użyć do odniesienia się do klucza $location , która była wcześniej używana w strukturze reguły.

Jeśli masz $location w strukturze reguł, możesz użyć pasującej zmiennej $ w wyrażeniu reguły, aby uzyskać imię i nazwisko aktualnie odczytywanego lub zapisywanego dziecka. Załóżmy więc, że chcemy zapewnić każdemu użytkownikowi dostęp do odczytu i zapisu w jego własnej lokalizacji /users/<user> . Moglibyśmy użyć:

{
  "rules": {
    "users": {
      "$user": {
        ".read": "auth.uid === $user",
        ".write": "auth.uid === $user"
      }
    }
  }
}

Gdy klient próbuje uzyskać dostęp do /users/barney , domyślna lokalizacja $user zostanie zgodna z wartością $user równą „barney”. Zatem reguła .read sprawdzi, czy auth.uid === 'barney' . W rezultacie odczyt /users/barney zakończy się sukcesem tylko wtedy, gdy klient zostanie uwierzytelniony za pomocą identyfikatora użytkownika „barney”.

Teraz

Zawiera liczbę milisekund od epoki Uniksa według serwerów Firebase Realtime Database.

Zmienna now zawiera liczbę milisekund od epoki UNIX według serwerów Firebase Realtime Database. Możesz na przykład użyć tego, aby sprawdzić, czy czas created przez użytkownika nigdy nie jest ustawiony na czas w przyszłości:

{
  "rules": {
    "users": {
      "$user": {
        "created": {
          ".validate": "newData.val() < now"
        }
      }
    }
  }
}

źródło

Zrzut RuleDataSnapshot odpowiadający bieżącym danym w katalogu głównym bazy danych Firebase Realtime Database.

Zmienna główna zapewnia zrzut RuleDataSnapshot odpowiadający bieżącym danym w katalogu głównym bazy danych Firebase Realtime Database. Możesz użyć tego do odczytania dowolnych danych w bazie danych w wyrażeniach reguł. Na przykład, jeśli chcielibyśmy pozwolić użytkownikom na czytanie /comments tylko wtedy, gdy ich /users/<id>/active było ustawione na true, moglibyśmy użyć:

{
  "rules": {
    "comments": {
      ".read": "root.child('users').child(auth.uid).child('active').val() == true"
    }
  }
}

Następnie, jeśli /users/barney/active zawiera wartość true, użytkownik uwierzytelniony za pomocą identyfikatora użytkownika „barney” może pisać do węzła /comments .

dane

RuleDataSnapshot odpowiadający bieżącym danym w bazie danych Firebase Realtime Database w lokalizacji aktualnie wykonywanej reguły.

Zmienna data daje RuleDataSnapshot odpowiadający bieżącym danym w lokalizacji bazy danych aktualnie wykonywanej reguły (w przeciwieństwie do root, który daje dane dla katalogu głównego twojej bazy danych).

Na przykład, jeśli chcesz zezwolić dowolnemu klientowi na dostęp do /users/<user> jeśli /users/<user>/public ma wartość true, możesz użyć:

{
  "rules": {
    "users": {
      "$user": {
        ".read": "data.child('public').val() == true"
      }
    }
  }
}

Zmienna danych jest dostępna w regułach .read , .write i .validate .

nowe dane

RuleDataSnapshot odpowiadający danym, które powstaną, jeśli zapis będzie dozwolony.

W przypadku reguł .write i .validate zmienna newData daje RuleDataSnapshot odpowiadający danym, które powstaną, jeśli zapis będzie dozwolony (jest to „scalanie” istniejących danych z zapisywanymi nowymi danymi). Jeśli więc chcesz mieć pewność, że każdy użytkownik ma imię i wiek, możesz użyć:

{
  "rules": {
    "users": {
      "$user": {
        ".read": true,
        ".write": true,
        ".validate": "newData.hasChildren(['name', 'age'])"
      }
    }
  }
}

Ponieważ newData łączy istniejące dane i nowe dane, zachowuje się poprawnie nawet w przypadku „częściowych” aktualizacji. Na przykład:

var fredRef = firebase.database().ref("users/fred");
// Valid since we have a name and age.
fredRef.set({ name: "Fred", age: 19 });
// Valid since we are updating the name but there's already an age.
fredRef.child("age").set(27);
// Invalid since the .validate rule will no longer be true.
fredRef.child("name").remove();

Zmienna newData nie jest dostępna w regułach .read , ponieważ nie są zapisywane żadne nowe dane. Powinieneś po prostu użyć danych .

RuleDataSnapshot: Metody

wartość()

Pobiera wartość pierwotną ( string , number , boolean lub null ) z tego RuleDataSnapshot .

Wartość zwracana : ( String , Number , Boolean , Null ) — Wartość pierwotna z tego zrzutu RuleDataSnapshot .

W przeciwieństwie do DataSnapshot.val() wywołanie metody val() na obiekcie RuleDataSnapshot zawierającym dane podrzędne nie zwróci obiektu zawierającego te dzieci. Zamiast tego zwróci specjalną wartość wskaźnikową. Dzięki temu reguły mogą zawsze działać niezwykle efektywnie.

W rezultacie, aby uzyskać dostęp do dzieci, musisz zawsze używać child() (np. data.child('name').val() , a nie data.val().name ).

Ten przykład pozwala na odczyt tylko wtedy, gdy element podrzędny isReadable ma ustawioną wartość true w odczytywanej lokalizacji.

".read": "data.child('isReadable').val() == true"

dziecko()

Pobiera RuleDataSnapshot dla lokalizacji w określonej ścieżce względnej.

Argumenty : childPath String - Ścieżka względna do lokalizacji danych podrzędnych.

Wartość zwracana : RuleDataSnapshotRuleDataSnapshot dla lokalizacji podrzędnej.

Ścieżka względna może być prostym imieniem podrzędnym (np. „fred”) lub głębszą ścieżką oddzieloną ukośnikami (np. „fred/imię/pierwszy”). Jeśli lokalizacja podrzędna nie zawiera danych, zwracany jest pusty plik RuleDataSnapshot.

Ten przykład pozwala na odczyt tylko wtedy, gdy element podrzędny isReadable ma ustawioną wartość true w odczytywanej lokalizacji.

".read": "data.child('isReadable').val() == true"

rodzic()

Pobiera RuleDataSnapshot dla lokalizacji nadrzędnej.

Wartość zwracana : RuleDataSnapshotRuleDataSnapshot dla lokalizacji nadrzędnej.

Jeśli ta instancja odwołuje się do katalogu głównego bazy danych Firebase Realtime Database, nie ma elementu nadrzędnego, a parent() zakończy się niepowodzeniem, powodując pominięcie bieżącego wyrażenia reguły (jako niepowodzenie).

Ten przykład pozwala na odczyt tylko wtedy, gdy rodzeństwo isReadable ma wartość true.

".read": "data.parent().child('isReadable').val() == true"

hasChild(childPath)

Zwraca wartość true, jeśli określone dziecko istnieje.

Argumenty : childPath String - Ścieżka względna do lokalizacji potencjalnego dziecka.

Wartość zwracana : Boolean - true , jeśli w określonej ścieżce podrzędnej istnieją dane; inaczej false .

Ten przykład pozwala na zapisanie danych tylko wtedy, gdy zawierają one „imię” podrzędne.

".validate": "newData.hasChild('name')"

maDzieci([dzieci])

Sprawdza obecność dzieci.

Argumenty : children Array opcjonalna - Tablica kluczy podrzędnych, z których wszystkie muszą istnieć.

Wartość zwracana : Boolean - true , jeśli istnieją (określone) dzieci; inaczej false .

Jeśli nie podano żadnych argumentów, zwróci wartość true, jeśli RuleDataSnapshot ma jakieś elementy podrzędne. Jeśli podano tablicę nazw podrzędnych, zwróci wartość true tylko wtedy, gdy wszystkie określone elementy podrzędne istnieją w RuleDataSnapshot .

Ten przykład pozwala na zapisanie danych tylko wtedy, gdy zawierają jedno lub więcej dzieci.

".validate": "newData.hasChildren()"

Ten przykład pozwala na zapisanie danych tylko wtedy, gdy zawierają one elementy podrzędne „imię” i „wiek”.

".validate": "newData.hasChildren(['name', 'age'])"

istnieje()

Zwraca wartość true, jeśli ten RuleDataSnapshot zawiera jakiekolwiek dane.

Wartość zwracana : Booleantrue , jeśli RuleDataSnapshot zawiera jakiekolwiek dane; inaczej false .

Funkcja istnieje zwraca wartość true, jeśli ten RuleDataSnapshot zawiera jakiekolwiek dane. Jest to funkcja czysto wygodna, ponieważ data.exists() jest równoważna data.val() != null .

Ten przykład umożliwia zapis w tej lokalizacji, o ile nie istnieją żadne dane.

".write": "!data.exists()"

uzyskajPriorytet()

Pobiera priorytet danych w RuleDataSnapshot .

Wartość zwracana : ( String , Number , Null ) — priorytet danych w tym zrzucie RuleDataSnapshot .

Ten przykład gwarantuje, że nowe zapisywane dane mają priorytet

".validate": "newData.getPriority() != null"

jestNumer()

Zwraca wartość true, jeśli ten zrzut RuleDataSnapshot zawiera wartość liczbową.

Wartość zwracana : Boolean - true , jeśli dane są numeryczne; inaczej false .

Ten przykład gwarantuje, że nowe zapisywane dane będą miały „wiek” podrzędny o wartości liczbowej.

".validate": "newData.child('age').isNumber()"

isString()

Zwraca wartość true, jeśli ten zrzut RuleDataSnapshot zawiera wartość ciągu.

Wartość zwracana : Booleantrue , jeśli dane są String ; inaczej false .

Ten przykład zapewnia, że ​​nowe zapisywane dane mają podrzędną „nazwę” z wartością ciągu.

".validate": "newData.child('name').isString()

isBoolean()

Zwraca wartość true, jeśli ten zrzut RuleDataSnapshot zawiera wartość logiczną.

Wartość zwracana : Booleantrue , jeśli dane są wartościami typu Boolean ; inaczej false .

Ten przykład zapewnia, że ​​nowe zapisywane dane mają dziecko „aktywne” z wartością logiczną.

".validate": "newData.child('active').isBoolean()"

Ciąg: Właściwości

długość

Zwraca długość ciągu.

Wartość zwracana : Number — liczba znaków w ciągu.

Ten przykład wymaga, aby ciąg miał co najmniej 10 znaków.

".validate": "newData.isString() && newData.val().length >= 10"

Ciąg: Metody

zawiera (podciąg)

Zwraca wartość true, jeśli ciąg zawiera określony podciąg.

Argumenty : substring String - Podciąg, którego należy szukać.

Wartość zwracana : Boolean - true , jeśli ciąg zawiera określony podciąg; inaczej false .

Ten przykład wymaga, aby dane były ciągiem zawierającym „@”.

".validate": "newData.isString() && newData.val().contains('@')"

zaczyna się od (podciągu)

Zwraca wartość true, jeśli ciąg zaczyna się od określonego podciągu.

Argumenty : substring String - Podciąg, którego należy szukać na początku.

Wartość zwracana : Boolean - true , jeśli ciąg zawiera określony podciąg; inaczej false .

Ten przykład umożliwia dostęp do odczytu, jeśli auth.token.identifier zaczyna się od „internal-”

".read": "auth.token.identifier.beginsWith('internal-')"

kończy się na (podciągu)

Zwraca wartość true, jeśli ciąg kończy się określonym podciągiem.

Argumenty : substring String - Podciąg, którego należy szukać na końcu.

Wartość zwracana : Boolean - true , jeśli ciąg kończy się określonym podciągiem; inaczej false .

Ten przykład umożliwia dostęp do odczytu, jeśli auth.token.identifier kończy się na „@company.com”

".read": "auth.token.identifier.endsWith('@company.com')"

zamień (podciąg, zamiana)

Zwraca kopię ciągu, w którym wszystkie wystąpienia określonego podciągu zostały zastąpione określonym ciągiem zastępczym.

Argumenty : substring String - Podciąg, którego należy szukać. replacement String — ciąg znaków, którym ma zostać zastąpiony podciąg.

Wartość zwracana : String - Nowy ciąg znaków po zastąpieniu podłańcucha zamiennikiem.

Metoda replace() różni się nieco od metody replace() języka JavaScript tym, że zastępuje wszystkie wystąpienia określonego podciągu określonym ciągiem zastępczym, a nie tylko pierwsze wystąpienie.

Ponieważ kropki nie są dozwolone w kluczach, musimy uciec z ciągów znaków z kropkami przed ich zapisaniem. Przykładem mogą być adresy e-mail. Załóżmy, że w węźle /whitelist/ mamy listę adresów e-mail znajdujących się na białej liście:

{
 "user": {
   "$uid": {
     "email": <email>
   }
 },
 "whitelist": {
   "fred@gmail%2Ecom": true,
   "barney@aol%2Ecom": true
 }
}

Możemy stworzyć regułę, która pozwoli na dodawanie użytkowników tylko wtedy, gdy ich adres e-mail znajduje się w węźle /whitelist/ :

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "true",
        ".write": "root.child('whitelist').child(newData.child('email').val().replace('.', '%2E')).exists()"
      }
    }
  }
}

doLowerCase()

Zwraca kopię ciągu znaków przekonwertowanego na małe litery.

Wartość zwracana : String — ciąg znaków przekonwertowany na małe litery.

Ten przykład umożliwia dostęp do odczytu, jeśli auth.token.identifier , ponieważ wszystkie małe litery znajdują się w /users .

".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"

do wielkich liter()

Zwraca kopię ciągu znaków przekonwertowanego na wielkie litery.

Wartość zwracana : String — ciąg znaków przekonwertowany na wielkie litery.

Ten przykład umożliwia dostęp do odczytu, jeśli auth.token.identifier , ponieważ wszystkie wielkie litery znajdują się w /users .

".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"

dopasowania (wyrażenie regularne)

Zwraca wartość true, jeśli ciąg znaków pasuje do określonego literału wyrażenia regularnego.

Wartość zwracana : Booleantrue , jeśli ciąg znaków pasuje do literału wyrażenia regularnego, regex; inaczej false .

Zobacz pełną dokumentację reguł wyrażeń regularnych .

Operatorzy

+ (dodaj)

Służy do dodawania zmiennych lub łączenia ciągów.

Poniższy przykład gwarantuje, że nowa wartość zwiększy istniejącą wartość dokładnie o jeden. Jest to przydatne do implementacji licznika:

".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"

- (neguj lub odejmij)

Służy do negowania wartości lub odejmowania dwóch wartości w wyrażeniu reguły.

Ta reguła sprawdzania poprawności sprawdza, czy nowa wartość jest odwrotnością wartości podrzędnej w lokalizacji:

".validate": "newData.val() === -(data.child('quantity').val())"

W poniższym przykładzie zastosowano odejmowanie, aby upewnić się, że można odczytać tylko wiadomości z ostatnich dziesięciu minut:

".read": "newData.child('timestamp').val() > (now - 600000)"

* (pomnożyć)

Służy do mnożenia zmiennych w wyrażeniu reguł.

Ta reguła sprawdzania poprawności sprawdza, czy nowa wartość jest równa iloczynowi ceny i ilości (dwóm istniejącym wartościom):

".validate": "newData.val() === data.child('price').val() * data.child('quantity').val()"

/ (dzielić)

Służy do dzielenia zmiennych w wyrażeniach reguł.

W poniższym przykładzie reguła sprawdzania poprawności zapewnia, że ​​przechowywane dane są średnią wszystkich danych przechowywanych gdzie indziej:

".validate": "newData.val() === data.parent().child('sum').val() / data.parent().child('numItems').val()"

% (moduł)

Służy do znajdowania reszty z dzielenia jednej zmiennej przez drugą w wyrażeniu reguł.

Ta reguła potwierdza, że ​​można zapisywać tylko liczby parzyste:

".validate": "newData.val() % 2 === 0"

=== (równa się)

Służy do sprawdzania, czy dwie zmienne w wyrażeniu reguł mają ten sam typ i wartość.

Poniższa reguła używa operatora === w celu przyznania prawa do zapisu tylko właścicielowi konta użytkownika. Identyfikator użytkownika musi dokładnie odpowiadać kluczowi ( $user_id ), aby reguła przyjęła wartość true.

"users": {
  ".write": "$user_id === auth.uid"
}

!== (nie równa się)

Służy do sprawdzania, czy dwie zmienne w wyrażeniu reguł nie są równe.

Poniższa reguła odczytu gwarantuje, że tylko zalogowani użytkownicy będą mogli czytać dane:

".read": "auth !== null"

&& (I)

Zwraca wartość true, jeśli oba operandy mają wartość true. Służy do oceny wielu warunków w wyrażeniu reguł.

Następująca reguła sprawdzania poprawności sprawdza, czy nowe dane są ciągiem krótszym niż 100 znaków:

".validate": "newData.isString() && newData.val().length < 100"

|| (LUB)

Zwraca wartość true, jeśli jeden z operandów w wyrażeniu reguł ma wartość true.

W tym przykładzie możemy pisać, o ile nie istnieją stare lub nowe dane. Innymi słowy, możemy napisać, czy usuwamy lub tworzymy dane, ale nie aktualizujemy danych.

".write": "!data.exists() || !newData.exists()"

! (NIE)

Zwraca wartość true, jeśli jej pojedynczy operand ma wartość false. W wyrażeniach reguł, ! Operator jest często używany do sprawdzania, czy dane zostały zapisane w lokalizacji.

Następująca reguła umożliwia zapis tylko wtedy, gdy w określonej lokalizacji nie ma danych:

".write": "!data.exists()"

> (większy niż)

Służy do sprawdzania, czy wartość jest większa niż inna wartość w wyrażeniu reguły.

Ta reguła sprawdzania poprawności sprawdza, czy zapisywany ciąg nie jest pustym ciągiem:

".validate": "newData.isString() && newData.val().length > 0"

< (mniej niż)

Służy do sprawdzania, czy wartość jest mniejsza niż inna wartość w wyrażeniu reguły.

Ta reguła sprawdzania poprawności sprawdza, czy ciąg znaków ma mniej niż 20 znaków:

".validate": "newData.isString() && newData.val().length < 20"

>= (większy lub równy)

Służy do sprawdzania, czy wartość jest większa lub równa innej wartości w wyrażeniu reguły.

Ta reguła sprawdzania poprawności sprawdza, czy zapisywany ciąg nie jest pustym ciągiem:

".validate": "newData.isString() && newData.val().length >= 1"

<= (mniejszy lub równy)

Służy do sprawdzania, czy wartość jest mniejsza lub równa innej wartości w wyrażeniu reguły.

Ta zasada sprawdzania poprawności gwarantuje, że w przyszłości nie będzie można dodać nowych danych:

".validate": "newData.val() <= now"

? (operator trójskładnikowy)

Służy do oceny wyrażenia reguł warunkowych.

Operator trójskładnikowy przyjmuje trzy operandy. Operand przed ? jest warunkiem. Jeśli warunek ma wartość true, obliczany jest drugi operand. Jeśli warunek jest fałszywy, obliczany jest trzeci operand.

W przypadku poniższej reguły sprawdzania poprawności nowa wartość może być liczbą lub wartością logiczną. Jeśli jest to liczba, musi być większa niż 0.

".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"