درس تطبيقي حول ترميز الويب في Cloud Firestore

1. نظرة عامة

الأهداف

في هذا الدرس التطبيقي حول الترميز، ستُنشئ تطبيق ويب لاقتراح المطاعم باستخدام Cloud Firestore.

img5.png

ما ستتعرّف عليه

  • قراءة البيانات وكتابتها في Cloud Firestore من تطبيق ويب
  • الاستماع إلى التغييرات في بيانات Cloud Firestore في الوقت الفعلي
  • استخدام قواعد أمان ومصادقة Firebase لتأمين بيانات Cloud Firestore
  • كتابة طلبات بحث معقّدة في Cloud Firestore

المتطلبات

قبل بدء هذا الدليل التعليمي حول الرموز البرمجية، تأكَّد من تثبيت ما يلي:

  • npm الذي يأتي عادةً مع Node.js - يُنصح باستخدام الإصدار 16 من Node أو الإصدارات الأحدث
  • بيئة تطوير البرامج (IDE) أو محرِّر النصوص المفضّل لديك، مثل WebStorm أو VS Code أو Sublime

2- إنشاء مشروع على Firebase وإعداده

إنشاء مشروع على Firebase

  1. في وحدة تحكّم Firebase، انقر على إضافة مشروع، ثمّ أدخِل اسم "FriendlyEats" لمشروع Firebase.

تذكَّر رقم تعريف مشروعك على Firebase.

  1. انقر على إنشاء مشروع.

يستخدم التطبيق الذي سننشئه بعض خدمات Firebase المتاحة على الويب:

  • Firebase Authentication لتحديد هوية المستخدمين بسهولة
  • Cloud Firestore لحفظ البيانات المنظَّمة على السحابة الإلكترونية والحصول على إشعار فوري عند تعديل البيانات
  • استضافة Firebase لاستضافة مواد العرض الثابتة وعرضها

بالنسبة إلى هذا الدليل التعليمي المحدّد، سبق أن أعددنا خدمة Firebase Hosting. بالنسبة إلى Firebase Auth وCloud Firestore، سنرشدك خلال عملية ضبط الإعدادات وتفعيل الخدمات باستخدام "وحدة تحكّم Firebase".

تفعيل المصادقة المجهولة

على الرغم من أنّ المصادقة ليست محور هذا الدليل التعليمي حول رموز البرامج، من المهم توفير شكل من أشكال المصادقة في تطبيقنا. سنستخدم تسجيل الدخول بدون إظهار الهوية، ما يعني أنّه سيتم تسجيل دخول المستخدم بدون أن يُطلب منه ذلك.

عليك تفعيل تسجيل الدخول بدون إظهار الهوية.

  1. في وحدة تحكُّم Firebase، ابحث عن قسم الإصدار في شريط التنقّل الأيمن.
  2. انقر على المصادقة، ثم انقر على علامة التبويب طريقة تسجيل الدخول (أو انقر على هذا الرابط للانتقال إليها مباشرةً).
  3. فعِّل موفِّر تسجيل الدخول غير المعروف، ثم انقر على حفظ.

img7.png

سيسمح ذلك للتطبيق بتسجيل دخول المستخدمين بصمت عند وصولهم إلى تطبيق الويب. يمكنك الاطّلاع على مستندات المصادقة المجهولة الهوية لمعرفة المزيد من المعلومات.

تفعيل Cloud Firestore

يستخدم التطبيق Cloud Firestore لحفظ معلومات المطاعم وتقييماتها وتلقّيها.

ستحتاج إلى تفعيل Cloud Firestore. في قسم الإنشاء في وحدة تحكُّم Firebase، انقر على قاعدة بيانات Firestore. انقر على إنشاء قاعدة بيانات في لوحة Cloud Firestore.

يتم التحكّم في الوصول إلى البيانات في Cloud Firestore من خلال قواعد الأمان. سنتحدث أكثر عن القواعد لاحقًا في هذا الدليل التعليمي، ولكن علينا أولاً ضبط بعض القواعد الأساسية على بياناتنا للبدء. في علامة التبويب "القواعد" في وحدة تحكّم Firebase، أضِف القواعد التالية، ثم انقر على نشر.

