Firebase Data Connect מספק אבטחה איתנה בצד הלקוח באמצעות:
- הרשאה ללקוחות בנייד ובאינטרנט
- אמצעי בקרה ספציפיים ברמת השאילתה וברמת המוטציה
- אימות אפליקציות באמצעות Firebase App Check.
Data Connect מרחיב את האבטחה הזו באמצעות:
- הרשאה בצד השרת
- אבטחת משתמשים בפרויקט Firebase וב-Cloud SQL באמצעות IAM.
מתן הרשאה לשאילתות ולמוטציות של לקוחות
Data Connect משולב באופן מלא עם Firebase Authentication, כך שתוכלו להשתמש בנתונים עשירים על משתמשים שמקבלים גישה לנתונים שלכם (אימות) בתכנון של הנתונים שהמשתמשים האלה יכולים לגשת אליהם (הרשאה).
Data Connect מספק הוראה @auth
לשאילתות ולמוטציות שמאפשרת להגדיר את רמת האימות הנדרשת כדי לאשר את הפעולה. במדריך הזה נתאר את ההנחיה @auth
עם דוגמאות.
בנוסף, Data Connect תומך בהרצה של שאילתות שמוטמעות במוטציות, כך שתוכלו לאחזר קריטריונים נוספים להרשאה ששמרתם במסד הנתונים, ולהשתמש בקריטריונים האלה בהוראות @check
כדי להחליט אם יש הרשאה למוטציות המצורפות. במקרה הזה של הרשאה, ההנחיה @redact
מאפשרת לכם לקבוע אם תוצאות השאילתה יחזרו ללקוחות בפרוטוקול הנתונים, והאם השאילתה המוטמעת תושמט מערכות ה-SDK שנוצרו. מבוא להנחיות האלה, עם דוגמאות
הסבר על ההנחיה @auth
אפשר להגדיר פרמטרים להנחיה @auth
כך שתתאים לאחת מכמה רמות גישה מוגדרות מראש, שמכסות תרחישים גישה נפוצים רבים. הרמות האלה נעות בין PUBLIC
(שמאפשרת שאילתות ומוטציות מכל הלקוחות ללא אימות מכל סוג שהוא) לבין NO_ACCESS
(שמגבילה שאילתות ומוטציות מחוץ לסביבות שרת בעלות הרשאות באמצעות Firebase Admin SDK). כל אחת מהרמות האלה קשורה לתהליכי אימות שמספק Firebase Authentication.
רמה | הגדרה |
---|---|
PUBLIC |
כל אחד יכול לבצע את הפעולה, עם או בלי אימות. |
PUBLIC |
כל אחד יכול לבצע את הפעולה, עם או בלי אימות. |
USER_ANON |
כל משתמש מזוהה, כולל משתמשים שנכנסו לחשבון באופן אנונימי באמצעות Firebase Authentication, מורשה לבצע את השאילתה או את המוטציה. |
USER |
כל משתמש שנכנס באמצעות Firebase Authentication מורשה לבצע את השאילתה או את המוטציה, מלבד משתמשים לא רשומים שנכנסו לחשבון. |
USER_EMAIL_VERIFIED |
כל משתמש שנכנס לחשבון באמצעות Firebase Authentication עם כתובת אימייל מאומתת מורשה לבצע את השאילתה או את המוטציה. |
NO_ACCESS |
לא ניתן לבצע את הפעולה הזו מחוץ להקשר של Admin SDK. |
רמות הגישה המוגדרות מראש האלה משמשות כנקודת מוצא להגדרת בדיקות הרשאה מורכבות וחזקות בהוראה @auth
באמצעות מסנני where
וביטויים של Common Expression Language (CEL) שמתבצעת להם הערכה בשרת.
שימוש בהנחיה @auth
להטמעת תרחישים נפוצים של הרשאות
רמות הגישה המוגדרות מראש הן נקודת ההתחלה של ההרשאה.
רמת הגישה USER
היא הרמה הבסיסית הכי שימושית להתחלה.
גישה מאובטחת לחלוטין תתבסס על רמה USER
, בתוספת מסננים וביטויים לבדיקת מאפייני משתמשים, מאפייני משאבים, תפקידים ובדיקות אחרות. הרמות USER_ANON
ו-USER_EMAIL_VERIFIED
הן וריאציות של המקרה USER
.
תחביר הביטויים מאפשר להעריך נתונים באמצעות אובייקט auth
שמייצג נתוני אימות שמועברים עם פעולות, גם נתונים רגילים באסימוני אימות וגם נתונים מותאמים אישית באסימונים. רשימת השדות שזמינים באובייקט auth
מפורטת בקטע העזרה.
כמובן שיש תרחישים לדוגמה שבהם PUBLIC
היא רמת הגישה הנכונה להתחלה. שוב, רמת הגישה היא תמיד נקודת ההתחלה, ונדרשים מסננים וביטויים נוספים כדי לשמור על אבטחה חזקה.
במדריך הזה מפורטות עכשיו דוגמאות לפיתוח ב-USER
וב-PUBLIC
.
דוגמה מעוררת השראה
הדוגמאות הבאות לשיטות מומלצות מתייחסות לסכימה הבאה של פלטפורמת בלוגים שבה תוכן מסוים נעול מאחורי תוכנית תשלומים.
סביר להניח שפלטפורמה כזו תיצור מודלים של Users
ושל Posts
.
type User @table(key: "uid") {
uid: String!
name: String
birthday: Date
createdAt: Timestamp! @default(expr: "request.time")
}
type Post @table {
author: User!
text: String!
# "one of 'draft', 'public', or 'pro'"
visibility: String! @default(value: "draft")
# "the time at which the post should be considered published. defaults to
# immediately"
publishedAt: Timestamp! @default(expr: "request.time")
createdAt: Timestamp! @default(expr: "request.time")
updatedAt: Timestamp! @default(expr: "request.time")
}
משאבים בבעלות המשתמש
מומלץ לכתוב ב-Firebase מסננים וביטויים שבודקים את הבעלות של משתמש על משאב, במקרים הבאים, הבעלות על Posts
.
בדוגמאות הבאות, נתונים מאסימוני אימות נקרא ומשווים באמצעות ביטויים. התבנית הרגילה היא להשתמש בביטויים כמו where: {authorUid:
{eq_expr: "auth.uid"}}
כדי להשוות בין authorUid
ששמור לבין auth.uid
(מזהה המשתמש) שהוענק באסימון האימות.
יצירה
כדי להשתמש בשיטת האימות הזו, צריך להוסיף את הערך auth.uid
מאסימון האימות לכל Post
חדש בתור שדה authorUid
, כדי לאפשר השוואה בבדיקות האימות הבאות.
# Create a new post as the current user
mutation CreatePost($text: String!, $visibility: String) @auth(level: USER) {
post_insert(data: {
# set the author's uid to the current user uid
authorUid_expr: "auth.uid"
text: $text
visibility: $visibility
})
}
עדכון
כשלקוח מנסה לעדכן Post
, אפשר לבדוק את auth.uid
שהועברו מול authorUid
ששמור.
# Update one of the current user's posts
mutation UpdatePost($id: UUID!, $text: String, $visibility: String) @auth(level:USER) {
post_update(
# only update posts whose author is the current user
first: { where: {
id: {eq: $id}
authorUid: {eq_expr: "auth.uid"}
}}
data: {
text: $text
visibility: $visibility
# insert the current server time for updatedAt
updatedAt_expr: "request.time"
}
)
}
מחיקה
אותה טכניקה משמשת לאישור פעולות מחיקה.
# Delete one of the current user's posts
mutation DeletePost($id: UUID!) @auth(level: USER) {
post_delete(
# only delete posts whose author is the current user
first: { where: {
id: {eq: $id}
authorUid: {eq_expr: "auth.uid"}
}}
)
}
# Common display information for a post
fragment DisplayPost on Post {
id, text, createdAt, updatedAt
author { uid, name }
}
רשימה
# List all posts belonging to the current user
query ListMyPosts @auth(level: USER) {
posts(where: {
userUid: {eq_expr: "auth.uid"}
}) {
# See the fragment above
...DisplayPost
# also show visibility since it is user-controlled
visibility
}
}
קבל
# Get a post only if it belongs to the current user
query GetMyPost($id: UUID!) @auth(level: USER) {
post(key: {id: $id},
first: {where: {
id: {eq: $id}
authorUid: {eq_expr: "auth.uid"}}
}}, {
# See the fragment above
...DisplayPost
# also show visibility since it is user-controlled
visibility
}
}
סינון הנתונים
מערכת ההרשאות של Data Connect מאפשרת לכתוב מסננים מתוחכמים בשילוב עם רמות גישה מוגדרות מראש כמו PUBLIC
, וגם באמצעות נתונים מאסימוני אימות.
מערכת ההרשאות מאפשרת גם להשתמש בביטויים בלבד, בלי רמת גישה בסיסית, כפי שמוצג בחלק מהדוגמאות הבאות.
סינון לפי מאפייני המשאבים
כאן, ההרשאה לא מבוססת על אסימוני אימות כי רמת האבטחה הבסיסית מוגדרת ל-PUBLIC
. עם זאת, אנחנו יכולים להגדיר באופן מפורש רשומות במסד הנתונים שלנו כמתאימות לגישה ציבורית. נניח שיש לנו Post
רשומות במסד הנתונים עם הערך visibility
שמוגדר כ'ציבורי'.
# List all posts marked as 'public' visibility
query ListPublicPosts @auth(level: PUBLIC) {
posts(where: {
# Test that visibility is "public"
visibility: {eq: "public"}
# Only display articles that are already published
publishedAt: {lt_expr: "request.time"}
}) {
# see the fragment above
...DisplayPost
}
}
סינון לפי הצהרות של משתמשים
כאן נניח שהגדרתם הצהרות משתמש בהתאמה אישית שמעבירות אסימוני אימות כדי לזהות משתמשים בתוכנית 'פרו' באפליקציה, שמסומנים בשדה auth.token.plan
באסימון האימות. הביטויים שלכם יכולים לבדוק את השדה הזה.
# List all public or pro posts, only permitted if user has "pro" plan claim
query ProListPosts @auth(expr: "auth.token.plan == 'pro'") {
posts(where: {
# display both public posts and "pro" posts
visibility: {in: ['public', 'pro']},
# only display articles that are already published
publishedAt: {lt_expr: "request.time"},
}) {
# see the fragment above
...DisplayPost
# show visibility so pro users can see which posts are pro\
visibility
}
}
סינון לפי סדר + מגבלה
לחלופין, יכול להיות שהגדרתם את השדה visibility
ברשאות Post
כדי לזהות שהן מכילות תוכן שזמין למשתמשים 'פרו', אבל כדי להציג תצוגה מקדימה או טיזר של הנתונים, תוכלו להגביל עוד יותר את מספר הרשומות שיוחזרו.
# Show 2 oldest Pro post as a preview
query ProTeaser @auth(level: USER) {
posts(
where: {
# show only pro posts
visibility: {eq: "pro"}
# that have already been published more than 30 days ago
publishedAt: {lt_time: {now: true, sub: {days: 30}}}
},
# order by publish time
orderBy: [{publishedAt: DESC}],
# only return two posts
limit: 2
) {
# See the fragment above
...DisplayPost
}
}
סינון לפי תפקיד
אם הצהרת ה-Claim בהתאמה אישית מגדירה תפקיד admin
, תוכלו לבדוק ולתת הרשאה לפעולות בהתאם.
# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
posts { ...DisplayPost }
}
הסבר על ההנחיות @check
ו-@redact
ההנחיה @check
מאמתת ששדות מסוימים נמצאים בתוצאות של השאילתה. ביטוי של Common Expression Language (CEL) משמש לבדיקה של ערכי השדות. ברירת המחדל של ההנחיה היא לבדוק אם יש צמתים עם ערך null
ולדחות אותם.
ההנחיה @redact
מסננת חלק מהתשובה מהלקוח. עדיין מתבצעת הערכה של שדות שחוסמים את המידע כדי לזהות השפעות לוואי (כולל שינויים בנתונים ו-@check
), והתוצאות עדיין זמינות לשלבים מאוחרים יותר בביטויים של CEL.
ב-Data Connect, ההנחיות @check
ו-@redact
משמשות בדרך כלל בהקשר של בדיקות הרשאה. אפשר לעיין בדיון לגבי חיפוש של נתוני הרשאה.
הוספת ההנחיות @check
ו-@redact
לחיפוש נתוני הרשאה
תרחיש לדוגמה של הרשאה נפוץ כולל אחסון של תפקידים בהתאמה אישית במסד הנתונים, למשל בטבלת הרשאות מיוחדת, ושימוש בתפקידים האלה כדי לאשר מוטציות ליצירה, לעדכון או למחיקה של נתונים.
באמצעות חיפושים של נתוני הרשאה, אפשר לשלוח שאילתות לגבי תפקידים על סמך מזהה משתמש ולהשתמש בביטויים של CEL כדי להחליט אם המוטציה מורשית. לדוגמה, יכול להיות שתרצו לכתוב מוטציה של UpdateMovieTitle
שמאפשרת ללקוח מורשה לעדכן שמות של סרטים.
בהמשך הסקירה נניח שמסד הנתונים של אפליקציית ביקורות הסרטים מאחסן תפקיד הרשאה בטבלה MoviePermission
.
# MoviePermission
# Suppose a user has an authorization role with respect to records in the Movie table
type MoviePermission @table(key: ["doc", "userId"]) {
movie: Movie! # implies another field: movieId: UUID!
userId: String! # Can also be a reference to a User table, doesn't matter
role: String!
}
בהטמעה לדוגמה הבאה, המוטציה UpdateMovieTitle
כוללת את השדה query
כדי לאחזר נתונים מ-MoviePermission
, ואת ההוראות הבאות כדי להבטיח שהפעולה מאובטחת וחזקה:
- הוראה
@transaction
כדי לוודא שכל השאילתות והבדיקות של ההרשאה יושלמו או יכשלו באופן אטומי. - ההנחיה
@redact
להשמטת תוצאות השאילתה מהתגובה, כלומר בדיקת ההרשאה מתבצעת בשרת Data Connect אבל מידע אישי רגיש לא נחשף ללקוח. שתי הנחיות
@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"}
# Step 1a: Use @check to test if the user has any role associated with the movie
# Here the `this` binding refers the lookup result, i.e. a MoviePermission object or null
# The `this != null` expression could be omitted since rejecting on null is default behavior
) @check(expr: "this != null", message: "You do not have access to this movie") {
# Step 1b: Check if the user has the editor role for the movie
# Next we execute another @check; now `this` refers to the contents of the `role` field
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
})
}
דפוסים שליליים שכדאי להימנע מהם בנוגע להרשאות
בקטע הקודם מוסבר על דפוסים שכדאי לפעול לפיהם כשמשתמשים בהנחיה @auth
.
חשוב גם להכיר דפוסים שליליים חשובים שצריך להימנע מהם.
הימנעות מעברת מזהי מאפייני משתמשים ופרמטרים של אסימוני אימות בארגומנטים של שאילתות ושל טרנספורמציות
Firebase Authentication הוא כלי רב-עוצמה להצגת תהליכי אימות ולתיעוד מאובטח של נתוני אימות, כמו מזהי משתמשים רשומים ומספר שדות שמאוחסנים באסימוני אימות.
לא מומלץ להעביר מזהי משתמשים ונתוני אסימוני אימות בארגומנטים של שאילתות ושל טרנספורמציות.
# Antipattern!
# This incorrectly allows any user to view any other user's posts
query AllMyPosts($userId: String!) @auth(level: USER) {
posts(where: {authorUid: {eq: $userId}}) {
id, text, createdAt
}
}
הימנעות משימוש ברמת הגישה USER
ללא מסננים
כפי שצוין כמה פעמים במדריך, רמות הגישה הבסיסיות כמו USER
, USER_ANON
ו-USER_EMAIL_VERIFIED
הן נקודות התחלה ורמות בסיס לבדיקות ההרשאה, שאפשר לשפר באמצעות מסננים וביטויים. שימוש ברמות האלה ללא מסנן או ביטוי תואם שבודק איזה משתמש מבצע את הבקשה, שווה ערך לשימוש ברמה PUBLIC
.
# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
documents {
id
title
text
}
}
אין להשתמש ברמת הגישה PUBLIC
או USER
ליצירת אב טיפוס
כדי לזרז את הפיתוח, יכול להיות שתתפתו להגדיר את כל הפעולות לרמת הגישה PUBLIC
או לרמת הגישה USER
בלי שיפורים נוספים כדי לאשר את כל הפעולות ולאפשר לכם לבדוק את הקוד במהירות.
אחרי שתיצרו אב טיפוס ראשוני מאוד בדרך הזו, תוכלו להתחיל לעבור מ-NO_ACCESS
לאישור מוכן לייצור באמצעות רמות PUBLIC
ו-USER
.
עם זאת, אל תפרסו אותם בתור PUBLIC
או USER
בלי להוסיף לוגיקה נוספת כפי שמתואר במדריך הזה.
# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
post: post_delete(
id: $id,
)
}
שימוש ב-Firebase App Check לאימות אפליקציות
אימות והרשאה הם רכיבים קריטיים באבטחה של Data Connect. אימות והרשאה בשילוב עם אימות אפליקציות יוצרים פתרון אבטחה חזק מאוד.
באמצעות אימות באמצעות Firebase App Check, במכשירים שבהם פועלת האפליקציה שלכם ישתמש ספק אימות של אפליקציה או מכשיר, שמאמת שהפעולות של Data Connect מגיעות מהאפליקציה המקורית והבקשות מגיעות ממכשיר מקורי שלא בוצע בו שינוי. האימות הזה מצורף לכל בקשה שהאפליקציה שולחת אל Data Connect.
בסקירה הכללית על App Check מוסבר איך מפעילים את App Check ב-Data Connect ומוסיפים את ה-SDK של הלקוח לאפליקציה.
רמות האימות להנחיה @auth(level)
בטבלה הבאה מפורטות כל רמות הגישה הרגילות והמקבילות שלהן ב-CEL. רמות האימות מפורטות מהרחבה לצרה – כל רמה כוללת את כל המשתמשים שתואמים לרמות הבאות.
רמה | הגדרה |
---|---|
PUBLIC |
כל אחד יכול לבצע את הפעולה, עם או בלי אימות.
שיקולים: כל משתמש יכול לקרוא או לשנות את הנתונים. Firebase ממליצה על רמת ההרשאה הזו לנתונים שגלויים לכולם, כמו כרטיסי מוצר או מדיה. דוגמאות ושיטות מומלצות לחלופות זהה ל- @auth(expr: "true")
לא ניתן להשתמש במסננים ובביטויים של @auth בשילוב עם רמת הגישה הזו. כל ביטוי כזה ייכשל עם שגיאת 400 בקשה שגויה.
|
USER_ANON |
כל משתמש מזוהה, כולל משתמשים שנכנסו לחשבון באופן אנונימי באמצעות Firebase Authentication, מורשה לבצע את השאילתה או את המוטציה.
הערה: USER_ANON הוא קבוצה רחבה יותר מ-USER .
הערות: חשוב לזכור שצריך לתכנן בקפידה את השאילתות והמוטציות ברמת ההרשאה הזו. ברמה הזו, המשתמשים יכולים להתחבר אנונימית (כניסה אוטומטית שמקושרת רק למכשיר של המשתמש) באמצעות Authentication, והיא לא מבצעת בעצמה בדיקות נוספות, למשל אם הנתונים שייכים למשתמש. דוגמאות ושיטות מומלצות לחלופות מכיוון ש תהליכי התחברות אנונימיים מנפיקים uid , הרמה USER_ANON זהה ל-@auth(expr: "auth.uid != nil") Authentication
|
USER |
כל משתמש שנכנס באמצעות Firebase Authentication מורשה לבצע את השאילתה או את המוטציה, מלבד משתמשים לא רשומים שנכנסו לחשבון.
הערות: חשוב לזכור שצריך לתכנן בקפידה את השאילתות והמוטציות ברמת ההרשאה הזו. ברמה הזו מתבצעת רק בדיקה שהמשתמש מחובר באמצעות Authentication, והיא לא מבצעת בעצמה בדיקות אחרות, למשל אם הנתונים שייכים למשתמש. דוגמאות ושיטות מומלצות לחלופות שווה ערך ל- @auth(expr: "auth.uid != nil &&
auth.token.firebase.sign_in_provider != 'anonymous'")"
|
USER_EMAIL_VERIFIED |
כל משתמש שנכנס לחשבון באמצעות Firebase Authentication עם כתובת אימייל מאומתת מורשה לבצע את השאילתה או את המוטציה.
שיקולים: מאחר שביצוע האימות באימייל מתבצע באמצעות Authentication, הוא מבוסס על שיטת Authentication חזקה יותר, ולכן רמה זו מספקת אבטחה נוספת בהשוואה ל- USER או ל-USER_ANON . ברמה הזו מתבצעת רק בדיקה שהמשתמש מחובר ל-Authentication באמצעות כתובת אימייל מאומתת, והיא לא מבצעת בעצמה בדיקות נוספות, למשל אם הנתונים שייכים למשתמש. דוגמאות ושיטות מומלצות לחלופות
שווה ערך ל- @auth(expr: "auth.uid != nil &&
auth.token.email_verified")" |
NO_ACCESS |
לא ניתן לבצע את הפעולה הזו מחוץ להקשר של Admin SDK.
שווה ערך ל- @auth(expr: "false") |
הפניה ל-CEL עבור @auth(expr)
ו-@check(expr)
כפי שמוצג בדוגמאות במקומות אחרים במדריך הזה, אפשר להשתמש בביטויים שהוגדרו ב-Common Expression Language (CEL) כדי לשלוט בהרשאה ל-Data Connect באמצעות ההוראות @auth(expr:)
ו-@check
.
בקטע הזה נסביר על תחביר CEL שרלוונטי ליצירת ביטויים להנחיות האלה.
מידע מפורט על CEL זמין במפרט של CEL.
בדיקת משתנים שמועברים בשאילתות ובמוטציות
התחביר של @auth(expr)
מאפשר לגשת למשתנים משאילתות וממוטציות ולבדוק אותם.
לדוגמה, אפשר לכלול משתנה פעולה, כמו $status
, באמצעות vars.status
.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
נתונים שזמינים לביטויים
גם ביטוי ה-CEL @auth(expr:)
וגם ביטוי ה-CEL @check(expr:)
יכולים להעריך את האפשרויות הבאות:
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
.
אובייקט האימות מכיל את הפרטים הבאים:
uid
: מזהה משתמש ייחודי שהוקצה למשתמש מבצע הבקשה.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, מספר, מחרוזת, רשימה, מפה, חותמת זמן או משך זמן |
משמאל לימין |
a==b a!=b |
אופרטורים להשוואה | משמאל לימין |
a && b |
AND מותנה | משמאל לימין |
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 |
מזהה הדייר שמשויך לחשבון, אם הוא קיים. לדוגמה, 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 .
|
מה השלב הבא?
- Firebase Data Connect מספק Admin SDK שמאפשר לבצע שאילתות ומוטציות בסביבות בעלות הרשאות.
- מידע נוסף על אבטחת IAM זמין במדריך לניהול שירותים ומסדי נתונים.