このリファレンス ガイドでは、@auth(expr:) ディレクティブと @check(expr:) ディレクティブの式を作成する際に使用する Common Expression Language(CEL)構文について説明します。
CEL の完全なリファレンス情報は、CEL 仕様で提供されています。
クエリとミューテーションで渡されるテスト変数
@auth(expr) 構文を使用すると、クエリとミューテーションから変数にアクセスしてテストできます。
たとえば、vars.status を使用して、$status などのオペレーション変数を含めることができます。
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
式で使用できるデータ: request、response、this
データは次の目的で使用されます。
@auth(expr:)ディレクティブと@check(expr:)ディレクティブでの CEL 式による評価- サーバー式 
<field>_exprを使用した割り当て。 
@auth(expr:) と @check(expr:) の両方の CEL 式で、次の値を評価できます。
request.operationNamevars(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: リクエストしているユーザーに割り当てられた一意のユーザー ID。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() a.f | 
      インデックス、呼び出し、フィールド アクセス | 左から右 | 
!a -a | 
      単項否定 | 右から左 | 
a/b a%b a*b | 
      乗法演算子 | 左から右 | 
a+b a-b | 
      加法演算子 | 左から右 | 
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==b a!=b | 
      比較演算子 | 左から右 | 
a && b | 
      条件付き AND | 左から右 | 
a || b | 
      条件付き OR | 左から右 | 
a ? true_value : false_value | 
      3 項式 | 左から右 | 
認証トークンのデータ
auth.token オブジェクトには次の値が含まれることがあります。
| フィールド | 説明 | 
|---|---|
email | 
アカウントに関連付けられているメールアドレス(存在する場合)。 | 
email_verified | 
ユーザーに email アドレスへのアクセス権があることが確認された場合は true。一部のプロバイダは、そのプロバイダが所有するメールアドレスを自動的に確認します。 | 
phone_number | 
アカウントに関連付けられている電話番号(存在する場合)。 | 
name | 
ユーザーの表示名(設定されている場合)。 | 
sub | 
ユーザーの Firebase UID。これはプロジェクト内で一意です。 | 
firebase.identities | 
このユーザーのアカウントに関連付けられているすべての ID の辞書。辞書のキーは、email、phone、google.com、facebook.com、github.com、twitter.com のいずれかです。辞書の値は、アカウントに関連付けられている各 ID プロバイダの一意の識別子からなる配列です。たとえば、auth.token.firebase.identities["google.com"][0] にはアカウントに関連付けられている最初の Google ユーザー ID が含まれます。 | 
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 エポック時刻からの秒数)。iat から最大 3,600 秒後の時間を設定できます。注: これは、カスタム トークン自体の有効期限が切れる時間のみを制御できます。ただし、 signInWithCustomToken() を使用してユーザーにログインさせた後は、セッションが無効になるかユーザーがログアウトするまで、デバイスにログインしたままになります。 | 
  
<claims>(オプション) | 
    
      トークンに含めるオプションのカスタム クレーム。式内の auth.token(または request.auth.token)からアクセスできます。たとえば、カスタム クレーム adminClaim を作成した場合、auth.token.adminClaim を使用してアクセスできます。 | 
  |