В этом справочном руководстве рассматривается синтаксис 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:)
-  Назначение с использованием выражений сервера, <field>_expr.
 Оба выражения CEL @auth(expr:) и @check(expr:) могут вычислять следующее:
-  request.operationName
-  vars(псевдоним дляrequest.variables)
-  auth(псевдоним дляrequest.auth)
В мутациях вы можете получить доступ и назначить содержимое:
-  response(для проверки частичных результатов в многошаговой логике)
 Кроме того, выражения @check(expr:) могут вычислять:
-  this(значение текущего поля)
-  response(для проверки частичных результатов в многошаговой логике)
Привязка request.operationName
 Привязка request.operarationName хранит тип операции: запрос или мутация.
 Привязка vars (request.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 (request.auth)
Authentication идентифицирует пользователей, запрашивающих доступ к вашим данным, и предоставляет эту информацию в качестве привязки, которую вы можете использовать в своих выражениях.
 В фильтрах и выражениях вы можете использовать auth как псевдоним для request.auth .
Привязка аутентификации содержит следующую информацию:
-  uid: уникальный идентификатор пользователя, назначенный запрашивающему пользователю.
-  token: Карта значений, собранных при Authentication .
 Более подробную информацию о содержимом auth.token см. в разделе Данные в токенах аутентификации.
 Привязка response
 Привязка response содержит данные, собираемые сервером в ответ на запрос или мутацию по мере сборки этих данных .
 По мере выполнения операции, когда каждый шаг завершается успешно, response содержит данные ответа с успешно завершенных шагов.
 Привязка response структурирована в соответствии с формой связанной с ней операции, включая (несколько) вложенных полей и (если применимо) встроенные запросы.
 Обратите внимание, что при доступе к встроенным данным ответа на запрос поля могут содержать любой тип данных в зависимости от данных, запрошенных во встроенном запросе; при доступе к данным, возвращаемым полями мутации, такими как _insert и _delete , они могут содержать ключи UUID, количество удалений, значения NULL (см. справочник по мутациям ).
Например:
-  В мутации, содержащей встроенный запрос, привязка responseсодержит данные поиска вresponse.query.<fieldName>.<fieldName>...., в данном случаеresponse.query.todoListи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
    }
  }
}
-  В многошаговой мутации, например с несколькими полями _insert, привязкаresponseсодержит частичные данные вresponse.<fieldName>.<fieldName>...., в данном случае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,
  })
}
 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, number, string, list, map, timestamp или duration | слева направо | 
| a==ba!=b | Операторы сравнения | слева направо | 
| a && b | Условное И | слева направо | 
| a || b | Условное ИЛИ | слева направо | 
| a ? true_value : false_value | Троичное выражение | слева направо | 
Данные в токенах авторизации
 Объект auth.token может содержать следующие значения:
| Поле | Описание | 
|---|---|
| email | Адрес электронной почты, связанный с учетной записью, если он есть. | 
| email_verified | true, если пользователь подтвердил, что у него есть доступ к адресуemail. Некоторые провайдеры автоматически проверяют принадлежащие им адреса электронной почты. | 
| phone_number | Номер телефона, связанный с учетной записью, если он есть. | 
| name | Отображаемое имя пользователя, если установлено. | 
| sub | Идентификатор пользователя 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 ID
 Вы также можете получить доступ к следующим полям 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. | |