本参考指南介绍了与为 @auth(expr:)
和 @check(expr:)
指令创建表达式相关的通用表达式语言 (CEL) 语法。
如需查看有关 CEL 的完整参考信息,请参阅 CEL 规范。
在查询和更改中传入的测试变量
借助 @auth(expr)
语法,您可以访问和测试查询和更改中的变量。
例如,您可以使用 vars.status
添加操作变量(例如 $status
)。
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
表达式可用的数据
@auth(expr:)
和 @check(expr:)
CEL 表达式都可以对以下内容进行求值:
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
的别名。
auth 对象包含以下信息:
uid
:分配给请求用户的唯一身份用户 ID。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() 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 |
条件“与” | 从左到右 |
a || b |
条件“或” | 从左到右 |
a ? true_value : false_value |
三元表达式 | 从左到右 |
身份验证令牌中的数据
auth.token
对象可能包含以下值:
字段 | 说明 |
---|---|
email |
与账号关联的电子邮件地址(如果存在)。 |
email_verified |
如果用户已验证他们可以访问 email 地址,则为 true 。某些提供方会自动验证他们拥有的电子邮件地址。 |
phone_number |
与账号关联的电话号码(如果有)。 |
name |
用户的显示名(如果已设置)。 |
sub |
用户的 Firebase UID。此 UID 在项目中是唯一的。 |
firebase.identities |
与此用户账号关联的所有身份的字典。字典的键可以是以下任一值:email 、phone 、google.com 、facebook.com 、github.com 、twitter.com 。字典的值是与账号关联的每个身份提供方的唯一标识符的数组。例如,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 |
与账号关联的租户 ID(如果有)。例如 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 晚最多 3600 秒。
注意:这仅会控制自定义令牌本身的过期时间。但是,一旦您使用 signInWithCustomToken() 让用户登录,他们将一直在设备上保持登录状态,直到其会话失效或用户退出账号为止。 |
<claims> (可选) |
要包含在令牌中的可选自定义声明,可通过表达式中的 auth.token (或 request.auth.token )访问。例如,如果您创建自定义声明 adminClaim ,则可以使用 auth.token.adminClaim 访问它。
|