การอ้างอิงไวยากรณ์ Common Expression Language สำหรับ SQL Connect

คู่มืออ้างอิงนี้ครอบคลุมไวยากรณ์ Common Expression Language (CEL) ที่เกี่ยวข้องกับการสร้างนิพจน์สำหรับคำสั่ง @auth(expr:), @check(expr:) และ @refresh(onMutationExecuted:)

ดูข้อมูลอ้างอิงทั้งหมดสำหรับ 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:), @check(expr:), @refresh(onMutationExecuted:) สามารถประเมินสิ่งต่อไปนี้ได้

  • request.operationName
  • vars (ชื่อแทนของ request.variables)
  • auth (ชื่อแทนของ request.auth)

ในการกลายพันธุ์ คุณสามารถเข้าถึงและกำหนดเนื้อหาของสิ่งต่อไปนี้ได้

  • response (เพื่อตรวจสอบผลลัพธ์บางส่วนในตรรกะแบบหลายขั้นตอน)

นอกจากนี้ นิพจน์ @check(expr:) ยังประเมินสิ่งต่อไปนี้ได้ด้วย

  • this (ค่าของช่องปัจจุบัน)
  • response (เพื่อตรวจสอบผลลัพธ์บางส่วนในตรรกะแบบหลายขั้นตอน)

และนิพจน์ @refresh(onMutationExecuted:) มีการเชื่อมโยงต่อไปนี้

  • mutation.variables
  • mutation.auth

การเชื่อมโยง 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 อาจเป็นบูลีน, int, float, ตัวเลข, สตริง, รายการ, แผนที่, การประทับเวลา หรือระยะเวลา ซ้ายไปขวา
a==b a!=b โอเปอเรเตอร์การเปรียบเทียบ ซ้ายไปขวา
a && b AND แบบมีเงื่อนไข ซ้ายไปขวา
a || b OR แบบมีเงื่อนไข ซ้ายไปขวา
a ? true_value : false_value นิพจน์แบบ Ternary ซ้ายไปขวา

ข้อมูลในโทเค็นการตรวจสอบสิทธิ์

ออบเจ็กต์ auth.token อาจมีค่าต่อไปนี้

ช่อง คำอธิบาย
email อีเมลที่เชื่อมโยงกับบัญชี (หากมี)
email_verified true หากผู้ใช้ยืนยันแล้วว่ามีสิทธิ์เข้าถึงอีเมล email ผู้ให้บริการบางรายจะยืนยันอีเมลที่ตนเป็นเจ้าของโดยอัตโนมัติ
phone_number หมายเลขโทรศัพท์ที่เชื่อมโยงกับบัญชี (หากมี)
name ชื่อที่แสดงของผู้ใช้ หากตั้งค่าไว้
sub UID ของ 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 tenantId ที่เชื่อมโยงกับบัญชี (หากมี) เช่น 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