rules_version = '2';
service cloud.firestore {

  // Determine if the value of the field "key" is the same
  // before and after the request.
  function unchanged(key) {
    return (key in resource.data)
      && (key in request.resource.data)
      && (resource.data[key] == request.resource.data[key]);
  }

  match /databases/{database}/documents {
    // Restaurants:
    //   - Authenticated user can read
    //   - Authenticated user can create/update (for demo purposes only)
    //   - Updates are allowed if no fields are added and name is unchanged
    //   - Deletes are not allowed (default)
    match /restaurants/{restaurantId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null;
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys())
                    && unchanged("name");

      // Ratings:
      //   - Authenticated user can read
      //   - Authenticated user can create if userId matches
      //   - Deletes and updates are not allowed (default)
      match /ratings/{ratingId} {
        allow read: if request.auth != null;
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;
      }
    }
  }
}

سنناقش هذه القواعد وطريقة عملها لاحقًا في ورشة رموز البرامج.

3- الحصول على رمز النموذج

استنسِخ مستودع GitHub من سطر الأوامر:

git clone https://github.com/firebase/friendlyeats-web

من المفترض أن يكون قد تم استنساخ نموذج الرمز البرمجي في الدليل 📁friendlyeats-web. من الآن فصاعدًا، احرص على تنفيذ جميع طلباتك من هذا الدليل:

cd friendlyeats-web/vanilla-js

استيراد التطبيق المُنشئ

باستخدام بيئة تطوير البرامج المتكاملة (WebStorm أو Atom أو Sublime أو Visual Studio Code أو غيرها)، افتح الدليل 📁friendlyeats-web أو استورِده. يحتوي هذا الدليل على الرمز البرمجي الأوّلي لجلسة التعلّم بالبرمجة التي تتألف من تطبيق اقتراحات المطاعم غير الوظيفي بعد. سنجعله وظيفيًا خلال جلسة التعلّم بالبرمجة هذه، لذا عليك تعديل الرمز البرمجي في هذا الدليل قريبًا.

4. تثبيت واجهة سطر أوامر Firebase

تتيح لك واجهة سطر الأوامر في Firebase (CLI) عرض تطبيق الويب محليًا ونشره على "استضافة Firebase".

  1. ثبِّت واجهة سطر الأوامر من خلال تنفيذ الأمر npm التالي:
npm -g install firebase-tools
  1. تأكَّد من تثبيت واجهة برمجة التطبيقات بشكلٍ صحيح من خلال تنفيذ الأمر التالي:
firebase --version

تأكَّد من أنّ إصدار Firebase CLI هو 7.4.0 أو إصدار أحدث.

  1. فوِّض Firebase CLI من خلال تنفيذ الأمر التالي:
firebase login

لقد أعددنا نموذج تطبيق الويب لسحب إعدادات تطبيقك في "استضافة Firebase" من الدليل والملفات المحلية لتطبيقك. ولكن لإجراء ذلك، علينا ربط تطبيقك بمشروعك على Firebase.

  1. تأكَّد من أنّ سطر الأوامر يصل إلى الدليل المحلي لتطبيقك.
  2. اربط تطبيقك بمشروعك على Firebase من خلال تنفيذ الأمر التالي:
firebase use --add
  1. اختَر رقم تعريف المشروع عندما يُطلب منك ذلك، ثمّ أدخِل اسمًا بديلاً لمشروعك على Firebase.

يكون الاسم المعرِّف مفيدًا إذا كانت لديك بيئات متعددة (الإصدار العلني والإصدار التجريبي وما إلى ذلك). ومع ذلك، في هذا الدليل التعليمي حول الرموز البرمجية، لنستخدم العنوان البديل default.

  1. اتّبِع التعليمات المتبقية في سطر الأوامر.

5- تشغيل الخادم المحلي

نحن على استعداد لبدء العمل على تطبيقنا. لنشغّل تطبيقنا على الجهاز.

  1. نفِّذ الأمر التالي في واجهة سطر أوامر Firebase:
firebase emulators:start --only hosting
  1. من المفترض أن يعرض سطر الأوامر الاستجابة التالية:
hosting: Local server: http://localhost:5000

نحن نستخدم محاكي استضافة Firebase لعرض تطبيقنا على الجهاز. من المفترض أن يكون تطبيق الويب متاحًا الآن من http://localhost:5000.

  1. افتح تطبيقك على الرابط http://localhost:5000.

من المفترض أن تظهر لك نسخة من FriendlyEats تم ربطها بمشروعك على Firebase.

