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

1- نظرة عامة

الأهداف

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

img5.png

المعلومات التي ستطّلع عليها

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

المتطلبات

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

  • npm الذي يأتي عادةً مع Node.js: يُنصح باستخدام العقدة 16 والإصدارات الأحدث
  • محرِّر IDE أو نصّ، مثل WebStorm أو VS Code أو Sublime

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

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

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

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

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

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

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

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

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

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

عليك تفعيل تسجيل الدخول مع إخفاء الهوية.

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

img7.png

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

تفعيل Cloud Firestore

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

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

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

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

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

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

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

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

من المفترَض أن يكون قد تم استنساخ نموذج الرمز في الدليل 📁friendlyeats-web. من الآن فصاعدًا، تأكَّد من تشغيل جميع الأوامر من هذا الدليل:

cd friendlyeats-web/vanilla-js

استيراد تطبيق إجراء التفعيل

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

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

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

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

تأكَّد من أنّ إصدار واجهة سطر الأوامر في Firebase هو الإصدار 7.4.0 أو إصدار أحدث.

  1. فوّض واجهة سطر الأوامر في Firebase من خلال تشغيل الأمر التالي:
firebase login

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

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

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

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

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

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

  1. شغِّل أمر Firebase CLI التالي:
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.

  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- تأمين بياناتك

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

  1. في قسم إنشاء في وحدة تحكُّم Firebase، انقر على قاعدة بيانات Firestore.
  2. انقر على علامة التبويب القواعد في قسم Cloud Firestore (أو انقر هنا للانتقال مباشرةً إلى هناك).
  3. استبدِل الإعدادات التلقائية بالقواعد التالية، ثمّ انقر على نشر.

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 لنشر القواعد إلى مشروعك على Firebase. يحتوي ملف firestore.rules في دليل العمل على القواعد المذكورة أعلاه. لنشر هذه القواعد من نظام الملفات على الجهاز (بدلاً من استخدام وحدة تحكُّم Firebase)، عليك تشغيل الأمر التالي:

firebase deploy --only firestore:rules

13- الخاتمة

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

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

14- [اختياري] فرض السياسة باستخدام ميزة "التحقّق من التطبيقات"

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

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

تفعيل reCAPTCHA Enterprise

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

تفعيل فحص التطبيقات

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

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

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

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

انتقِل إلى ملف 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.

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

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

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