Referencia de sintaxis de Common Expression Language para Data Connect

Esta guía de referencia abarca la sintaxis de Common Expression Language (CEL) pertinente para crear expresiones para las directivas @auth(expr:) y @check(expr:).

Se proporciona información de referencia completa para CEL en la especificación de CEL.

Variables de prueba que se pasan en consultas y mutaciones

La sintaxis @auth(expr) te permite acceder a las variables de consultas y mutaciones, y probarlas.

Por ejemplo, puedes incluir una variable de operación, como $status, con vars.status.

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

Datos disponibles para expresiones: request, response, this

Usas datos para lo siguiente:

  • Evaluación con expresiones CEL en @auth(expr:) y @check(expr:) directivas
  • Asignación con expresiones del servidor, <field>_expr

Las expresiones CEL @auth(expr:) y @check(expr:) pueden evaluar lo siguiente:

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

En las mutaciones, puedes acceder al contenido de lo siguiente y asignarlo:

  • response (para verificar resultados parciales en la lógica de varios pasos)

Además, las expresiones @check(expr:) pueden evaluar lo siguiente:

  • this (el valor del campo actual)
  • response (para verificar resultados parciales en la lógica de varios pasos)

La vinculación request.operationName

La vinculación request.operarationName almacena el tipo de operación, ya sea una consulta o una mutación.

La vinculación vars (request.vars)

La vinculación vars permite que tus expresiones accedan a todas las variables que se pasan en tu consulta o mutación.

Puedes usar vars.<variablename> en una expresión como alias de completamente calificado 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'")

La vinculación auth (request.auth)

Authentication identifica a los usuarios que solicitan acceso a tus datos y proporciona esa información como una vinculación que puedes aprovechar en tus expresiones.

En tus filtros y expresiones, puedes usar auth como alias de request.auth.

La vinculación auth contiene la siguiente información:

  • uid: un ID de usuario único, asignado al usuario solicitante.
  • token: un mapa de valores recopilados por Authentication.

Para obtener más detalles sobre el contenido de auth.token, consulta Datos en tokens de autenticación

La vinculación response

La vinculación response contiene los datos que el servidor ensambla en respuesta a una consulta o mutación a medida que se ensamblan esos datos.

A medida que avanza la operación, y a medida que se completa cada paso de forma correcta, response contiene datos de respuesta de los pasos completados correctamente.

La vinculación response se estructura según la forma de su operación asociada, incluidos los campos anidados (múltiples) y las consultas incorporadas (si corresponde) .

Ten en cuenta que, cuando accedes a datos de respuesta de consultas incorporadas, los campos pueden contener cualquier tipo de datos, según los datos solicitados en la consulta incorporada. Cuando accedes a los datos que muestran los campos de mutación, como _insert y _delete, pueden contener claves UUID, cantidad de eliminaciones, valores nulos (consulta la referencia de mutaciones).

Por ejemplo:

  • En una mutación que contiene una consulta incorporada, la response vinculación contiene datos de búsqueda en response.query.<fieldName>.<fieldName>...., en este caso, response.query.todoList y response.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
    }
  }
}
  • En una mutación de varios pasos, por ejemplo, con varios campos _insert, la response vinculación contiene datos parciales en response.<fieldName>.<fieldName>...., en este 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,
  })
}

La vinculación this

La vinculación this se evalúa en el campo al que está adjunta la directiva @check. En un caso básico, puedes evaluar los resultados de consultas de un solo valor.

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
  })
}

Si el campo que se muestra aparece varias veces porque algún antecesor es una lista, cada aparición se prueba con this vinculada a cada valor.

Para cualquier ruta determinada, si un antecesor es null o [], no se alcanzará el campo y se omitirá la evaluación de CEL para esa ruta. En otras palabras, la evaluación solo se realiza cuando this es null o no es null, pero nunca undefined.

Cuando el campo en sí es una lista o un objeto, this sigue la misma estructura (incluidos todos los descendientes seleccionados en el caso de los objetos), como se ilustra en el siguiente ejemplo.

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
  })
}

Sintaxis de expresiones complejas

Puedes escribir expresiones más complejas combinando con los && y || operadores.

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

En la siguiente sección, se describen todos los operadores disponibles.

Operadores y prioridad de operadores

Usa la siguiente tabla como referencia para los operadores y su prioridad correspondiente.

Dadas las expresiones arbitrarias a y b, un campo f y un índice i.

Operador Descripción Asociatividad
a[i] a() a.f Acceso a índice, llamada o campo de izquierda a derecha
!a -a Negación unaria De derecha a izquierda
a/b a%b a*b Operadores multiplicativos de izquierda a derecha
a+b a-b Operadores aditivos de izquierda a derecha
a>b a>=b a<b a<=b Operadores relacionales de izquierda a derecha
a in b Existencia en lista o mapa de izquierda a derecha
type(a) == t Comparación de tipos, en la que t puede ser bool, int, float, number, string, list, map, timestamp o duration de izquierda a derecha
a==b a!=b Operadores de comparación de izquierda a derecha
a && b Condicional AND de izquierda a derecha
a || b Condicional OR de izquierda a derecha
a ? true_value : false_value Expresión ternaria de izquierda a derecha

Datos en tokens de autenticación

El objeto auth.token puede contener los siguientes valores:

Campo Descripción
email Dirección de correo electrónico asociada con la cuenta, si está presente.
email_verified true si el usuario verificó que tiene acceso a la dirección email. Algunos proveedores verifican automáticamente las direcciones de correo electrónico de su propiedad.
phone_number Número de teléfono asociado con la cuenta, si está presente.
name Nombre visible del usuario, si se configuró.
sub UID de Firebase del usuario. Es único dentro de un proyecto. Debe ser único dentro de un proyecto.
firebase.identities Diccionario de todas las identidades asociadas con la cuenta del usuario. Las claves del diccionario pueden ser cualquiera de las siguientes: email, phone, google.com, facebook.com, github.com y twitter.com. Los valores del diccionario son arreglos de identificadores únicos para cada proveedor de identidad asociado con la cuenta. Por ejemplo, auth.token.firebase.identities["google.com"][0] contiene el primer ID de usuario de Google asociado a la cuenta.
firebase.sign_in_provider Proveedor de acceso utilizado para obtener este token. Puede ser una de las siguientes strings: custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com.
firebase.tenant El tenantId asociado con la cuenta, si está presente, p. ej., For example, tenant2-m6tyz

Campos adicionales en tokens de ID de JWT

También puedes acceder a los siguientes auth.token campos:

Reclamaciones de tokens personalizados
alg Algoritmo "RS256"
iss Emisor Dirección de correo electrónico de la cuenta de servicio del proyecto
sub Asunto Dirección de correo electrónico de la cuenta de servicio del proyecto
aud Público "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Hora de emisión Hora actual, en segundos transcurridos desde la época UNIX
exp Hora de vencimiento Hora de vencimiento del token, en segundos transcurridos desde la época UNIX Puede ser un máximo de 3,600 segundos más tarde de iat.
Nota: Ten en cuenta que esto solo controla la hora de vencimiento del token personalizado en sí. Sin embargo, cuando haces que un usuario acceda con signInWithCustomToken(), su acceso al dispositivo se mantendrá hasta que esa sesión deje de ser válida o el usuario la cierre.
<claims> (opcional) Reclamaciones personalizadas opcionales para incluir en el token, a las que se puede acceder a través de auth.token (o request.auth.token) en expresiones. Por ejemplo, si creas una reclamación personalizada adminClaim, puedes acceder a ella con auth.token.adminClaim.