Dokumentacja składni języka Common Expression Language w usłudze Data Connect

Ten przewodnik zawiera informacje o składni języka Common Expression Language (CEL) przydatnej do tworzenia wyrażeń w przypadku dyrektyw @auth(expr:)@check(expr:).

Pełne informacje referencyjne dotyczące CEL znajdziesz w specyfikacji CEL.

Testowanie zmiennych przekazywanych w zapytaniach i mutacjach

Składnia @auth(expr) umożliwia dostęp do zmiennych z zapytań i mutacji oraz ich testowanie.

Możesz na przykład użyć zmiennej operacji, takiej jak $status, za pomocą parametru vars.status.

mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")

Dane dostępne dla wyrażeń

Zarówno wyrażenia CEL @auth(expr:), jak i @check(expr:) mogą oceniać te elementy:

  • request.operationName
  • vars (alias do request.variables)
  • auth (alias do request.auth)

Dodatkowo wyrażenia @check(expr:) mogą oceniać:

  • this (wartość bieżącego pola)

Obiekt request.operationName

Obiekt request.operarationName przechowuje typ operacji, czyli zapytanie lub mutację.

Obiekt vars

Obiekt vars umożliwia wyrażeniom dostęp do wszystkich zmiennych przekazanych w zapytaniu lub mutacji.

Możesz użyć w wyrażeniu atrybutu vars.<variablename> jako aliasu pełnego atrybutu request.variables.<variablename>:

# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")

Obiekt auth

Authentication identyfikuje użytkowników, którzy proszą o dostęp do Twoich danych, i przekazuje te informacje jako obiekt, na podstawie którego możesz budować swoje wyrażenia.

W filtrach i wyrażeniach możesz używać wartości auth jako aliasu wartości request.auth.

Obiekt auth zawiera te informacje:

  • uid: unikalny identyfikator użytkownika przypisany do użytkownika przesyłającego żądanie.
  • token: mapa wartości zebranych przez Authentication.

Więcej informacji o zawartości pola auth.token znajdziesz w artykule Dane w tokenach uwierzytelniania.

Powiązanie this

Powiązanie this zwraca pole, do którego jest przypisane pole dyrektywy @check. W najprostszym przypadku możesz analizować wyniki zapytania o pojedynczej wartości.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    ) {
      # Check if the user has the editor role for the movie. `this` is the string value of `role`.
      # If the parent moviePermission is null, the @check will also fail automatically.
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

Jeśli zwracane pole występuje kilka razy, ponieważ każdy z jego przodków jest listą, każde wystąpienie jest testowane z użyciem this powiązanego z każdą wartością.

W przypadku dowolnej ścieżki, jeśli jeden z jej elementów jest elementem nadrzędnym null lub [], nie dojdzie do odwołania się do pola i ocena CEL zostanie pominięta. Inaczej mówiąc, sprawdzanie odbywa się tylko wtedy, gdy this ma wartość null lub nie-null, ale nigdy undefined.

Gdy samo pole jest listą lub obiektem, this ma taką samą strukturę (w tym wszystkich potomków wybranych w przypadku obiektów), jak w tym przykładzie.

mutation UpdateMovieTitle2($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query {
    moviePermissions( # Now we query for a list of all matching MoviePermissions.
      where: {movieId: {eq: $movieId}, userId: {eq_expr: "auth.uid"}}
    # This time we execute the @check on the list, so `this` is the list of objects.
    # We can use the `.exists` macro to check if there is at least one matching entry.
    ) @check(expr: "this.exists(p, p.role == 'editor')", message: "You must be an editor of this movie to update title") {
      role
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

Składnia wyrażeń złożonych

Aby tworzyć bardziej złożone wyrażenia, możesz łączyć operatory &&||.

mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")

W sekcji poniżej opisujemy wszystkie dostępne operatory.

Operatory i pierwotność operatorów

Poniższa tabela zawiera informacje o operatorach i odpowiednim dla nich priorytecie.

Załóżmy dowolne wyrażenia ab, pole f oraz indeks i.

Operator Opis Związek
a[i] a() a.f Indeksowanie, wywoływanie i dostęp do pól od lewej do prawej.
!a -a Negacja unarna od prawej do lewej
a/b a%b a*b Operatory mnożenia od lewej do prawej.
a+b a-b Operatory addytywne od lewej do prawej.
a>b a>=b a<b a<=b Operatory relacji od lewej do prawej.
a in b występowanie na liście lub mapie; od lewej do prawej.
type(a) == t Porównanie typu, gdzie t może być wartością logiczną, liczbą całkowitą, liczbą zmiennoprzecinkową, liczbą, ciągiem znaków, listą, mapą, sygnaturą czasową lub czasem trwania. od lewej do prawej.
a==b a!=b Operatory porównania od lewej do prawej.
a && b Warunkowe AND od lewej do prawej.
a || b Warunkowe LUB od lewej do prawej.
a ? true_value : false_value Wyrażenie warunkowe od lewej do prawej.

Dane w tokenach uwierzytelniania

Obiekt auth.token może zawierać te wartości:

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ą należące do siebie adresy e-mail.
phone_number numer telefonu powiązany z kontem (jeśli istnieje);
name Wyświetlana nazwa użytkownika (jeśli została ustawiona).
sub Identyfikator UID użytkownika w Firebase. Musi być niepowtarzalny w ramach projektu.
firebase.identities Słownik wszystkich tożsamości powiązanych z kontem tego użytkownika. Klucze słownika mogą być dowolnymi z tych elementów: email, phone, google.com, facebook.com, github.com, twitter.com. Wartości w słowniku 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 pierwsze identyfikator użytkownika Google powiązany z kontem.
firebase.sign_in_provider Dostawca logowania użyty do uzyskania tego tokena. Może być dowolnym z tych ciągów: custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com.
firebase.tenant Identyfikator tenantId powiązany z kontem (jeśli występuje). na przykład tenant2-m6tyz.

Dodatkowe pola w tokenach identyfikacyjnych JWT

Możesz też uzyskać dostęp do tych pól auth.token:

Deklaracje tokenów niestandardowych
alg Algorytm "RS256"
iss Wystawca Adres e-mail konta usługi projektu
sub Temat Adres e-mail konta usługi projektu
aud Odbiorcy "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Issued-at time Bieżący czas w sekundach od początku epoki UNIX
exp Okres ważności Czas w sekundach od początku epoki UNIX, w którym token traci ważność. Może ona nastąpić maksymalnie 3600 sekund później niż iat.
Uwaga: to ustawienie określa tylko czas wygaśnięcia tokenu niestandardowego. Jednak po zalogowaniu użytkownika za pomocą opcji signInWithCustomToken() będzie on zalogowany na urządzeniu do czasu unieważnienia sesji lub wylogowania się.
<claims> (opcjonalnie) Opcjonalne oświadczenia niestandardowe do uwzględnienia w tokenie, do których można uzyskać dostęp za pomocą funkcji auth.token (lub request.auth.token) w wyrażeniach. Jeśli na przykład utworzysz roszczenie niestandardowe adminClaim, możesz uzyskać do niego dostęp za pomocą auth.token.adminClaim.