Справочник по синтаксису Common Expression Language для подключения к данным

В этом справочном руководстве рассматривается синтаксис Common Expression Language (CEL), относящийся к созданию выражений для директив @auth(expr:) и @check(expr:) .

Полная справочная информация по CEL представлена ​​в спецификации CEL .

Тестовые переменные, передаваемые в запросах и мутациях

Синтаксис @auth(expr) позволяет получать доступ и проверять переменные из запросов и мутаций.

Например, вы можете включить переменную операции, например $status , используя vars.status .

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

Данные, доступные для выражений

Оба выражения CEL @auth(expr:) и @check(expr:) могут оценивать следующее:

  • request.operationName
  • vars (псевдоним request.variables )
  • auth (псевдоним request.auth )

Кроме того, выражения @check(expr:) могут оценивать:

  • this (значение текущего поля)

Объект request.operationName

Объект request.operarationName хранит тип операции: запрос или мутацию.

Объект vars

Объект vars позволяет вашим выражениям получать доступ ко всем переменным, переданным в вашем запросе или мутации.

Вы можете использовать vars.<variablename> в выражении в качестве псевдонима для полного 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'")

Объект auth

Authentication идентифицирует пользователей, запрашивающих доступ к вашим данным, и предоставляет эту информацию в виде объекта, который вы можете использовать в своих выражениях.

В ваших фильтрах и выражениях вы можете использовать auth в качестве псевдонима для request.auth .

Объект аутентификации содержит следующую информацию:

  • uid : уникальный идентификатор пользователя, назначенный запрашивающему пользователю.
  • token : Карта значений, собранных с помощью Authentication .

Более подробную информацию о содержимом auth.token см. в разделе Данные в токенах аутентификации.

this привязка

Привязка this оценивает поле, к которому прикреплена директива @check . В базовом случае вы можете оценить однозначные результаты запроса.

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

Если возвращаемое поле встречается несколько раз, поскольку любой предок является списком, каждое вхождение проверяется с this к каждому значению.

Для любого заданного пути, если предок имеет значение null или [] , поле не будет достигнуто, и оценка CEL для этого пути будет пропущена. Другими словами, оценка происходит только тогда, когда this значение null или не null , но никогда не undefined .

Если само поле представляет собой список или объект, this имеет ту же структуру (включая всех выбранных потомков в случае объектов), как показано в следующем примере.

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

Синтаксис сложного выражения

Вы можете писать более сложные выражения, комбинируя их с && и || операторы.

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

В следующем разделе описаны все доступные операторы.

Операторы и приоритет операторов

Используйте следующую таблицу в качестве справочника по операторам и их соответствующему приоритету.

Даны произвольные выражения a и b , поле f и индекс i .

Оператор Описание Ассоциативность
a[i] a() af Индекс, вызов, доступ к полям слева направо
!a -a Унарное отрицание справа налево
a/ba%ba*b Мультипликативные операторы слева направо
a+b ab Аддитивные операторы слева направо
a>b a>=b a<b a<=b Реляционные операторы слева направо
a in b Наличие в списке или на карте слева направо
type(a) == t Сравнение типов, где t может быть bool, int, float, числом, строкой, списком, картой, меткой времени или продолжительностью. слева направо
a==ba!=b Операторы сравнения слева направо
a && b Условное И слева направо
a || b Условное ИЛИ слева направо
a ? true_value : false_value Тернарное выражение слева направо

Данные в токенах аутентификации

Объект auth.token может содержать следующие значения:

Поле Описание
email Адрес электронной почты, связанный с учетной записью, если таковой имеется.
email_verified true , если пользователь подтвердил, что у него есть доступ к адресу email . Некоторые провайдеры автоматически проверяют принадлежащие им адреса электронной почты.
phone_number Номер телефона, связанный с учетной записью, если он присутствует.
name Отображаемое имя пользователя, если оно установлено.
sub UID пользователя Firebase. Это уникально в рамках проекта.
firebase.identities Словарь всех идентификаторов, связанных с учетной записью этого пользователя. Ключами словаря могут быть любые из следующих: email , phone , google.com , facebook.com , github.com , twitter.com . Значения словаря представляют собой массивы уникальных идентификаторов для каждого поставщика удостоверений, связанного с учетной записью. Например, auth.token.firebase.identities["google.com"][0] содержит первый идентификатор пользователя Google, связанный с учетной записью.
firebase.sign_in_provider Поставщик входа, использованный для получения этого токена. Может быть одной из следующих строк: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com .
firebase.tenant TenantId, связанный с учетной записью, если он присутствует. Например, tenant2-m6tyz

Дополнительные поля в токенах идентификатора JWT

Вы также можете получить доступ к следующим полям auth.token :

Пользовательские заявки на токены
alg Алгоритм "RS256"
iss Эмитент Адрес электронной почты сервисного аккаунта вашего проекта
sub Предмет Адрес электронной почты сервисного аккаунта вашего проекта
aud Аудитория "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Выдано вовремя Текущее время в секундах с начала эпохи UNIX.
exp Срок годности Время в секундах с начала эпохи UNIX, когда истекает срок действия токена. Это может быть максимум на 3600 секунд позже, чем iat .
Примечание: это контролирует только время истечения срока действия самого пользовательского токена . Но как только вы войдете в систему с помощью signInWithCustomToken() , они останутся в системе до тех пор, пока их сеанс не будет признан недействительным или пользователь не выйдет из системы.
<claims> (необязательно) Необязательные пользовательские утверждения для включения в токен, доступ к которым можно получить через auth.token (или request.auth.token ) в выражениях. Например, если вы создаете пользовательское утверждение adminClaim , вы можете получить к нему доступ с помощью auth.token.adminClaim .