In diesem Referenzhandbuch wird die CEL-Syntax (Common Expression Language) behandelt, die für das Erstellen von Ausdrücken für die Direktiven @auth(expr:)
und @check(expr:)
relevant ist.
Vollständige Referenzinformationen zu CEL finden Sie in der CEL-Spezifikation.
Testvariablen, die in Abfragen und Mutationen übergeben werden
Mit der @auth(expr)
-Syntax können Sie auf Variablen aus Abfragen und Mutationen zugreifen und sie testen.
Sie können beispielsweise eine Vorgangsvariable wie $status
mit vars.status
einfügen.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
Für Ausdrücke verfügbare Daten: request, response, this
Sie verwenden Daten für:
- Auswertung mit CEL-Ausdrücken in
@auth(expr:)
- und@check(expr:)
-Direktiven - Zuweisung mit Serverausdrücken,
<field>_expr
.
Sowohl @auth(expr:)
- als auch @check(expr:)
-CEL-Ausdrücke können Folgendes auswerten:
request.operationName
vars
(Alias fürrequest.variables
)auth
(Alias fürrequest.auth
)
In Mutationen können Sie auf die Inhalte von Folgendem zugreifen und sie zuweisen:
response
(zum Prüfen von Teilergebnissen in der mehrstufigen Logik)
Außerdem können @check(expr:)
-Ausdrücke Folgendes auswerten:
this
(der Wert des aktuellen Felds)response
(zum Prüfen von Teilergebnissen in der mehrstufigen Logik)
Die Bindung „request.operationName“
Die request.operarationName
-Bindung speichert den Vorgangstyp, entweder „query“ (Abfrage) oder „mutation“ (Mutation).
Die vars
-Bindung (request.vars)
Mit der vars
-Bindung können Ihre Ausdrücke auf alle Variablen zugreifen, die in Ihrer Abfrage oder Mutation übergeben werden.
Sie können vars.<variablename>
in einem Ausdruck als Alias für den vollständig qualifizierten request.variables.<variablename>
verwenden:
# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")
Die auth
-Bindung (request.auth)
Mit Authentication werden Nutzer identifiziert, die Zugriff auf Ihre Daten anfordern. Diese Informationen werden als Bindung bereitgestellt, die Sie in Ihren Ausdrücken verwenden können.
In Ihren Filtern und Ausdrücken können Sie auth
als Alias für request.auth
verwenden.
Die Authentifizierungsbindung enthält die folgenden Informationen:
uid
: Eine eindeutige Nutzer-ID, die dem anfragenden Nutzer zugewiesen ist.token
: Eine Zuordnung von Werten, die von Authentication erfasst wurden.
Weitere Informationen zum Inhalt von auth.token
findest du unter Daten in Autorisierungstokens.
Die response
-Bindung
Die response
-Bindung enthält die Daten, die vom Server als Reaktion auf eine Abfrage oder Mutation während der Zusammenstellung zusammengestellt werden.
Im Laufe des Vorgangs enthält response
nach jedem erfolgreich abgeschlossenen Schritt Antwortdaten.
Die response
-Bindung ist entsprechend der Form des zugehörigen Vorgangs strukturiert, einschließlich (mehrerer) verschachtelter Felder und (falls zutreffend) eingebetteter Abfragen.
Wenn Sie auf eingebettete Abfrageantwortdaten zugreifen, können Felder je nach den in der eingebetteten Abfrage angeforderten Daten einen beliebigen Datentyp enthalten. Wenn Sie auf Daten zugreifen, die von Mutationsfeldern wie _insert
und _delete
zurückgegeben werden, können diese UUID-Schlüssel, die Anzahl der Löschvorgänge und Nullwerte enthalten (siehe Mutationsreferenz).
Beispiel:
- In einer Mutation, die eine eingebettete Abfrage enthält, enthält die
response
-Bindung Lookup-Daten unterresponse.query.<fieldName>.<fieldName>....
, in diesem Fallresponse.query.todoList
undresponse.query.todoList.priority
.
mutation CheckTodoPriority(
$uniqueListName: String!
) {
# This query is identified as `response.query`
query @check(expr: "response.query.todoList.priority == 'high'", message: "This list is not for high priority items!") {
# This field is identified as `response.query.todoList`
todoList(where: { name: $uniqueListName }) {
# This field is identified as `response.query.todoList.priority`
priority
}
}
}
- Bei einer mehrstufigen Mutation, z. B. mit mehreren
_insert
-Feldern, enthält dieresponse
-Bindung Teildaten unterresponse.<fieldName>.<fieldName>....
, in diesem Fallresponse.todoList_insert.id
.
mutation CreateTodoListWithFirstItem(
$listName: String!,
$itemContent: String!
) @transaction {
# Step 1
todoList_insert(data: {
id_expr: "uuidV4()",
name: $listName,
})
# Step 2:
todo_insert(data: {
listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
content: $itemContent,
})
}
Die this
-Bindung
Die Bindung this
wird zum Feld ausgewertet, an das die @check
-Anweisung angehängt ist. Im einfachsten Fall werten Sie Ergebnisse von Anfragen mit einem einzelnen Wert aus.
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
})
}
Wenn das zurückgegebene Feld mehrmals vorkommt, weil ein übergeordnetes Element eine Liste ist, wird jedes Vorkommen mit this
getestet, wobei this
an jeden Wert gebunden ist.
Wenn ein Vorfahre für einen bestimmten Pfad null
oder []
ist, wird das Feld nicht erreicht und die CEL-Auswertung für diesen Pfad wird übersprungen. Die Auswertung erfolgt also nur, wenn this
null
oder nicht null
ist, aber nie undefined
.
Wenn das Feld selbst eine Liste oder ein Objekt ist, folgt this
derselben Struktur (einschließlich aller ausgewählten untergeordneten Elemente im Fall von Objekten), wie im folgenden Beispiel veranschaulicht.
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
})
}
Syntax für komplexe Ausdrücke
Sie können komplexere Ausdrücke schreiben, indem Sie sie mit den Operatoren &&
und ||
kombinieren.
mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")
Im folgenden Abschnitt werden alle verfügbaren Operatoren beschrieben.
Operatoren und Operator-Vorrang
In der folgenden Tabelle finden Sie eine Übersicht über die Operatoren und ihre entsprechende Priorität.
Angenommen, es gibt beliebige Ausdrücke a
und b
, ein Feld f
und einen Index i
.
Operator | Beschreibung | Assoziativität |
---|---|---|
a[i] a() a.f |
Index, Aufruf, Feldzugriff | von links nach rechts |
!a -a |
Unäre Negation | von rechts nach links |
a/b a%b a*b |
Multiplikative Operatoren | von links nach rechts |
a+b a-b |
Additive Operatoren | von links nach rechts |
a>b a>=b a<b a<=b |
Relationale Operatoren | von links nach rechts |
a in b |
Vorhandensein in der Liste oder auf der Karte | von links nach rechts |
type(a) == t |
Typvergleich, wobei t bool, int, float, number, string, list, map, timestamp oder duration sein kann |
von links nach rechts |
a==b a!=b |
Vergleichsoperatoren | von links nach rechts |
a && b |
Bedingtes AND | von links nach rechts |
a || b |
Bedingtes ODER | von links nach rechts |
a ? true_value : false_value |
Ternärer Ausdruck | von links nach rechts |
Daten in Auth-Tokens
Das auth.token
-Objekt kann die folgenden Werte enthalten:
Feld | Beschreibung |
---|---|
email |
Die mit dem Konto verknüpfte E-Mail-Adresse, falls vorhanden. |
email_verified |
true , wenn der Nutzer bestätigt hat, dass er Zugriff auf die Adresse email hat. Einige Anbieter bestätigen automatisch E-Mail-Adressen, die ihnen gehören. |
phone_number |
Die mit dem Konto verknüpfte Telefonnummer, falls vorhanden. |
name |
Der Anzeigename des Nutzers, falls festgelegt. |
sub |
Die Firebase-UID des Nutzers. Sie ist innerhalb eines Projekts eindeutig. |
firebase.identities |
Verzeichnis aller Identitäten, die mit dem Konto dieses Nutzers verknüpft sind. Die Schlüssel des Dictionarys können einer der folgenden Werte sein: email , phone , google.com , facebook.com , github.com , twitter.com . Die Werte des Dictionary sind Arrays mit eindeutigen Kennungen für jeden Identitätsanbieter, der mit dem Konto verknüpft ist. auth.token.firebase.identities["google.com"][0] enthält beispielsweise die erste Google-Nutzer-ID, die mit dem Konto verknüpft ist. |
firebase.sign_in_provider |
Der Anmeldeanbieter, der zum Abrufen dieses Tokens verwendet wurde. Kann einer der folgenden Strings sein: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant |
Die dem Konto zugeordnete „tenantId“, falls vorhanden. Beispiel: tenant2-m6tyz |
Zusätzliche Felder in JWT-ID-Tokens
Sie können auch auf die folgenden auth.token
-Felder zugreifen:
Benutzerdefinierte Token-Anforderungen | ||
---|---|---|
alg |
Algorithmus | "RS256" |
iss |
Aussteller | Die E-Mail-Adresse des Dienstkontos Ihres Projekts |
sub |
Betreff | Die E-Mail-Adresse des Dienstkontos Ihres Projekts |
aud |
Zielgruppe | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Ausstellungszeit | Die aktuelle Zeit in Sekunden seit der UNIX-Epoche. |
exp |
Ablaufzeit |
Die Zeit in Sekunden seit der UNIX-Epoche, zu der das Token abläuft. Dies kann maximal 3.600 Sekunden später als iat sein.
Beachten Sie, dass damit nur der Zeitpunkt gesteuert wird, zu dem das benutzerdefinierte Token selbst abläuft. Wenn Sie jedoch einen Nutzer mit signInWithCustomToken() anmelden, bleiben er so lange auf dem Gerät angemeldet, bis die Sitzung ungültig wird oder der Nutzer sich abmeldet.
|
<claims> (optional) |
Optionale benutzerdefinierte Anforderungen, die in das Token aufgenommen werden sollen und über auth.token (oder request.auth.token ) in Ausdrücken aufgerufen werden können. Wenn Sie beispielsweise einen benutzerdefinierten Anspruch adminClaim erstellen, können Sie mit auth.token.adminClaim darauf zugreifen.
|