इस पेज पर, सुरक्षा नियमों को स्ट्रक्चर करने और सुरक्षा नियमों के लिए शर्तें लिखने के बारे में बताया गया है. इससे आपको यह समझने में मदद मिलेगी कि Cloud Firestore Security Rules का इस्तेमाल करके, ऐसे नियम कैसे बनाए जा सकते हैं जो क्लाइंट को किसी दस्तावेज़ के कुछ फ़ील्ड पर कार्रवाइयां करने की अनुमति देते हैं, लेकिन अन्य फ़ील्ड पर नहीं.
ऐसा हो सकता है कि आप किसी दस्तावेज़ में किए जाने वाले बदलावों को दस्तावेज़ के लेवल पर नहीं, बल्कि फ़ील्ड के लेवल पर कंट्रोल करना चाहें.
उदाहरण के लिए, हो सकता है कि आप किसी क्लाइंट को कोई दस्तावेज़ बनाने या उसमें बदलाव करने की अनुमति देना चाहें, लेकिन उसे उस दस्तावेज़ के कुछ फ़ील्ड में बदलाव करने की अनुमति न देना चाहें. इसके अलावा, हो सकता है कि आप यह लागू करना चाहें कि क्लाइंट जो भी दस्तावेज़ बनाए उसमें फ़ील्ड का एक सेट हमेशा मौजूद हो. इस गाइड में बताया गया है कि Cloud Firestore Security Rules का इस्तेमाल करके, इनमें से कुछ टास्क कैसे पूरे किए जा सकते हैं.
एआई असिस्टेंस के लिए एआई प्रॉम्प्ट
एआई असिस्टेंस पाने के लिए, यहां दिए गए प्रॉम्प्ट को अपने एआई कोडिंग एजेंट (जैसे, Android Studio में Gemini, Antigravity, Claude Code, Codex, और Cursor) में कॉपी करें. प्रॉम्प्ट को अपनी पसंद के मुताबिक बनाया जा सकता है. साथ ही, एजेंट के साथ मिलकर उसमें बदलाव किया जा सकता है. इंस्टॉल करने के बारे में ज़्यादा जानकारी के लिए, Firebase एजेंट स्किल पर जाएं.
Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's Firestore data.
सिर्फ़ कुछ फ़ील्ड के लिए रीड ऐक्सेस देना
नियमों में रीड ऑपरेशन, दस्तावेज़ के लेवल पर किए जाते हैं. या तो पूरा दस्तावेज़ वापस मिलता है या कुछ भी नहीं. अधूरे दस्तावेज़ को वापस पाने का कोई तरीका नहीं है. सिर्फ़ सुरक्षा नियमों का इस्तेमाल करके, उपयोगकर्ताओं को किसी दस्तावेज़ में मौजूद खास फ़ील्ड को पढ़ने से नहीं रोका जा सकता.
अगर आपको किसी दस्तावेज़ में मौजूद कुछ फ़ील्ड को कुछ उपयोगकर्ताओं से छिपाकर रखना है, तो सबसे अच्छा तरीका यह होगा कि आप उन्हें किसी अलग दस्तावेज़ में रखें. उदाहरण के लिए, इस तरह के private सब-कलेक्शन में दस्तावेज़ बनाया जा सकता है:
/employees/{emp_id}
name: "Alice Hamilton",
department: 461,
start_date: <timestamp>
/employees/{emp_id}/private/finances
salary: 80000,
bonus_mult: 1.25,
perf_review: 4.2
इसके बाद, सुरक्षा के ऐसे नियम जोड़े जा सकते हैं जिनमें दोनों कलेक्शन के लिए, ऐक्सेस के अलग-अलग लेवल हों. इस उदाहरण में, हम कस्टम ऑथ क्लेम का इस्तेमाल कर रहे हैं. इससे यह तय किया जा सकता है कि सिर्फ़ वे उपयोगकर्ता किसी कर्मचारी की वित्तीय जानकारी देख सकते हैं जिनके पास कस्टम ऑथ क्लेम role की वैल्यू Finance के बराबर है.
service cloud.firestore {
match /databases/{database}/documents {
// Allow any logged in user to view the public employee data
match /employees/{emp_id} {
allow read: if request.resource.auth != null
// Allow only users with the custom auth claim of "Finance" to view
// the employee's financial data
match /private/finances {
allow read: if request.resource.auth &&
request.resource.auth.token.role == 'Finance'
}
}
}
}
दस्तावेज़ बनाते समय फ़ील्ड पर पाबंदी लगाना
Rules में कोई स्कीमा नहीं होता. इसका मतलब है कि डेटाबेस लेवल पर इस बात की कोई पाबंदी नहीं होती कि किसी दस्तावेज़ में कौनसे फ़ील्ड शामिल हैं. इस सुविधा से डेवलपमेंट आसान हो सकता है. हालांकि, कभी-कभी आपको यह पक्का करना होगा कि क्लाइंट सिर्फ़ ऐसे दस्तावेज़ बना सकें जिनमें कुछ खास फ़ील्ड हों या जिनमें अन्य फ़ील्ड न हों.
request.resource.data ऑब्जेक्ट के keys तरीके की जांच करके, ये नियम बनाए जा सकते हैं. यह उन सभी फ़ील्ड की सूची है जिन्हें क्लाइंट इस नए दस्तावेज़ में लिखने की कोशिश कर रहा है. फ़ील्ड के इस सेट को hasOnly() या hasAny() जैसे फ़ंक्शन के साथ जोड़कर, ऐसा लॉजिक जोड़ा जा सकता है जो उपयोगकर्ता को नियमों में कुछ खास तरह के दस्तावेज़ जोड़ने से रोकता है.
नए दस्तावेज़ों में कुछ खास फ़ील्ड भरना ज़रूरी करना
मान लें कि आपको यह पक्का करना है कि restaurant कलेक्शन में बनाए गए सभी दस्तावेज़ों में कम से कम एक name, location, और city फ़ील्ड शामिल हो. इसके लिए, नए दस्तावेज़ में मौजूद कुंजियों की सूची पर hasAll() को कॉल किया जा सकता है.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document contains a name
// location, and city field
match /restaurant/{restId} {
allow create: if request.resource.data.keys().hasAll(['name', 'location', 'city']);
}
}
}
इससे रेस्टोरेंट को अन्य फ़ील्ड के साथ भी बनाया जा सकता है. हालांकि, यह पक्का होता है कि क्लाइंट के बनाए गए सभी दस्तावेज़ों में कम से कम ये तीन फ़ील्ड शामिल हों.
नए दस्तावेज़ों में कुछ फ़ील्ड को प्रतिबंधित करना
इसी तरह, क्लाइंट को ऐसे दस्तावेज़ बनाने से रोका जा सकता है जिनमें कुछ खास फ़ील्ड शामिल हों. इसके लिए, प्रतिबंधित फ़ील्ड की सूची के लिए hasAny() का इस्तेमाल करें. अगर किसी दस्तावेज़ में इनमें से कोई भी फ़ील्ड मौजूद है, तो यह तरीका true वैल्यू देता है. इसलिए, कुछ फ़ील्ड को प्रतिबंधित करने के लिए, आपको नतीजे को नकारना पड़ सकता है.
उदाहरण के लिए, नीचे दिए गए उदाहरण में क्लाइंट को ऐसा दस्तावेज़ बनाने की अनुमति नहीं है जिसमें average_score या rating_count फ़ील्ड शामिल हो. ऐसा इसलिए, क्योंकि ये फ़ील्ड बाद में सर्वर कॉल से जोड़े जाएंगे.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document does *not*
// contain an average_score or rating_count field.
match /restaurant/{restId} {
allow create: if (!request.resource.data.keys().hasAny(
['average_score', 'rating_count']));
}
}
}
नए दस्तावेज़ों के लिए, अनुमति वाली सूची में फ़ील्ड जोड़ना
नए दस्तावेज़ों में कुछ फ़ील्ड को प्रतिबंधित करने के बजाय, सिर्फ़ उन फ़ील्ड की सूची बनाई जा सकती है जिन्हें नए दस्तावेज़ों में इस्तेमाल करने की अनुमति है. इसके बाद, hasOnly() फ़ंक्शन का इस्तेमाल करके यह पक्का किया जा सकता है कि बनाए गए किसी भी नए दस्तावेज़ में सिर्फ़ ये फ़ील्ड (या इन फ़ील्ड का सबसेट) शामिल हों, कोई और नहीं.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document doesn't contain
// any fields besides the ones listed below.
match /restaurant/{restId} {
allow create: if (request.resource.data.keys().hasOnly(
['name', 'location', 'city', 'address', 'hours', 'cuisine']));
}
}
}
ज़रूरी और वैकल्पिक फ़ील्ड को जोड़ना
सुरक्षा के नियमों में, hasAll और hasOnly ऑपरेशन को एक साथ जोड़ा जा सकता है. इससे कुछ फ़ील्ड को ज़रूरी बनाया जा सकता है और कुछ को अनुमति दी जा सकती है. उदाहरण के लिए, इस उदाहरण में यह ज़रूरी है कि सभी नए दस्तावेज़ों में name, location, और city फ़ील्ड शामिल हों. साथ ही, address, hours, और cuisine फ़ील्ड को शामिल करने का विकल्प भी दिया गया है.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document has a name,
// location, and city field, and optionally address, hours, or cuisine field
match /restaurant/{restId} {
allow create: if (request.resource.data.keys().hasAll(['name', 'location', 'city'])) &&
(request.resource.data.keys().hasOnly(
['name', 'location', 'city', 'address', 'hours', 'cuisine']));
}
}
}
असल दुनिया में, हो सकता है कि आप इस लॉजिक को हेल्पर फ़ंक्शन में ले जाना चाहें, ताकि आपके कोड का डुप्लीकेट न बने. साथ ही, ज़रूरी और वैकल्पिक फ़ील्ड को एक ही सूची में आसानी से जोड़ा जा सके. जैसे:
service cloud.firestore {
match /databases/{database}/documents {
function verifyFields(required, optional) {
let allAllowedFields = required.concat(optional);
return request.resource.data.keys().hasAll(required) &&
request.resource.data.keys().hasOnly(allAllowedFields);
}
match /restaurant/{restId} {
allow create: if verifyFields(['name', 'location', 'city'],
['address', 'hours', 'cuisine']);
}
}
}
अपडेट करने पर फ़ील्ड पर पाबंदी लगाना
सुरक्षा के लिहाज़ से, क्लाइंट को सिर्फ़ कुछ फ़ील्ड में बदलाव करने की अनुमति दी जाती है. सिर्फ़ पिछले सेक्शन में बताई गई request.resource.data.keys() सूची को देखकर, ऐसा नहीं किया जा सकता. इसकी वजह यह है कि इस सूची में पूरा दस्तावेज़ शामिल होता है, जैसा कि वह अपडेट के बाद दिखेगा. इसलिए, इसमें ऐसे फ़ील्ड भी शामिल होंगे जिनमें क्लाइंट ने कोई बदलाव नहीं किया है.
हालांकि, diff() फ़ंक्शन का इस्तेमाल करके, request.resource.data की तुलना resource.data ऑब्जेक्ट से की जा सकती है. यह ऑब्जेक्ट, अपडेट से पहले डेटाबेस में मौजूद दस्तावेज़ को दिखाता है. इससे एक mapDiff ऑब्जेक्ट बनता है. यह एक ऐसा ऑब्जेक्ट होता है जिसमें दो अलग-अलग मैप के बीच हुए सभी बदलाव शामिल होते हैं.
इस mapDiff पर affectedKeys() तरीके को कॉल करके, उन फ़ील्ड का सेट बनाया जा सकता है जिनमें बदलाव किया गया था. इसके बाद, hasOnly() या hasAny() जैसे फ़ंक्शन का इस्तेमाल करके, यह पक्का किया जा सकता है कि इस सेट में कुछ आइटम शामिल हैं या नहीं.
कुछ फ़ील्ड में बदलाव करने से रोकना
affectedKeys() से जनरेट किए गए सेट पर hasAny() तरीके का इस्तेमाल करके और फिर नतीजे को अस्वीकार करके, क्लाइंट के ऐसे किसी भी अनुरोध को अस्वीकार किया जा सकता है जो उन फ़ील्ड को बदलने की कोशिश करता है जिन्हें आपको नहीं बदलना है.
उदाहरण के लिए, हो सकता है कि आप क्लाइंट को किसी रेस्टोरेंट की जानकारी अपडेट करने की अनुमति देना चाहें, लेकिन उसके औसत स्कोर या समीक्षाओं की संख्या में बदलाव करने की अनुमति न देना चाहें.
service cloud.firestore {
match /databases/{database}/documents {
match /restaurant/{restId} {
// Allow the client to update a document only if that document doesn't
// change the average_score or rating_count fields
allow update: if (!request.resource.data.diff(resource.data).affectedKeys()
.hasAny(['average_score', 'rating_count']));
}
}
}
सिर्फ़ कुछ फ़ील्ड में बदलाव करने की अनुमति देना
जिन फ़ील्ड में बदलाव नहीं करना है उन्हें बताने के बजाय, hasOnly() फ़ंक्शन का इस्तेमाल करके उन फ़ील्ड की सूची भी बनाई जा सकती है जिनमें आपको बदलाव करना है. आम तौर पर, इसे ज़्यादा सुरक्षित माना जाता है. ऐसा इसलिए, क्योंकि किसी भी नए दस्तावेज़ के फ़ील्ड में डेटा लिखने की अनुमति डिफ़ॉल्ट रूप से नहीं होती. इसके लिए, आपको सुरक्षा के नियमों में जाकर, साफ़ तौर पर अनुमति देनी होगी.
उदाहरण के लिए, average_score और rating_count फ़ील्ड को अनुमति न देने के बजाय, ऐसे सुरक्षा नियम बनाए जा सकते हैं जो क्लाइंट को सिर्फ़ name, location, city, address, hours, और cuisine फ़ील्ड में बदलाव करने की अनुमति दें.
service cloud.firestore {
match /databases/{database}/documents {
match /restaurant/{restId} {
// Allow a client to update only these 6 fields in a document
allow update: if (request.resource.data.diff(resource.data).affectedKeys()
.hasOnly(['name', 'location', 'city', 'address', 'hours', 'cuisine']));
}
}
}
इसका मतलब है कि अगर आने वाले समय में आपके ऐप्लिकेशन के किसी वर्शन में, रेस्टोरेंट के दस्तावेज़ों में telephone फ़ील्ड शामिल किया जाता है, तो उस फ़ील्ड में तब तक बदलाव नहीं किया जा सकेगा, जब तक आप वापस जाकर उस फ़ील्ड को सुरक्षा नियमों की hasOnly() सूची में नहीं जोड़ते.
फ़ील्ड टाइप लागू करना
नियमों के स्कीमालेस होने का एक और असर यह होता है कि डेटाबेस लेवल पर यह लागू नहीं होता कि किसी खास फ़ील्ड में किस तरह का डेटा सेव किया जा सकता है. इसे सुरक्षा के नियमों में लागू किया जा सकता है. हालांकि, इसके लिए is ऑपरेटर का इस्तेमाल करना होगा.
उदाहरण के लिए, यहां दिया गया सुरक्षा नियम यह लागू करता है कि समीक्षा के score फ़ील्ड में कोई इंटिजर होना चाहिए. साथ ही, headline, content, और author_name फ़ील्ड में स्ट्रिंग होनी चाहिए और review_date में टाइमस्टैंप होना चाहिए.
service cloud.firestore {
match /databases/{database}/documents {
match /restaurant/{restId} {
// Restaurant rules go here...
match /review/{reviewId} {
allow create: if (request.resource.data.score is int &&
request.resource.data.headline is string &&
request.resource.data.content is string &&
request.resource.data.author_name is string &&
request.resource.data.review_date is timestamp
);
}
}
}
}
is ऑपरेटर के लिए मान्य डेटा टाइप ये हैं: bool, bytes, float, int,
list, latlng, number, path, map, string, और timestamp. is ऑपरेटर, constraint, duration, set, और map_diff डेटा टाइप के साथ भी काम करता है. हालांकि, इन्हें सुरक्षा नियमों की भाषा से जनरेट किया जाता है, न कि क्लाइंट से. इसलिए, ज़्यादातर ऐप्लिकेशन में इनका इस्तेमाल बहुत कम किया जाता है.
list और map डेटा टाइप, जेनेरिक या टाइप आर्ग्युमेंट के साथ काम नहीं करते.
दूसरे शब्दों में, सुरक्षा के नियमों का इस्तेमाल करके यह लागू किया जा सकता है कि किसी फ़ील्ड में सूची या मैप शामिल हो. हालांकि, यह लागू नहीं किया जा सकता कि किसी फ़ील्ड में सभी पूर्णांकों या सभी स्ट्रिंग की सूची शामिल हो.
इसी तरह, सुरक्षा के नियमों का इस्तेमाल करके, सूची या मैप में मौजूद खास एंट्री के लिए टाइप वैल्यू लागू की जा सकती हैं. इसके लिए, ब्रैकेट नोटेशन या कुंजी के नामों का इस्तेमाल किया जाता है. हालांकि, मैप या सूची में मौजूद सभी सदस्यों के डेटा टाइप को एक साथ लागू करने का कोई शॉर्टकट नहीं है.
उदाहरण के लिए, यहां दिए गए नियमों से यह पक्का होता है कि किसी दस्तावेज़ में tags फ़ील्ड में एक सूची हो और पहली एंट्री एक स्ट्रिंग हो. यह यह भी पक्का करता है कि product फ़ील्ड में एक मैप हो, जिसमें प्रॉडक्ट का नाम हो, जो एक स्ट्रिंग हो और मात्रा एक पूर्णांक हो.
service cloud.firestore {
match /databases/{database}/documents {
match /orders/{orderId} {
allow create: if request.resource.data.tags is list &&
request.resource.data.tags[0] is string &&
request.resource.data.product is map &&
request.resource.data.product.name is string &&
request.resource.data.product.quantity is int
}
}
}
}
दस्तावेज़ बनाते और अपडेट करते समय, फ़ील्ड टाइप लागू करना ज़रूरी है. इसलिए, हमारा सुझाव है कि आप एक हेल्पर फ़ंक्शन बनाएं, जिसे सुरक्षा नियमों के 'बनाएं' और 'अपडेट करें', दोनों सेक्शन में कॉल किया जा सके.
service cloud.firestore {
match /databases/{database}/documents {
function reviewFieldsAreValidTypes(docData) {
return docData.score is int &&
docData.headline is string &&
docData.content is string &&
docData.author_name is string &&
docData.review_date is timestamp;
}
match /restaurant/{restId} {
// Restaurant rules go here...
match /review/{reviewId} {
allow create: if reviewFieldsAreValidTypes(request.resource.data) &&
// Other rules may go here
allow update: if reviewFieldsAreValidTypes(request.resource.data) &&
// Other rules may go here
}
}
}
}
वैकल्पिक फ़ील्ड के लिए टाइप लागू करना
यह याद रखना ज़रूरी है कि किसी ऐसे दस्तावेज़ पर request.resource.data.foo को कॉल करने से गड़बड़ी होती है जिसमें foo मौजूद नहीं है. इसलिए, उस कॉल को करने वाला कोई भी सुरक्षा नियम, अनुरोध को अस्वीकार कर देगा. request.resource.data पर get तरीके का इस्तेमाल करके, इस स्थिति को मैनेज किया जा सकता है. get तरीके का इस्तेमाल करके, मैप से वापस लाए जा रहे फ़ील्ड के लिए डिफ़ॉल्ट आर्ग्युमेंट दिया जा सकता है. ऐसा तब किया जा सकता है, जब वह फ़ील्ड मौजूद न हो.
उदाहरण के लिए, अगर समीक्षा वाले दस्तावेज़ों में वैकल्पिक photo_url फ़ील्ड और वैकल्पिक tags फ़ील्ड भी शामिल हैं, तो आपको पुष्टि करनी होगी कि वे स्ट्रिंग और सूचियां हैं. इसके लिए, reviewFieldsAreValidTypes फ़ंक्शन को फिर से लिखें. जैसे:
function reviewFieldsAreValidTypes(docData) {
return docData.score is int &&
docData.headline is string &&
docData.content is string &&
docData.author_name is string &&
docData.review_date is timestamp &&
docData.get('photo_url', '') is string &&
docData.get('tags', []) is list;
}
यह उन दस्तावेज़ों को अस्वीकार करता है जिनमें tags मौजूद है, लेकिन वह सूची नहीं है. हालांकि, यह उन दस्तावेज़ों को अनुमति देता है जिनमें tags (या photo_url) फ़ील्ड शामिल नहीं है.
अधूरे डेटा को लिखने की अनुमति कभी नहीं दी जाती
Cloud Firestore Security Rules के बारे में एक आखिरी बात यह है कि वे क्लाइंट को किसी दस्तावेज़ में बदलाव करने की अनुमति देते हैं या पूरे बदलाव को अस्वीकार कर देते हैं. ऐसे सुरक्षा नियम नहीं बनाए जा सकते जो आपके दस्तावेज़ के कुछ फ़ील्ड में डेटा लिखने की अनुमति देते हों, जबकि उसी कार्रवाई में अन्य फ़ील्ड में डेटा लिखने की अनुमति न देते हों.