Este guia de referência abrange 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 de referência completas sobre a 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: request, response, this
Você usa dados para:
- Avaliação com expressões CEL em diretivas
@auth(expr:)
e@check(expr:)
- Atribuição usando expressões do servidor,
<field>_expr
.
As expressões CEL @auth(expr:)
e @check(expr:)
podem avaliar o
seguinte:
request.operationName
vars
(alias pararequest.variables
)auth
(alias pararequest.auth
)
Nas mutações, é possível acessar e atribuir o conteúdo de:
response
(para verificar resultados parciais na lógica de várias etapas)
Além disso, as expressões @check(expr:)
podem avaliar:
this
(o valor do campo atual)response
(para verificar resultados parciais na lógica de várias etapas)
A vinculação request.operationName
A vinculação request.operarationName
armazena o tipo de operação, consulta
ou mutação.
A vinculação vars
(request.vars)
A vinculação 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'")
A vinculação auth
(request.auth)
Authentication identifica os usuários que solicitam acesso aos seus dados e fornece essas informações como uma vinculação que pode ser usada nas suas expressões.
Nos filtros e expressões, é possível usar auth
como um alias para
request.auth
.
A vinculação 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 response
A vinculação response
contém os dados que estão sendo montados pelo servidor em
resposta a uma consulta ou mutação enquanto esses dados estão sendo montados.
À medida que a operação avança e cada etapa é concluída,
response
contém dados de resposta das etapas concluídas.
A vinculação response
é estruturada de acordo com a forma da operação
associada, incluindo (vários) campos aninhados e (se aplicável) consultas
embutidas.
Quando você acessa dados de resposta de consulta incorporados, os campos podem conter
qualquer tipo de dados, dependendo dos dados solicitados na consulta incorporada. Quando você
acessa dados retornados por campos de mutação, como _insert
s e _delete
s, eles podem
conter chaves UUID, número de exclusões e valores nulos (consulte a
referência de mutações).
Exemplo:
- Em uma mutação que contém uma consulta incorporada, a vinculação
response
contém dados de pesquisa emresponse.query.<fieldName>.<fieldName>....
, neste caso,response.query.todoList
eresponse.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
}
}
}
- Em uma mutação em várias etapas, por exemplo, com vários campos
_insert
, a vinculaçãoresponse
contém dados parciais emresponse.<fieldName>.<fieldName>....
, neste 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,
})
}
A vinculação this
A vinculação this
é avaliada para 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 abaixo.
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 .
|