अपने 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 सीएलआई का इस्तेमाल करें. इसके बाद, यहां दिया गया कमांड चलाएं:

firebase setup:emulators:firestore

एम्युलेटर चलाएं

सबसे पहले, अपनी वर्किंग डायरेक्ट्री में Firebase प्रोजेक्ट शुरू करें. Firebase सीएलआई का इस्तेमाल करते समय, यह पहला चरण है.

firebase init

नीचे दिए गए निर्देश का इस्तेमाल करके, एम्युलेटर को शुरू करें. एम्युलेटर तब तक चलेगा, जब तक कि इस प्रोसेस को बंद नहीं किया जाता:

firebase emulators:start --only firestore

कई मामलों में, आप एम्युलेटर शुरू करना चाहते हैं, एक टेस्ट सुइट चलाना चाहते हैं, और फिर जांच चलाने के बाद एम्युलेटर को बंद करना चाहते हैं. emulators:exec निर्देश का इस्तेमाल करके, ऐसा आसानी से किया जा सकता है:

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

शुरू होने पर, एम्युलेटर डिफ़ॉल्ट पोर्ट (8080) पर चलने की कोशिश करेगा. अपनी firebase.json फ़ाइल के "emulators" सेक्शन में बदलाव करके, एम्युलेटर पोर्ट को बदला जा सकता है:

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

एम्युलेटर को चलाने से पहले

एम्युलेटर का इस्तेमाल शुरू करने से पहले, इन बातों का ध्यान रखें:

  • एम्युलेटर शुरू में आपकी firebase.json फ़ाइल के firestore.rules फ़ील्ड में बताए गए नियमों को लोड करेगा. इसे उस लोकल फ़ाइल के नाम की ज़रूरत होती है जिसमें आपके Cloud Firestore के सुरक्षा नियम मौजूद होते हैं. साथ ही, उन नियमों को सभी प्रोजेक्ट पर लागू करता है. अगर लोकल फ़ाइल पाथ नहीं दिया जाता या नीचे बताए गए loadFirestoreRules तरीके का इस्तेमाल किया जाता है, तो एम्युलेटर सभी प्रोजेक्ट को सभी के लिए लागू नियम मानता है.
  • हालांकि, ज़्यादातर Firebase SDK टूल, एम्युलेटर के साथ सीधे काम करते हैं. हालांकि, सुरक्षा के नियमों में सिर्फ़ @firebase/rules-unit-testing लाइब्रेरी का इस्तेमाल करके auth की नकल की जा सकती है. इससे यूनिट टेस्ट करना आसान हो जाता है. इसके अलावा, लाइब्रेरी में एम्युलेटर की कुछ खास सुविधाओं का भी इस्तेमाल किया जा सकता है, जैसे कि सारा डेटा मिटाना. ये सुविधाएं नीचे दी गई हैं.
  • एम्युलेटर, क्लाइंट SDK टूल से मिले प्रोडक्शन Firebase पुष्टि टोकन भी स्वीकार करेंगे और उसके मुताबिक नियमों का आकलन करेंगे. इससे आपका ऐप्लिकेशन, इंटिग्रेशन और मैन्युअल टेस्ट में मौजूद एम्युलेटर से सीधे कनेक्ट हो पाएगा.

लोकल यूनिट टेस्ट चलाना

v9 JavaScript SDK टूल की मदद से लोकल यूनिट टेस्ट करना

Firebase अपने वर्शन 9 JavaScript SDK और अपने वर्शन 8 SDK, दोनों के साथ सुरक्षा नियमों की यूनिट टेस्टिंग लाइब्रेरी उपलब्ध कराता है. लाइब्रेरी के एपीआई काफ़ी अलग होते हैं. हम v9 टेस्टिंग लाइब्रेरी का सुझाव देते हैं, जो ज़्यादा व्यवस्थित है. साथ ही, इसे एम्युलेटर से कनेक्ट करने के लिए कम सेटअप की ज़रूरत होती है. इस तरह, प्रोडक्शन संसाधनों के गलती से इस्तेमाल से बचा जा सकता है. पुराने सिस्टम के साथ काम करने की सुविधा के लिए, हम v8 टेस्टिंग लाइब्रेरी उपलब्ध कराते रहेंगे.

स्थानीय तौर पर चलने वाले एम्युलेटर के साथ इंटरैक्ट करने के लिए, @firebase/rules-unit-testing मॉड्यूल का इस्तेमाल करें. अगर आपको टाइम आउट या ECONNREFUSED गड़बड़ियां मिलती हैं, तो दोबारा जांच लें कि एम्युलेटर असल में चल रहा है या नहीं.

हमारा सुझाव है कि आप Node.js के नए वर्शन का इस्तेमाल करें, ताकि आप async/await नोटेशन का इस्तेमाल कर सकें. करीब-करीब हर उस व्यवहार की जांच होती है जिसकी आपको जांच करनी है. टेस्टिंग मॉड्यूल को इस तरह से डिज़ाइन किया गया है कि यह प्रॉमिस-आधारित कोड के साथ काम करता है.

