اختبر قواعد أمان Cloud Firestore

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

بداية سريعة

بالنسبة لعدد قليل من حالات الاختبار الأساسية ذات القواعد البسيطة ، جرب عينة البدء السريع .

فهم قواعد أمان Cloud Firestore

نفِّذ مصادقة Firebase وقواعد أمان Cloud Firestore للمصادقة بدون خادم والتفويض والتحقق من صحة البيانات عند استخدام مكتبات عميل الويب والجوال.

تتضمن قواعد أمان Cloud Firestore قطعتين:

  1. بيان match يحدد المستندات في قاعدة البيانات الخاصة بك.
  2. تعبير allow بالتحكم في الوصول إلى تلك المستندات.

تتحقق مصادقة Firebase من بيانات اعتماد المستخدمين وتوفر الأساس لأنظمة الوصول المستندة إلى المستخدم والمستندة إلى الأدوار.

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

تعرف على المزيد حول قواعد أمان Cloud Firestore في بدء استخدام قواعد أمان Cloud Firestore .

قم بتثبيت المحاكي

لتثبيت محاكي Cloud Firestore ، استخدم Firebase CLI وقم بتشغيل الأمر أدناه:

firebase setup:emulators:firestore

قم بتشغيل المحاكي

ابدأ بتهيئة مشروع Firebase في دليل العمل الخاص بك. هذه خطوة أولى شائعة عند استخدام Firebase CLI .

firebase init

ابدأ المحاكي باستخدام الأمر التالي. سيتم تشغيل المحاكي حتى تقتل العملية:

firebase emulators:start --only firestore

في كثير من الحالات ، تريد بدء تشغيل المحاكي ، وتشغيل مجموعة اختبار ، ثم إيقاف تشغيل المحاكي بعد تشغيل الاختبارات. يمكنك القيام بذلك بسهولة باستخدام emulators:exec :

firebase emulators:exec --only firestore "./my-test-script.sh"

عند بدء تشغيل المحاكي سيحاول التشغيل على المنفذ الافتراضي (8080). يمكنك تغيير منفذ المحاكي عن طريق تعديل قسم "emulators" في ملف firebase.json الخاص بك:

{
  // ...
  "emulators": {
    "firestore": {
      "port": "YOUR_PORT"
    }
  }
}

قبل تشغيل المحاكي

قبل البدء في استخدام المحاكي ، ضع في اعتبارك ما يلي:

  • سيقوم المحاكي في البداية بتحميل القواعد المحددة في حقل firestore.rules لملف firebase.json الخاص بك. تتوقع اسم ملف محلي يحتوي على قواعد أمان Cloud Firestore الخاصة بك وتطبق هذه القواعد على جميع المشاريع. إذا لم تقدم مسار الملف المحلي أو تستخدم طريقة loadFirestoreRules كما هو موضح أدناه ، فإن المحاكي يعامل جميع المشاريع على أنها ذات قواعد مفتوحة.
  • بينما تعمل معظم مجموعات Firebase SDK مع المحاكيات مباشرةً ، تدعم مكتبة @firebase/rules-unit-testing فقط auth السخرية في قواعد الأمان ، مما يجعل اختبارات الوحدة أسهل بكثير. بالإضافة إلى ذلك ، تدعم المكتبة بعض الميزات الخاصة بالمحاكي مثل مسح جميع البيانات ، كما هو موضح أدناه.
  • ستقبل المحاكيات أيضًا رموز Firebase Auth المميزة للإنتاج المقدمة من خلال Client SDKs وتقييم القواعد وفقًا لذلك ، مما يسمح بربط تطبيقك مباشرة بالمحاكيات في التكامل والاختبارات اليدوية.

قم بإجراء اختبارات الوحدة المحلية

قم بإجراء اختبارات الوحدة المحلية باستخدام الإصدار 9 من JavaScript SDK

يوزع Firebase مكتبة اختبار وحدة قواعد الأمان مع الإصدار 9 من JavaScript SDK والإصدار 8 SDK. تختلف واجهات برمجة التطبيقات الخاصة بالمكتبة اختلافًا كبيرًا. نوصي بمكتبة اختبار الإصدار 9 ، وهي أكثر انسيابية وتتطلب إعدادًا أقل للاتصال بالمحاكيات وبالتالي تجنب الاستخدام العرضي لموارد الإنتاج بأمان. للتوافق مع الإصدارات السابقة ، نواصل إتاحة مكتبة اختبار الإصدار 8.