لقد ربط التطبيق تلقائيًا مشروعك على Firebase وسجّلك بدون إشعارك كمستخدم مجهول.

img2.png

6- كتابة البيانات في Cloud Firestore

في هذا القسم، سنكتب بعض البيانات في Cloud Firestore لنتمكّن من تعبئة واجهة مستخدم التطبيق. يمكن إجراء ذلك يدويًا من خلال وحدة تحكّم Firebase، ولكن سننفّذه في التطبيق نفسه لعرض عملية كتابة أساسية في Cloud Firestore.

نموذج البيانات

يتم تقسيم بيانات Firestore إلى مجموعات ومستندات وحقول ومجموعات فرعية. سنخزّن كل مطعم كمستند في مجموعة على مستوى أعلى تُسمى restaurants.

img3.png

وفي وقت لاحق، سنخزّن كل مراجعة في مجموعة فرعية باسم ratings ضمن كل مطعم.

img4.png

إضافة مطاعم إلى Firestore

عنصر النموذج الرئيسي في تطبيقنا هو مطعم. لنكتب بعض التعليمات البرمجية التي تضيف مستند مطعم إلى مجموعة restaurants.

  1. من الملفات التي تم تنزيلها، افتح scripts/FriendlyEats.Data.js.
  2. ابحث عن الدالة FriendlyEats.prototype.addRestaurant.
  3. استبدِل الدالة بأكملها بالرمز التالي.

FriendlyEats.Data.js

FriendlyEats.prototype.addRestaurant = function(data) {
  var collection = firebase.firestore().collection('restaurants');
  return collection.add(data);
};

يضيف الرمز أعلاه مستندًا جديدًا إلى مجموعة restaurants. تأتي بيانات المستند من عنصر JavaScript عادي. ننفّذ ذلك من خلال الحصول أولاً على مرجع إلى مجموعة Cloud Firestore restaurants ثم add للبيانات.

لنضيف المطاعم.

  1. ارجع إلى تطبيق FriendlyEats في المتصفّح وأعِد تحميله.
  2. انقر على إضافة بيانات وهمية.

سينشئ التطبيق تلقائيًا مجموعة عشوائية من عناصر المطاعم، ثم سيستدعي الدالة addRestaurant. ومع ذلك، لن تظهر لك البيانات في تطبيق الويب الفعلي بعد لأنّنا ما زلنا بحاجة إلى تنفيذ استرداد البيانات (القسم التالي من ورشة رموز البرامج).

إذا انتقلت إلى علامة تبويب Cloud Firestore في "وحدة تحكّم Firebase"، من المفترض أن تظهر لك الآن مستندات جديدة في مجموعة restaurants.

img6.png

مبروك، لقد كتبت للتو بيانات في Cloud Firestore من تطبيق ويب.

في القسم التالي، ستتعرّف على كيفية استرداد البيانات من Cloud Firestore وعرضها في تطبيقك.

7. عرض البيانات من Cloud Firestore

في هذا القسم، ستتعرّف على كيفية استرداد البيانات من Cloud Firestore وعرضها في تطبيقك. وهما خطوتان رئيسيتان: إنشاء طلب بحث وإضافة مستمع لقطات. سيتم إشعار هذا المستمع بجميع البيانات الحالية التي تتطابق مع الطلب، وسيتلقّى آخر المعلومات في الوقت الفعلي.

أولاً، لننشئ طلب البحث الذي سيعرض القائمة التلقائية غير المُفلترة للمطاعم.

  1. ارجع إلى الملف scripts/FriendlyEats.Data.js.
  2. ابحث عن الدالة FriendlyEats.prototype.getAllRestaurants.
  3. استبدِل الدالة بأكملها بالرمز التالي.

FriendlyEats.Data.js

FriendlyEats.prototype.getAllRestaurants = function(renderer) {
  var query = firebase.firestore()
      .collection('restaurants')
      .orderBy('avgRating', 'desc')
      .limit(50);

  this.getDocumentsInQuery(query, renderer);
};

في الرمز أعلاه، نُنشئ طلب بحث سيسترجع ما يصل إلى 50 مطعمًا من المجموعة ذات المستوى الأعلى التي تحمل الاسم restaurants، والتي يتم ترتيبها حسب متوسط التقييم (كل التقييمات حاليًا صفرية). بعد أن نعلن عن هذا الطلب، نمرّره إلى طريقة getDocumentsInQuery() المسؤولة عن تحميل البيانات وعرضها.