v9 रूल यूनिट की टेस्टिंग लाइब्रेरी को एम्युलेटर के बारे में हमेशा जानकारी रहती है. साथ ही, यह आपके प्रोडक्शन से जुड़े संसाधनों को बेहतर तरीके से छूता नहीं है.

आप v9 मॉड्यूलर इंपोर्ट स्टेटमेंट का इस्तेमाल करके लाइब्रेरी इंपोर्ट करते हैं. उदाहरण के लिए:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment
} 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.

इंपोर्ट होने के बाद, यूनिट टेस्ट लागू करने के लिए ये काम करने की ज़रूरत होती है:

  • initializeTestEnvironment को कॉल के साथ RulesTestEnvironment बनाना और कॉन्फ़िगर करना.
  • नियमों को ट्रिगर किए बिना, टेस्ट डेटा सेट अप करने के लिए, एक आसान तरीका इस्तेमाल करें. इससे, कुछ समय के लिए उन्हें बायपास किया जा सकता है, RulesTestEnvironment.withSecurityRulesDisabled.
  • टेस्ट सुइट और हर टेस्ट को सेट अप करने से, टेस्ट डेटा और एनवायरमेंट को साफ़ करने के लिए कहा जाता है, जैसे कि RulesTestEnvironment.cleanup() या RulesTestEnvironment.clearFirestore().
  • ऐसे टेस्ट केस लागू करना जो RulesTestEnvironment.authenticatedContext और RulesTestEnvironment.unauthenticatedContext का इस्तेमाल करके, पुष्टि करने की स्थिति की नकल करते हैं.

सामान्य तरीके और उपयोगिता फ़ंक्शन

v9 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 ऑथराइज़ेशन टोकन अटैच नहीं होगा.

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'), { ... });

एम्युलेटर के लिए खास तरीके

v9 SDK टूल में टेस्ट करने के सामान्य तरीके और यूटिलिटी फ़ंक्शन भी देखें.

RulesTestEnvironment.clearFirestore() => Promise<void>

इस तरीके से, Firestore डेटाबेस में मौजूद डेटा को हटा दिया जाता है. यह डेटा, Firestore एम्युलेटर के लिए कॉन्फ़िगर किए गए projectId से जुड़ा होता है.

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

जांच के इस कॉन्टेक्स्ट के लिए, इस तरीके को Firestore इंस्टेंस मिलता है. लौटाए गए Firebase JS क्लाइंट SDK इंस्टेंस का इस्तेमाल, क्लाइंट SDK API (v9 मॉड्यूलर या v9 कंपैट) के साथ किया जा सकता है.

नियमों के आकलन को विज़ुअलाइज़ करना

Cloud Firestore एम्युलेटर की मदद से, एम्युलेटर सुइट के यूज़र इंटरफ़ेस (यूआई) में क्लाइंट के अनुरोधों को विज़ुअलाइज़ किया जा सकता है. इसमें, Firebase के सुरक्षा नियमों के लिए इवैलुएशन ट्रेसिंग भी शामिल है.

हर अनुरोध का पूरा आकलन करने का क्रम देखने के लिए, Firestore > अनुरोध टैब खोलें.

Firestore एम्युलेटर के अनुरोधों का मॉनिटर करने से, सुरक्षा के नियमों का आकलन दिखाया जा रहा है

टेस्ट रिपोर्ट जनरेट करना

टेस्ट का सुइट चलाने के बाद, टेस्ट कवरेज रिपोर्ट ऐक्सेस की जा सकती हैं. इससे पता चलता है कि सुरक्षा के हर नियम का आकलन किस तरह किया गया है.

रिपोर्ट पाने के लिए, एम्युलेटर पर चलने के दौरान, बिना अनुमति के सार्वजनिक किए गए एंडपॉइंट से क्वेरी करें. ब्राउज़र-फ़्रेंडली वर्शन के लिए, इस यूआरएल का इस्तेमाल करें:

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

इससे आपके नियम, एक्सप्रेशन और सब-एक्सप्रेशन में बंट जाते हैं. ज़्यादा जानकारी के लिए, इनका माउसओवर किया जा सकता है. इसमें आकलन और दिखाई गई वैल्यू की संख्या शामिल है. इस डेटा के रॉ JSON वर्शन के लिए, अपनी क्वेरी में यह यूआरएल शामिल करें:

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

एम्युलेटर और प्रोडक्शन के बीच अंतर

  1. आपको अलग से Cloud Firestore प्रोजेक्ट बनाने की ज़रूरत नहीं है. एम्युलेटर, ऐक्सेस किया जाने वाला कोई भी इंस्टेंस अपने-आप बना देता है.
  2. Cloud Firestore एम्युलेटर, Firebase की पुष्टि करने की सामान्य प्रक्रिया के साथ काम नहीं करता. इसके बजाय, हमने Firebase टेस्ट SDK टूल में rules-unit-testing लाइब्रेरी में initializeTestApp() तरीका दिया है. इसके लिए, 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 सुरक्षा नियम, अलग-अलग मामलों को सही तरीके से अनुमति देते हैं / अस्वीकार करते हैं.