استخدم @firebase/rules-unit-testing للتفاعل مع المحاكي الذي يعمل محليًا. إذا حصلت على أخطاء مهلة أو أخطاء ECONNREFUSED ، فتحقق جيدًا من تشغيل المحاكي بالفعل.

نوصي بشدة باستخدام إصدار حديث من Node.js حتى تتمكن من استخدام تدوين غير async/await . تتضمن جميع السلوكيات التي قد ترغب في اختبارها تقريبًا وظائف غير متزامنة ، وقد تم تصميم وحدة الاختبار للعمل مع التعليمات البرمجية المستندة إلى Promise.

مكتبة v9 Rules Unit Testing دائمًا على دراية بالمحاكيات ولا تلمس أبدًا موارد الإنتاج الخاصة بك.

يمكنك استيراد المكتبة باستخدام عبارات الاستيراد المعيارية v9. فمثلا:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
  RulesTestEnvironment,
} from "@firebase/rules-unit-testing"

// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.

بمجرد الاستيراد ، يتضمن تنفيذ اختبارات الوحدة ما يلي:

  • إنشاء وتكوين " RulesTestEnvironment " مع استدعاء initializeTestEnvironment الاختبار البيئة.
  • إعداد بيانات الاختبار دون تشغيل القواعد ، باستخدام طريقة ملائمة تسمح لك بتجاوزها مؤقتًا ، RulesTestEnvironment.withSecurityRulesDisabled .
  • إعداد مجموعة الاختبار وكل اختبار قبل / بعد الخطافات مع استدعاءات لتنظيف بيانات الاختبار والبيئة ، مثل RulesTestEnvironment.cleanup() أو RulesTestEnvironment.clearFirestore() .
  • تنفيذ حالات الاختبار التي تحاكي حالات المصادقة باستخدام RulesTestEnvironment.authenticatedContext و RulesTestEnvironment.unauthenticatedContext .

الطرق الشائعة ووظائف المنفعة

راجع أيضًا طرق الاختبار الخاصة بالمحاكي في الإصدار 9 SDK .

initializeTestEnvironment() => RulesTestEnvironment

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

تقبل الوظيفة كائنًا اختياريًا يحدد TestEnvironmentConfig ، والذي يمكن أن يتكون من معرف المشروع وإعدادات تكوين المحاكي.

let testEnv = await initializeTestEnvironment({
  projectId: "demo-project-1234",
  firestore: {
    rules: fs.readFileSync("firestore.rules", "utf8"),
  },
});

RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext

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

استخدم كائن سياق الاختبار الذي تم إرجاعه في اختباراتك للوصول إلى أي مثيلات محاكي تم تكوينها ، بما في ذلك تلك التي تم تكوينها باستخدام initializeTestEnvironment .

// Assuming a Firestore app and the Firestore emulator for this example
import { setDoc } from "firebase/firestore";

const alice = testEnv.authenticatedContext("alice", { … });
// Use the Firestore instance associated with this context
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

RulesTestEnvironment.unauthenticatedContext() => RulesTestContext

تنشئ هذه الطريقة RulesTestContext ، والتي تتصرف مثل عميل لم يتم تسجيل دخوله عبر المصادقة. الطلبات التي تم إنشاؤها عبر السياق الذي تم إرجاعه لن يتم إرفاق رموز Firebase Auth الخاصة بها.

استخدم كائن سياق الاختبار الذي تم إرجاعه في اختباراتك للوصول إلى أي مثيلات محاكي تم تكوينها ، بما في ذلك تلك التي تم تكوينها باستخدام initializeTestEnvironment .

// Assuming a Cloud Storage app and the Storage emulator for this example
import { getStorage, ref, deleteObject } from "firebase/storage";

const alice = testEnv.unauthenticatedContext();

// Use the Cloud Storage instance associated with this context
const desertRef = ref(alice.storage(), 'images/desert.jpg');
await assertSucceeds(deleteObject(desertRef));

RulesTestEnvironment.withSecurityRulesDisabled()

قم بتشغيل وظيفة إعداد اختبار مع سياق يتصرف كما لو تم تعطيل قواعد الأمان.

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

RulesTestEnvironment.cleanup()

تعمل هذه الطريقة على تدمير جميع RulesTestContexts التي تم إنشاؤها في بيئة الاختبار وتنظيف الموارد الأساسية ، مما يسمح بخروج نظيف.

هذه الطريقة لا تغير حالة المحاكيات بأي شكل من الأشكال. لإعادة تعيين البيانات بين الاختبارات ، استخدم طريقة البيانات الواضحة الخاصة بمحاكي التطبيق.

