במדריכים האלה מוסבר על תחביר של 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)")
נתונים שזמינים לביטויים: request, response, this
אתם משתמשים בנתונים כדי:
- הערכה באמצעות ביטויים של CEL בהוראות
@auth(expr:)
ו-@check(expr:)
- הקצאה באמצעות ביטויים של שרת,
<field>_expr
.
גם ביטוי ה-CEL @auth(expr:)
וגם ביטוי ה-CEL @check(expr:)
יכולים להעריך את האפשרויות הבאות:
request.operationName
vars
(כתובת אימייל חלופית ל-request.variables
)auth
(כתובת אימייל חלופית ל-request.auth
)
ב-mutations אפשר לגשת לתוכן של:
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() 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, מספר, מחרוזת, רשימה, מפה, חותמת זמן או משך זמן |
משמאל לימין |
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 .
|