سنفعل ذلك من خلال إضافة مستمع لقطة شاشة.

  1. ارجع إلى الملف scripts/FriendlyEats.Data.js.
  2. ابحث عن الدالة FriendlyEats.prototype.getDocumentsInQuery.
  3. استبدِل الدالة بأكملها بالرمز التالي.

FriendlyEats.Data.js

FriendlyEats.prototype.getDocumentsInQuery = function(query, renderer) {
  query.onSnapshot(function(snapshot) {
    if (!snapshot.size) return renderer.empty(); // Display "There are no restaurants".

    snapshot.docChanges().forEach(function(change) {
      if (change.type === 'removed') {
        renderer.remove(change.doc);
      } else {
        renderer.display(change.doc);
      }
    });
  });
};

في الرمز أعلاه، سيُشغِّل query.onSnapshot دالة الاستدعاء في كل مرة يحدث فيها تغيير في نتيجة الطلب.

  • في المرة الأولى، يتم تشغيل دالة الاستدعاء مع مجموعة النتائج بالكامل من طلب البحث، أي مجموعة restaurants بأكملها من Cloud Firestore. وبعد ذلك، يتم تمرير جميع المستندات الفردية إلى الدالة renderer.display.
  • عند حذف مستند، يساوي change.type removed. في هذه الحالة، سنستدعي دالة تزيل المطعم من واجهة المستخدم.

بعد تنفيذ كلتا الطريقتَين، أعِد تحميل التطبيق وتأكَّد من أنّ المطاعم التي رأيناها سابقًا في وحدة تحكّم Firebase ظاهرة الآن في التطبيق. إذا أكملت هذا القسم بنجاح، يعني ذلك أنّ تطبيقك يقرأ البيانات ويكتبها الآن باستخدام Cloud Firestore.

وكلما تغيّرت قائمة المطاعم، سيستمر هذا المستمع في التحديث تلقائيًا. جرِّب الانتقال إلى وحدة تحكّم Firebase وحذف مطعم يدويًا أو تغيير اسمه، وستلاحظ ظهور التغييرات على موقعك الإلكتروني على الفور.

img5.png

8. بيانات Get()

لقد شرحنا حتى الآن كيفية استخدام onSnapshot لاسترداد آخر الأخبار في الوقت الفعلي، ولكن هذا ليس ما نريد دائمًا. في بعض الأحيان، يكون من المنطقي جلب البيانات مرة واحدة فقط.

سنحتاج إلى تنفيذ طريقة يتم تفعيلها عندما ينقر مستخدم على مطعم معيّن في تطبيقك.

  1. ارجع إلى ملفك scripts/FriendlyEats.Data.js.
  2. ابحث عن الدالة FriendlyEats.prototype.getRestaurant.
  3. استبدِل الدالة بأكملها بالرمز التالي.

FriendlyEats.Data.js

FriendlyEats.prototype.getRestaurant = function(id) {
  return firebase.firestore().collection('restaurants').doc(id).get();
};

بعد تنفيذ هذه الطريقة، ستتمكّن من عرض صفحات كل مطعم. ما عليك سوى النقر على مطعم في القائمة وستظهر لك صفحة تفاصيل المطعم:

img1.png

في الوقت الحالي، لا يمكنك إضافة تقييمات لأنّنا ما زلنا بحاجة إلى تنفيذ إضافة التقييمات لاحقًا في ورشة رموز البرامج.

9. ترتيب البيانات وتصفيتها

يعرض تطبيقنا حاليًا قائمة بالمطاعم، ولكن لا تتوفّر للمستخدم طريقة لفلترة النتائج استنادًا إلى احتياجاته. في هذا القسم، ستستخدم طلبات البحث المتقدّمة في Cloud Firestore لتفعيل التصفية.

في ما يلي مثال على طلب بحث بسيط لجلب جميع المطاعم Dim Sum:

var filteredQuery = query.where('category', '==', 'Dim Sum')

كما يوحي الاسم، ستؤدي طريقة where() إلى تنزيل طلب البحث فقط لأعضاء المجموعة الذين تستوفي حقولهم القيود التي وضعناها. في هذه الحالة، سيتم تنزيل المطاعم التي يكون فيها category هو Dim Sum فقط.

