במדריך הזה מוסבר על התחביר של 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)")
נתונים שזמינים לביטויים: בקשה, תגובה, this
אתם משתמשים בנתונים כדי:
- הערכה באמצעות ביטויי 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
s ו-_delete
s, הם עשויים להכיל מפתחות 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
מוערך לשדה שאליו מצורף ה-directive @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 |
ביטוי טרנרי | משמאל לימין |
נתונים בטוקנים של אימות
האובייקט 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 |
מזהה הדייר שמשויך לחשבון, אם קיים. לדוגמה, tenant2-m6tyz |
שדות נוספים באסימוני JWT מזהים
אפשר גם לגשת לשדות הבאים של auth.token
:
הצהרות טוקן בהתאמה אישית | ||
---|---|---|
alg |
אלגוריתם | "RS256" |
iss |
הונפק על ידי: | כתובת האימייל של חשבון השירות בפרויקט |
sub |
נושא | כתובת האימייל של חשבון השירות בפרויקט |
aud |
קהל | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
הזמן שבו הונפק האסימון | הזמן הנוכחי, בשניות מאז ראשית זמן יוניקס (Unix epoch) |
exp |
מועד תפוגה |
הזמן שבו יפוג תוקף האסימון, בשניות מאז ראשית זמן יוניקס (Unix epoch). התאריך יכול להיות עד 3,600 שניות אחרי התאריך iat .
הערה: ההגדרה הזו קובעת רק את הזמן שבו יפוג התוקף של האסימון המותאם אישית עצמו. אבל אחרי שמתחברים לחשבון של משתמש באמצעות signInWithCustomToken() , הוא יישאר מחובר למכשיר עד שהסשן שלו יבוטל או עד שהמשתמש יתנתק.
|
ֶ<claims> (אופציונלי) |
טענות אופציונליות בהתאמה אישית שייכללו בטוקן, שאפשר לגשת אליהן דרך auth.token (או request.auth.token ) בביטויים. לדוגמה, אם יוצרים טענה מותאמת אישית
adminClaim , אפשר לגשת אליה באמצעות
auth.token.adminClaim .
|