مرجع بنية لغة التعبير الشائعة لخدمة Data Connect

تتضمّن أدلة المراجع هذه بنية لغة التعبير الشائعة (CEL) ذات الصلة بإنشاء تعبيرات لتوجيهَي @auth(expr:) و@check(expr:).

تتوفّر معلومات مرجعية كاملة حول CEL في مواصفات CEL.

اختبار المتغيّرات التي تم تمريرها في الاستعلامات وعمليات التعديل

تتيح لك بنية @auth(expr) الوصول إلى المتغيرات واختبارها من الاستعلامات وعمليات التعديل.

على سبيل المثال، يمكنك تضمين متغيّر عملية، مثل $status، باستخدام vars.status.

mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")

البيانات المتاحة للتعبيرات: الطلب والاستجابة و"هذا"

يمكنك استخدام البيانات في ما يلي:

  • التقييم باستخدام تعابير 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 و_delete، قد تحتوي على مفاتيح UUID وعدد عمليات الحذف والقيم الخالية (راجِع مرجع عمليات التعديل).

على سبيل المثال:

  • في عملية تغيير تتضمّن طلب بحث مضمّنًا، يحتوي الربط على بيانات البحث في response.query.<fieldName>.<fieldName>....، وفي هذه الحالة، response.query.todoList وresponse.query.todoList.priority.response
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 قيمة منطقية أو عددًا صحيحًا أو عددًا عشريًا أو رقمًا أو سلسلة أو قائمة أو خريطة أو طابعًا زمنيًا أو مدة من اليسار إلى اليمين
a==b a!=b عوامل تشغيل المقارنة من اليسار إلى اليمين
a && b Conditional AND من اليسار إلى اليمين
a || b Conditional OR من اليسار إلى اليمين
a ? true_value : false_value التعبير الثلاثي من اليسار إلى اليمين

البيانات في رموز المصادقة

قد يحتوي الكائن 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 تمثّل هذه السمة رقم تعريف المستأجر المرتبط بالحساب، إذا كان متوفرًا. على سبيل المثال، tenant2-m6tyz

حقول إضافية في رموز JWT المميّزة الخاصة بمعرّف المستخدم

يمكنك أيضًا الوصول إلى حقول auth.token التالية:

مطالبات الرموز المميّزة المخصّصة
alg خوارزمية "RS256"
iss جهة الإصدار عنوان البريد الإلكتروني لحساب الخدمة في مشروعك
sub الموضوع عنوان البريد الإلكتروني لحساب الخدمة في مشروعك
aud الجمهور "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat وقت الإصدار الوقت الحالي، بالثواني منذ بدء حساب الفترة في نظام التشغيل UNIX
exp وقت انتهاء الصلاحية الوقت الذي تنتهي فيه صلاحية الرمز المميّز، بالثواني منذ بدء حساب الفترة في نظام التشغيل UNIX يمكن أن يكون بعد 3600 ثانية كحدّ أقصى من iat.
ملاحظة: يتحكّم هذا الإعداد فقط في وقت انتهاء صلاحية الرمز المميّز المخصّص نفسه. ولكن بعد تسجيل دخول المستخدم باستخدام signInWithCustomToken()، سيظل مسجّلاً الدخول إلى الجهاز إلى أن تصبح جلسته غير صالحة أو يسجّل المستخدم خروجه.
<claims> (اختياري) مطالبات مخصّصة اختيارية لتضمينها في الرمز المميز، ويمكن الوصول إليها من خلال auth.token (أو request.auth.token) في التعبيرات. على سبيل المثال، إذا أنشأت مطالبة مخصّصة adminClaim، يمكنك الوصول إليها باستخدام auth.token.adminClaim.