في تطبيقنا، يمكن للمستخدم ربط فلاتر متعددة لإنشاء طلبات بحث محدّدة، مثل "بيتزا في القاهرة" أو "مأكولات بحرية في الإسكندرية حسب مدى الرائج".

سننشئ طريقة لإنشاء طلب بحث سيفلتر المطاعم استنادًا إلى معايير متعدّدة يختارها المستخدمون.

  1. ارجع إلى ملفك scripts/FriendlyEats.Data.js.
  2. ابحث عن الدالة FriendlyEats.prototype.getFilteredRestaurants.
  3. استبدِل الدالة بأكملها بالرمز التالي.

FriendlyEats.Data.js

FriendlyEats.prototype.getFilteredRestaurants = function(filters, renderer) {
  var query = firebase.firestore().collection('restaurants');

  if (filters.category !== 'Any') {
    query = query.where('category', '==', filters.category);
  }

  if (filters.city !== 'Any') {
    query = query.where('city', '==', filters.city);
  }

  if (filters.price !== 'Any') {
    query = query.where('price', '==', filters.price.length);
  }

  if (filters.sort === 'Rating') {
    query = query.orderBy('avgRating', 'desc');
  } else if (filters.sort === 'Reviews') {
    query = query.orderBy('numRatings', 'desc');
  }

  this.getDocumentsInQuery(query, renderer);
};

يضيف الرمز البرمجي أعلاه فلاتر where متعددة وعبارة orderBy واحدة لإنشاء طلب بحث مركّب استنادًا إلى إدخال المستخدم. لن يعرض طلب البحث الآن سوى المطاعم التي تتوافق مع متطلبات المستخدم.

أعِد تحميل تطبيق FriendlyEats في المتصفّح، ثم تأكَّد من أنّه يمكنك الفلترة حسب السعر والمدينة والفئة. أثناء الاختبار، ستظهر لك أخطاء في وحدة تحكّم JavaScript في المتصفّح على النحو التالي:

The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_composite=...

تحدث هذه الأخطاء لأنّ Cloud Firestore تتطلّب إنشاء فهارس لمعظم طلبات البحث المركبة. إنّ طلب الفهارس على طلبات البحث يحافظ على سرعة Cloud Firestore على نطاق واسع.

سيؤدي فتح الرابط من رسالة الخطأ إلى فتح واجهة مستخدم إنشاء الفهرس تلقائيًا في وحدة تحكّم Firebase مع ملء المَعلمات الصحيحة. في القسم التالي، سنكتب الفهارس اللازمة لهذا التطبيق وننشرها.

10. نشر الفهارس

إذا لم نرغب في استكشاف كل مسار في تطبيقنا واتّباع كل رابط من روابط إنشاء الفهرس، يمكننا بسهولة نشر العديد من الفهارس في آنٍ واحد باستخدام واجهة برمجة التطبيقات Firebase CLI.

  1. في الدليل المحلي الذي تم تنزيله من تطبيقك، ستجد ملف firestore.indexes.json.

يصف هذا الملفّ جميع الفهارس اللازمة لجميع التركيبات الممكنة للفلاتر.

firestore.indexes.json

{
 "indexes": [
   {
     "collectionGroup": "restaurants",
     "queryScope": "COLLECTION",
     "fields": [
       { "fieldPath": "city", "order": "ASCENDING" },
       { "fieldPath": "avgRating", "order": "DESCENDING" }
     ]
   },

   ...

 ]
}
  1. يمكنك نشر هذه الفهارس باستخدام الأمر التالي:
firebase deploy --only firestore:indexes

بعد بضع دقائق، ستصبح الفهارس متوفّرة وستتم إزالة رسائل الخطأ.

11. كتابة البيانات في معاملة

في هذا القسم، سنضيف ميزة تتيح للمستخدمين إرسال مراجعات عن المطاعم. حتى الآن، كانت جميع عمليات الكتابة لدينا بسيطة نسبيًا. إذا حدث خطأ في أيّ من هذه العمليات، من المرجّح أن نطلب من المستخدم إعادة تنفيذها أو أن يعيد تطبيقنا تنفيذ عملية الكتابة تلقائيًا.

