Este guia de referência aborda a sintaxe da linguagem de expressão comum (CEL) relevante para
criar expressões para as diretivas @auth(expr:)
e @check(expr:)
.
As informações completas de referência da CEL estão disponíveis na especificação da CEL.
Testar variáveis transmitidas em consultas e mutações
A sintaxe @auth(expr)
permite acessar e testar variáveis de consultas e
mutações.
Por exemplo, é possível incluir uma variável de operação, como $status
, usando
vars.status
.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
Dados disponíveis para expressões
As expressões CEL @auth(expr:)
e @check(expr:)
podem avaliar o
seguinte:
request.operationName
vars
(alias pararequest.variables
)auth
(alias pararequest.auth
)
Além disso, as expressões @check(expr:)
podem avaliar:
this
(o valor do campo atual)
O objeto request.operationName
O objeto request.operarationName
armazena o tipo de operação, consulta
ou mutação.
O objeto vars
O objeto vars
permite que as expressões acessem todas as variáveis
transmitidas na consulta ou mutação.
É possível usar vars.<variablename>
em uma expressão como um alias para o
request.variables.<variablename>
totalmente qualificado:
# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")
O objeto auth
Authentication identifica os usuários que solicitam acesso aos seus dados e fornece essas informações como um objeto que pode ser usado nas suas expressões.
Nos filtros e expressões, é possível usar auth
como um alias para
request.auth
.
O objeto de autenticação contém as seguintes informações:
uid
: um ID de usuário exclusivo, atribuído ao usuário solicitante.token
: um mapa de valores coletados por Authentication.
Para mais detalhes sobre o conteúdo de auth.token
, consulte
Dados em tokens de autenticação.
A vinculação this
A vinculação this
é avaliada como o campo ao qual a diretiva @check
está anexada. Em um caso básico, você pode avaliar resultados de consulta
de valor único.
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 o campo retornado ocorrer várias vezes porque algum ancestral é uma lista, cada
ocorrência será testada com this
vinculado a cada valor.
Para qualquer caminho, se um ancestral for null
ou []
, o campo não será
alcançado e a avaliação do CEL será ignorada para esse caminho. Em outras palavras,
a avaliação só acontece quando this
é null
ou não é null
, mas nunca
undefined
.
Quando o campo é uma lista ou um objeto, this
segue a mesma estrutura (incluindo todos os descendentes selecionados no caso de objetos), conforme ilustrado no exemplo a seguir.
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
})
}
Sintaxe de expressão complexa
É possível escrever expressões mais complexas combinando com os operadores &&
e ||
.
mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")
A seção a seguir descreve todos os operadores disponíveis.
Operadores e precedência do operador
Use a tabela a seguir como referência para os operadores e a precedência correspondente.
Expressões arbitrárias fornecidas a
e b
, um campo f
e um índice i
.
Operador | Descrição | Associatividade |
---|---|---|
a[i] a() a.f |
Índice, chamada, acesso ao campo | da esquerda para a direita |
!a -a |
Negação unária | da direita para a esquerda |
a/b a%b a*b |
Operadores multiplicativos | da esquerda para a direita |
a+b a-b |
Operadores aditivos | da esquerda para a direita |
a>b a>=b a<b a<=b |
Operadores relacionais | da esquerda para a direita |
a in b |
Existência na lista ou no mapa | da esquerda para a direita |
type(a) == t |
Comparação de tipos, em que t pode ser bool, int, float,
number, string, list, map, timestamp ou duration |
da esquerda para a direita |
a==b a!=b |
Operadores de comparação | da esquerda para a direita |
a && b |
Condicional E | da esquerda para a direita |
a || b |
Condicional OU | da esquerda para a direita |
a ? true_value : false_value |
Expressão ternária | da esquerda para a direita |
Dados em tokens de autenticação
O objeto auth.token
pode conter os seguintes valores:
Campo | Descrição |
---|---|
email |
O endereço de e-mail associado à conta, se essa informação existir. |
email_verified |
true se o usuário tiver verificado que tem acesso ao endereço email . Alguns provedores verificam automaticamente esses endereços de e-mail. |
phone_number |
O número de telefone associado à conta, se essa informação existir. |
name |
O nome de exibição do usuário, se ele tiver sido definido. |
sub |
O UID do Firebase do usuário. Ele é exclusivo dentro de um projeto. |
firebase.identities |
O dicionário de todas as identidades associadas à conta desse usuário. As chaves do dicionário podem ser qualquer uma das seguintes: email , phone , google.com , facebook.com , github.com , twitter.com . Os valores do dicionário são matrizes de identificadores exclusivos de cada provedor de identidade associado à conta. Por exemplo, auth.token.firebase.identities["google.com"][0] contém o primeiro ID de usuário do Google associado à conta. |
firebase.sign_in_provider |
O provedor de entrada usado para receber esse token. Pode ser uma das seguintes strings: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant |
O ID do locatário associado à conta, se houver. Por exemplo, tenant2-m6tyz . |
Outros campos em tokens de ID JWT
Também é possível acessar os seguintes campos auth.token
:
Declarações de tokens personalizados | ||
---|---|---|
alg |
Algoritmo | "RS256" |
iss |
Emissor | Endereço de e-mail da conta de serviço do seu projeto |
sub |
Assunto | Endereço de e-mail da conta de serviço do seu projeto |
aud |
Público | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Hora de emissão | A hora atual, em segundos, desde a época do UNIX |
exp |
Tempo de expiração |
O tempo, em segundos, desde a época do UNIX, em que o token expira. Pode ser no máximo 3.600 segundos depois de iat .
Observação: ele controla o tempo apenas quando o token personalizado expira. No entanto, quando você faz o login de um usuário utilizando signInWithCustomToken() , ele permanece conectado ao
dispositivo até que a sessão seja invalidada ou que o usuário se desconecte.
|
<claims> (opcional) |
Declarações personalizadas opcionais a serem incluídas no token, que podem ser acessadas por
auth.token (ou request.auth.token ) nas
expressões. Por exemplo, se você criar uma reivindicação personalizada
adminClaim , poderá acessá-la com
auth.token.adminClaim .
|