Questa guida di riferimento tratta la sintassi di Common Expression Language (CEL) pertinente alla creazione di espressioni per le direttive @auth(expr:) e @check(expr:).
Le informazioni di riferimento complete per CEL sono disponibili nella specifica CEL.
Testare le variabili passate in query e mutazioni
La sintassi @auth(expr) consente di accedere alle variabili di query e mutazioni e di testarle.
Ad esempio, puoi includere una variabile di operazione, come $status, utilizzando vars.status.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
Dati disponibili per le espressioni: request, response, this
Utilizzi i dati per:
- Valutazione con espressioni CEL nelle direttive
@auth(expr:)e@check(expr:) - Assegnazione utilizzando espressioni server,
<field>_expr.
Le espressioni CEL @auth(expr:) e @check(expr:) possono valutare quanto segue:
request.operationNamevars(alias direquest.variables)auth(alias direquest.auth)
Nelle mutazioni, puoi accedere ai contenuti di quanto segue e assegnarli:
response(per controllare i risultati parziali nella logica multi-step)
Inoltre, le espressioni @check(expr:) possono valutare:
this(il valore del campo corrente)response(per controllare i risultati parziali nella logica multi-step)
L'associazione request.operationName
L'associazione request.operarationName memorizza il tipo di operazione, query o mutazione.
L'associazione vars (request.vars)
L'associazione vars consente alle espressioni di accedere a tutte le variabili passate nella query o nella mutazione.
Puoi utilizzare vars.<variablename> in un'espressione come alias per
request.variables.<variablename> con nome completo:
# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")
L'associazione auth (request.auth)
Authentication identifica gli utenti che richiedono l'accesso ai tuoi dati e fornisce queste informazioni come un'associazione su cui puoi basarti nelle tue espressioni.
Nei filtri e nelle espressioni, puoi utilizzare auth come alias di
request.auth.
L'associazione auth contiene le seguenti informazioni:
uid: un ID utente univoco, assegnato all'utente richiedente.token: una mappa di valori raccolti da Authentication.
Per maggiori dettagli sui contenuti di auth.token, consulta
Dati nei token di autenticazione
L'associazione response
L'associazione response contiene i dati assemblati dal server in risposta a una query o a una mutazione durante l'assemblaggio.
Man mano che l'operazione procede e ogni passaggio viene completato correttamente, response contiene i dati di risposta dei passaggi completati correttamente.
L'associazione response è strutturata in base alla forma dell'operazione associata, inclusi i campi nidificati (multipli) e (se applicabile) le query incorporate.
Tieni presente che quando accedi ai dati di risposta della query incorporata, i campi possono contenere
qualsiasi tipo di dati, a seconda dei dati richiesti nella query incorporata; quando accedi ai dati restituiti dai campi di mutazione come _insert e _delete, possono contenere chiavi UUID, numero di eliminazioni, valori null (consulta il
riferimento alle mutazioni).
Ad esempio:
- In una mutazione che contiene una query incorporata, l'
responseassociazione contiene i dati di ricerca inresponse.query.<fieldName>.<fieldName>...., in questo caso,response.query.todoListeresponse.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
}
}
}
- In una mutazione multi-step, ad esempio con più campi
_insert, l'responsebinding contiene dati parziali inresponse.<fieldName>.<fieldName>...., in questo caso,response.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,
})
}
L'associazione this
L'associazione this restituisce il campo a cui è collegata la direttiva @check. In un caso di base, potresti valutare i risultati di query a valore singolo.
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
})
}
Se il campo restituito si verifica più volte perché un antenato è un elenco, ogni occorrenza viene testata con this associato a ogni valore.
Per un determinato percorso, se un predecessore è null o [], il campo non verrà raggiunto e la valutazione CEL verrà ignorata per quel percorso. In altre parole, la valutazione avviene solo quando this è null o non null, ma mai undefined.
Quando il campo stesso è un elenco o un oggetto, this segue la stessa struttura (inclusi tutti i discendenti selezionati in caso di oggetti), come illustrato nell'esempio seguente.
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
})
}
Sintassi di espressioni complesse
Puoi scrivere espressioni più complesse combinandole con gli && e ||
operatori.
mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")
La sezione seguente descrive tutti gli operatori disponibili.
Operatori e precedenza degli operatori
Utilizza la tabella seguente come riferimento per gli operatori e la relativa precedenza.
Date espressioni arbitrarie a e b, un campo f e un indice i.
| Operatore | Descrizione | Associatività |
|---|---|---|
a[i] a() a.f |
Indice, chiamata, accesso al campo | da sinistra a destra |
!a -a |
Negazione unaria | da destra a sinistra |
a/b a%b a*b |
Operatori moltiplicativi | da sinistra a destra |
a+b a-b |
Operatori additivi | da sinistra a destra |
a>b a>=b a<b a<=b |
Operatori relazionali | da sinistra a destra |
a in b |
Esistenza in elenco o mappa | da sinistra a destra |
type(a) == t |
Confronto di tipi, dove t può essere bool, int, float,
number, string, list, map, timestamp o duration |
da sinistra a destra |
a==b a!=b |
Operatori di confronto | da sinistra a destra |
a && b |
AND condizionale | da sinistra a destra |
a || b |
OR condizionale | da sinistra a destra |
a ? true_value : false_value |
Espressione ternaria | da sinistra a destra |
Dati nei token di autenticazione
L'oggetto auth.token può contenere i seguenti valori:
| Campo | Descrizione |
|---|---|
email |
L'indirizzo email associato all'account, se presente. |
email_verified |
true se l'utente ha verificato di avere accesso all'indirizzo email. Alcuni provider verificano automaticamente gli indirizzi email di loro proprietà. |
phone_number |
Il numero di telefono associato all'account, se presente. |
name |
Il nome visualizzato dell'utente, se impostato. |
sub |
L'UID Firebase dell'utente. È univoco all'interno di un progetto. |
firebase.identities |
Dizionario di tutte le identità associate all'account di questo utente. Le chiavi del dizionario possono essere una delle seguenti: email, phone, google.com, facebook.com, github.com, twitter.com. I valori del dizionario sono array di identificatori univoci per ogni provider di identità associato all'account. Ad esempio, auth.token.firebase.identities["google.com"][0] contiene il primo ID utente Google associato all'account. |
firebase.sign_in_provider |
Il provider di accesso utilizzato per ottenere questo token. Può essere una delle seguenti stringhe: custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com. |
firebase.tenant |
Il tenantId associato all'account, se presente. Ad esempio, tenant2-m6tyz |
Campi aggiuntivi nei token ID JWT
Puoi anche accedere ai seguenti campi auth.token:
| Attestazioni token personalizzate | ||
|---|---|---|
alg |
Algoritmo | "RS256" |
iss |
Emittente | L'indirizzo email del service account del tuo progetto |
sub |
Oggetto | L'indirizzo email del service account del tuo progetto |
aud |
Pubblico | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Ora di emissione | L'ora attuale, in secondi dall'epoca UNIX |
exp |
Scadenza |
L'ora, in secondi dall'epoca UNIX, in cui il token scade. Può
essere al massimo 3600 secondi dopo iat.
Nota: questo controlla solo l'ora di scadenza del token personalizzato stesso. Tuttavia, una volta che un utente ha eseguito l'accesso utilizzando signInWithCustomToken(), rimarrà connesso al
dispositivo finché la sua sessione non viene invalidata o l'utente non esegue la disconnessione.
|
<claims> (facoltativo) |
Attestazioni personalizzate facoltative da includere nel token, a cui è possibile accedere tramite
auth.token (o request.auth.token) nelle
espressioni. Ad esempio, se crei un'attestazione personalizzata
adminClaim, puoi accedervi con
auth.token.adminClaim.
|
|