assertSucceeds(pr: Promise<any>)) => Promise<any>

هذه وظيفة حالة اختبار.

تؤكد الوظيفة أنه سيتم حل الوعد المقدم الذي يغلف عملية المحاكي بدون انتهاكات لقواعد الأمان.

await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

assertFails(pr: Promise<any>)) => Promise<any>

هذه وظيفة حالة اختبار.

تؤكد الوظيفة أن الوعد المقدم الذي يغلف عملية المحاكي سيتم رفضه بانتهاك قواعد الأمان.

await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });

طرق خاصة بالمحاكي

راجع أيضًا طرق الاختبار الشائعة ووظائف الأداة في الإصدار 9 SDK .

RulesTestEnvironment.clearFirestore() => Promise<void>

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

RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;

تحصل هذه الطريقة على مثيل Firestore لسياق الاختبار هذا. يمكن استخدام مثيل Firebase JS Client SDK الذي تم إرجاعه مع واجهات برمجة تطبيقات SDK للعميل (الإصدار 9 المعياري أو الإصدار 9 المتوافق).

تصور تقييمات القواعد

يتيح لك محاكي Cloud Firestore تصور طلبات العميل في واجهة مستخدم Emulator Suite ، بما في ذلك تتبع التقييم لقواعد أمان Firebase.

افتح علامة التبويب Firestore> الطلبات لعرض تسلسل التقييم التفصيلي لكل طلب.

Firestore Emulator طلبات مراقب يعرض تقييمات قواعد الأمان

توليد تقارير الاختبار

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

للحصول على التقارير ، استعلام عن نقطة نهاية مكشوفة على المحاكي أثناء تشغيله. للحصول على إصدار متوافق مع المتصفح ، استخدم عنوان URL التالي:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html

يؤدي هذا إلى تقسيم القواعد إلى تعبيرات وتعبيرات فرعية يمكنك تمرير الماوس فوقها للحصول على مزيد من المعلومات ، بما في ذلك عدد التقييمات والقيم التي تم إرجاعها. للحصول على نسخة JSON الأولية من هذه البيانات ، قم بتضمين عنوان URL التالي في استعلامك:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage

الفروق بين المحاكي والإنتاج

  1. لا يتعين عليك إنشاء مشروع Cloud Firestore بشكل صريح. يقوم المحاكي تلقائيًا بإنشاء أي مثيل يتم الوصول إليه.
  2. لا يعمل محاكي Cloud Firestore مع تدفق مصادقة Firebase العادي. بدلاً من ذلك ، في Firebase Test SDK ، قدمنا ​​طريقة initializeTestApp() في مكتبة rules-unit-testing ، والتي تأخذ حقل auth . سيعمل مقبض Firebase الذي تم إنشاؤه باستخدام هذه الطريقة كما لو أنه قد تمت مصادقته بنجاح ككيان تقدمه. إذا مررت قيمة null ، فسوف تتصرف كمستخدم غير مصدق ( auth != null ، على سبيل المثال).

استكشاف المشكلات المعروفة وإصلاحها

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

سلوك الاختبار غير متسق

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

على وجه الخصوص ، راجع العمليات غير المتزامنة التالية:

  • تحديد قواعد الأمان ، باستخدام ، على سبيل المثال ، initializeTestEnvironment .
  • قراءة وكتابة البيانات ، على سبيل المثال ، db.collection("users").doc("alice").get() .
  • التأكيدات التشغيلية ، بما في ذلك التأكيد على assertSucceeds والتأكيد على assertFails .

تجتاز الاختبارات فقط في المرة الأولى التي تقوم فيها بتحميل المحاكي

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

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

إعداد الاختبار معقد للغاية

عند إعداد اختبارك ، قد ترغب في تعديل البيانات بطريقة لا تسمح بها قواعد أمان Cloud Firestore بالفعل. إذا كانت القواعد الخاصة بك تجعل إعداد الاختبار معقدًا ، فحاول استخدام RulesTestEnvironment.withSecurityRulesDisabled في خطوات الإعداد ، لذلك لن تؤدي عمليات القراءة والكتابة إلى حدوث أخطاء PERMISSION_DENIED .

بعد ذلك ، يمكن للاختبار إجراء العمليات كمستخدم مصدق عليه أو غير مصادق باستخدام RulesTestEnvironment.authenticatedContext و unauthenticatedContext على التوالي. يتيح لك ذلك التحقق من أن قواعد أمان Cloud Firestore الخاصة بك تسمح / ترفض الحالات المختلفة بشكل صحيح.