سيضم تطبيقنا العديد من المستخدمين الذين يريدون إضافة تقييم لمطعم، لذا سنحتاج إلى تنسيق عمليات القراءة والكتابة المتعدّدة. يجب أولاً إرسال المراجعة نفسها، ثم تعديل تقييم المطعم count وaverage rating. إذا تعذّر تنفيذ أحدهما ولكن تم تنفيذ الآخر، سنبقى في حالة غير متّسقة حيث لا تتطابق البيانات في جزء من قاعدة بياناتنا مع البيانات في جزء آخر.

لحسن الحظ، توفّر Cloud Firestore وظيفة المعاملات التي تسمح لنا بإجراء عمليات قراءة وكتابة متعددة في عملية واحدة موحّدة، ما يضمن بقاء بياناتنا متسقة.

  1. ارجع إلى ملفك scripts/FriendlyEats.Data.js.
  2. ابحث عن الدالة FriendlyEats.prototype.addRating.
  3. استبدِل الدالة بأكملها بالرمز التالي.

FriendlyEats.Data.js

FriendlyEats.prototype.addRating = function(restaurantID, rating) {
  var collection = firebase.firestore().collection('restaurants');
  var document = collection.doc(restaurantID);
  var newRatingDocument = document.collection('ratings').doc();

  return firebase.firestore().runTransaction(function(transaction) {
    return transaction.get(document).then(function(doc) {
      var data = doc.data();

      var newAverage =
          (data.numRatings * data.avgRating + rating.rating) /
          (data.numRatings + 1);

      transaction.update(document, {
        numRatings: data.numRatings + 1,
        avgRating: newAverage
      });
      return transaction.set(newRatingDocument, rating);
    });
  });
};

في المجموعة أعلاه، نُجري معاملة لتعديل القيم الرقمية avgRating وnumRatings في مستند المطعم. في الوقت نفسه، نضيف rating الجديدة إلى المجموعة الفرعية ratings.

12. تأمين بياناتك

في بداية هذا الدليل التعليمي حول الرموز البرمجية، ضبطنا قواعد أمان تطبيقنا لحظر الوصول إليه.

firestore.rules

rules_version = '2';
service cloud.firestore {

  // Determine if the value of the field "key" is the same
  // before and after the request.
  function unchanged(key) {
    return (key in resource.data)
      && (key in request.resource.data)
      && (resource.data[key] == request.resource.data[key]);
  }

  match /databases/{database}/documents {
    // Restaurants:
    //   - Authenticated user can read
    //   - Authenticated user can create/update (for demo purposes only)
    //   - Updates are allowed if no fields are added and name is unchanged
    //   - Deletes are not allowed (default)
    match /restaurants/{restaurantId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null;
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys())
                    && unchanged("name");

      // Ratings:
      //   - Authenticated user can read
      //   - Authenticated user can create if userId matches
      //   - Deletes and updates are not allowed (default)
      match /ratings/{ratingId} {
        allow read: if request.auth != null;
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;
      }
    }
  }
}

تفرض هذه القواعد قيودًا على الوصول لضمان إجراء العملاء تغييرات آمنة فقط. على سبيل المثال:

  • لا يمكن أن تؤدي التعديلات على مستند المطعم إلى تغيير التقييمات فقط، وليس الاسم أو أي بيانات أخرى غير قابلة للتغيير.
  • لا يمكن إنشاء التقييمات إلا إذا كان رقم تعريف المستخدم مطابقًا للمستخدم الذي سجّل الدخول، ما يمنع انتحال الهوية.

بدلاً من استخدام وحدة تحكّم Firebase، يمكنك استخدام واجهة برمجة التطبيقات Firebase CLI لنشر القواعد في مشروعك على Firebase. يحتوي ملف firestore.rules في دليل العمل على القواعد الواردة أعلاه. لنشر هذه القواعد من نظام الملفات المحلي (بدلاً من استخدام وحدة تحكّم Firebase)، عليك تنفيذ الأمر التالي:

firebase deploy --only firestore:rules

13. الخاتمة

في هذا الدليل التعليمي حول الرموز البرمجية، تعلمت كيفية إجراء عمليات القراءة والكتابة الأساسية والمتقدّمة باستخدام Cloud Firestore، بالإضافة إلى كيفية تأمين الوصول إلى البيانات باستخدام قواعد الأمان. يمكنك العثور على الحل الكامل في مستودع quickstarts-js.

لمزيد من المعلومات حول Cloud Firestore، يُرجى الانتقال إلى المراجع التالية:

14. [اختياري] فرض الميزة باستخدام App Check

توفّر ميزة فحص التطبيقات من Firebase الحماية من خلال المساعدة في التحقّق من الزيارات غير المرغوب فيها إلى تطبيقك ومنعها. وفي هذه الخطوة، ستؤمّن الوصول إلى خدماتك من خلال إضافة ميزة "فحص التطبيقات" مع reCAPTCHA Enterprise.

أولاً، عليك تفعيل ميزتَي "فحص التطبيق" وreCaptcha.

تفعيل reCaptcha Enterprise

  1. في وحدة تحكّم Cloud، ابحث عن reCaptcha Enterprise واختَره ضمن "الأمان".
  2. فعِّل الخدمة كما هو مطلوب، ثم انقر على إنشاء مفتاح.
  3. أدخِل اسمًا معروضًا كما هو مطلوب، واختَر موقع إلكتروني كنوع المنصة.
  4. أضِف عناوين URL المنشورة إلى قائمة النطاقات، وتأكَّد من عدم اختيار الخيار "استخدام تحدّي مربّع الاختيار".
  5. انقر على إنشاء مفتاح، واحفظ المفتاح الذي تم إنشاؤه في مكان آمن. ستحتاج إليه لاحقًا في هذه الخطوة.

تفعيل ميزة "فحص التطبيق"

  1. في وحدة تحكّم Firebase، ابحث عن قسم الإصدار في اللوحة اليمنى.
  2. انقر على فحص التطبيق، ثم انقر على الزر البدء (أو إعادة التوجيه مباشرةً إلى وحدة التحكّم).
  3. انقر على تسجيل وأدخِل مفتاح reCaptcha Enterprise عندما يُطلب منك ذلك، ثم انقر على حفظ.
  4. في عرض واجهات برمجة التطبيقات، اختَر مساحة التخزين وانقر على فرض. اتّبِع الخطوات نفسها مع Cloud Firestore.

من المفترض أن يكون تطبيق "فحص التطبيق" مفعّلاً الآن. يُرجى إعادة تحميل التطبيق ومحاولة إنشاء مطعم أو الاطّلاع عليه. من المفترض أن تظهر لك رسالة الخطأ التالية:

Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

وهذا يعني أنّ أداة App Check تحظر الطلبات التي لم يتم التحقّق منها تلقائيًا. لنضيف الآن عملية التحقّق إلى تطبيقك.

انتقِل إلى ملف FriendlyEats.View.js وعدِّل الدالة initAppCheck وأضِف مفتاح إعادة التحقق من صحة المستخدمين (reCaptcha) لبدء فحص التطبيق.

FriendlyEats.prototype.initAppCheck = function() {
    var appCheck = firebase.appCheck();
    appCheck.activate(
    new firebase.appCheck.ReCaptchaEnterpriseProvider(
      /* reCAPTCHA Enterprise site key */
    ),
    true // Set to true to allow auto-refresh.
  );
};

يتمّ إعداد مثيل appCheck باستخدام ReCaptchaEnterpriseProvider مع مفتاحك، ويسمح isTokenAutoRefreshEnabled بإعادة تحميل الرموز المميّزة تلقائيًا في تطبيقك.

لتفعيل الاختبار على الجهاز، ابحث عن القسم الذي يتم فيه إعداد التطبيق في ملف FriendlyEats.js، وأضِف السطر التالي إلى الدالة FriendlyEats.prototype.initAppCheck:

if(isLocalhost) {
  self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}

سيؤدي ذلك إلى تسجيل رمز مميّز لتصحيح الأخطاء في وحدة تحكّم تطبيق الويب المحلي، على النحو التالي:

App Check debug token: 8DBDF614-649D-4D22-B0A3-6D489412838B. You will need to add it to your app's App Check settings in the Firebase console for it to work.

الآن، انتقِل إلى عرض التطبيقات في ميزة "فحص التطبيقات" في وحدة تحكُّم Firebase.

انقر على قائمة الخيارات الإضافية، واختَر إدارة الرموز المميّزة لتصحيح الأخطاء.

بعد ذلك، انقر على إضافة رمز تصحيح الأخطاء والصق رمز تصحيح الأخطاء من وحدة التحكّم كما هو مطلوب.

تهانينا! من المفترض أن يعمل تطبيق "فحص التطبيق" الآن في تطبيقك.