1 अवलोकन
लक्ष्य
इस कोडलैब में आप स्विफ्ट में आईओएस पर एक फायरस्टार-समर्थित रेस्तरां सिफारिश ऐप बनाएंगे। आप जान जायेंगे कैसे:
- किसी iOS ऐप से Firestore में डेटा पढ़ें और लिखें
- रीयलटाइम में फायरस्टोर डेटा में परिवर्तन सुनें
- फायरस्टार डेटा को सुरक्षित करने के लिए फायरबेस प्रमाणीकरण और सुरक्षा नियमों का उपयोग करें
- जटिल फायरस्टार प्रश्न लिखें
आवश्यक शर्तें
इस कोडलैब को शुरू करने से पहले सुनिश्चित करें कि आपने इंस्टॉल किया है:
- Xcode संस्करण 13.0 (या उच्चतर)
- कोकोपोड्स 1.11.0 (या उच्चतर)
2. फायरबेस कंसोल प्रोजेक्ट बनाएं
प्रोजेक्ट में फायरबेस जोड़ें
- फायरबेस कंसोल पर जाएं।
- नया प्रोजेक्ट बनाएं चुनें और अपने प्रोजेक्ट का नाम "Firestore iOS Codelab" रखें।
3. नमूना परियोजना प्राप्त करें
कोड डाउनलोड करें
नमूना प्रोजेक्ट की क्लोनिंग और प्रोजेक्ट डायरेक्टरी में pod update
चलाकर शुरू करें:
git clone https://github.com/firebase/friendlyeats-ios cd friendlyeats-ios pod update
Xcode में FriendlyEats.xcworkspace
खोलें और इसे चलाएं (Cmd+R)। ऐप को सही ढंग से संकलित करना चाहिए और लॉन्च पर तुरंत क्रैश हो जाना चाहिए, क्योंकि इसमें GoogleService-Info.plist
फ़ाइल गुम है। हम इसे अगले चरण में ठीक कर देंगे।
फायरबेस सेट करें
एक नया फायरस्टार प्रोजेक्ट बनाने के लिए दस्तावेज़ीकरण का पालन करें। एक बार आपको अपना प्रोजेक्ट मिल जाने के बाद, अपने प्रोजेक्ट की GoogleService-Info.plist
फ़ाइल को Firebase कंसोल से डाउनलोड करें और इसे Xcode प्रोजेक्ट के रूट तक खींचें। यह सुनिश्चित करने के लिए प्रोजेक्ट को फिर से चलाएं कि ऐप सही तरीके से कॉन्फ़िगर हो और लॉन्च पर क्रैश न हो। लॉग इन करने के बाद, आपको नीचे दिए गए उदाहरण की तरह एक खाली स्क्रीन दिखनी चाहिए। यदि आप लॉग इन करने में असमर्थ हैं, तो सुनिश्चित करें कि आपने प्रमाणीकरण के तहत फायरबेस कंसोल में ईमेल/पासवर्ड साइन-इन विधि को सक्षम किया है।
4. फायरस्टोर को डेटा लिखें
इस सेक्शन में हम कुछ डेटा Firestore को लिखेंगे ताकि हम ऐप UI को पॉप्युलेट कर सकें। यह फायरबेस कंसोल के माध्यम से मैन्युअल रूप से किया जा सकता है, लेकिन हम इसे ऐप में ही एक बुनियादी फायरस्टार लेखन प्रदर्शित करने के लिए करेंगे।
हमारे ऐप में मुख्य मॉडल वस्तु एक रेस्तरां है। फायरस्टार डेटा दस्तावेजों, संग्रहों और उपसंग्रहों में विभाजित है। हम प्रत्येक रेस्तरां को restaurants
नामक एक शीर्ष-स्तरीय संग्रह में दस्तावेज़ के रूप में संग्रहीत करेंगे। अगर आप Firestore डेटा मॉडल के बारे में अधिक जानना चाहते हैं, तो दस्तावेज़ीकरण में दस्तावेज़ों और संग्रह के बारे में पढ़ें।
इससे पहले कि हम फायरस्टोर में डेटा जोड़ सकें, हमें रेस्तरां संग्रह का संदर्भ प्राप्त करना होगा। RestaurantsTableViewController.didTapPopulateButton(_:)
मेथड में इनर फॉर लूप में निम्नलिखित जोड़ें।
let collection = Firestore.firestore().collection("restaurants")
अब जब हमारे पास एक संग्रह संदर्भ है तो हम कुछ डेटा लिख सकते हैं। हमारे द्वारा जोड़े गए कोड की अंतिम पंक्ति के ठीक बाद निम्नलिखित जोड़ें:
let collection = Firestore.firestore().collection("restaurants")
// ====== ADD THIS ======
let restaurant = Restaurant(
name: name,
category: category,
city: city,
price: price,
ratingCount: 0,
averageRating: 0
)
collection.addDocument(data: restaurant.dictionary)
उपरोक्त कोड रेस्तरां संग्रह में एक नया दस्तावेज़ जोड़ता है। दस्तावेज़ डेटा एक शब्दकोश से आता है, जिसे हम एक रेस्तरां संरचना से प्राप्त करते हैं।
हम लगभग वहाँ हैं - इससे पहले कि हम फायरस्टोर को दस्तावेज़ लिख सकें, हमें फायरस्टोर के सुरक्षा नियमों को खोलना होगा और वर्णन करना होगा कि हमारे डेटाबेस के किन हिस्सों को किस उपयोगकर्ता द्वारा लिखने योग्य होना चाहिए। अभी के लिए, हम केवल प्रमाणीकृत उपयोगकर्ताओं को संपूर्ण डेटाबेस को पढ़ने और लिखने की अनुमति देंगे। यह एक प्रोडक्शन ऐप के लिए थोड़ा बहुत अनुमत है, लेकिन ऐप-बिल्डिंग प्रक्रिया के दौरान हम पर्याप्त आराम चाहते हैं, इसलिए हम प्रयोग करते समय लगातार प्रमाणीकरण मुद्दों में नहीं चलेंगे। इस कोडलैब के अंत में हम इस बारे में बात करेंगे कि आपके सुरक्षा नियमों को कैसे सख्त बनाया जाए और अनजाने में पढ़ने और लिखने की संभावना को सीमित किया जाए।
Firebase कंसोल के नियम टैब में निम्न नियम जोड़ें और फिर प्रकाशित करें पर क्लिक करें।
rules_version = '2'; 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; } } }
हम बाद में सुरक्षा नियमों के बारे में विस्तार से चर्चा करेंगे, लेकिन यदि आप जल्दी में हैं, तो सुरक्षा नियमों के दस्तावेज़ देखें।
ऐप चलाएँ और साइन इन करें। फिर ऊपरी बाएँ में " पॉप्युलेट " बटन पर टैप करें, जो रेस्तरां दस्तावेज़ों का एक बैच बनाएगा, हालाँकि आपको यह अभी ऐप में दिखाई नहीं देगा।
अगला, Firebase कंसोल में Firestore डेटा टैब पर नेविगेट करें। अब आपको रेस्तरां संग्रह में नई प्रविष्टियाँ देखनी चाहिए:
बधाई हो, आपने अभी-अभी iOS ऐप से Firestore को डेटा लिखा है! अगले भाग में आप सीखेंगे कि फायरस्टोर से डेटा कैसे प्राप्त करें और इसे ऐप में कैसे प्रदर्शित करें।
5. फायरस्टोर से डेटा प्रदर्शित करें
इस खंड में आप सीखेंगे कि फायरस्टोर से डेटा कैसे प्राप्त करें और इसे ऐप में कैसे प्रदर्शित करें। दो प्रमुख चरण एक क्वेरी बना रहे हैं और एक स्नैपशॉट श्रोता जोड़ रहे हैं। इस श्रोता को सभी मौजूदा डेटा के बारे में अधिसूचित किया जाएगा जो क्वेरी से मेल खाते हैं और वास्तविक समय में अपडेट प्राप्त करते हैं।
सबसे पहले, चलिए उस क्वेरी का निर्माण करते हैं जो रेस्तरां की डिफ़ॉल्ट, फ़िल्टर न की गई सूची प्रस्तुत करेगी। RestaurantsTableViewController.baseQuery()
के कार्यान्वयन पर एक नज़र डालें:
return Firestore.firestore().collection("restaurants").limit(to: 50)
यह क्वेरी "रेस्तरां" नामक शीर्ष-स्तरीय संग्रह के 50 रेस्तरां तक पुनः प्राप्त करती है। अब हमारे पास एक प्रश्न है, हमें अपने ऐप में फायरस्टोर से डेटा लोड करने के लिए एक स्नैपशॉट श्रोता संलग्न करना होगा। stopObserving()
को कॉल करने के तुरंत बाद RestaurantsTableViewController.observeQuery()
मेथड में निम्न कोड जोड़ें।
listener = query.addSnapshotListener { [unowned self] (snapshot, error) in
guard let snapshot = snapshot else {
print("Error fetching snapshot results: \(error!)")
return
}
let models = snapshot.documents.map { (document) -> Restaurant in
if let model = Restaurant(dictionary: document.data()) {
return model
} else {
// Don't use fatalError here in a real app.
fatalError("Unable to initialize type \(Restaurant.self) with dictionary \(document.data())")
}
}
self.restaurants = models
self.documents = snapshot.documents
if self.documents.count > 0 {
self.tableView.backgroundView = nil
} else {
self.tableView.backgroundView = self.backgroundView
}
self.tableView.reloadData()
}
उपरोक्त कोड फायरस्टार से संग्रह डाउनलोड करता है और इसे स्थानीय रूप से सरणी में संग्रहीत करता है। addSnapshotListener(_:)
कॉल क्वेरी में एक स्नैपशॉट श्रोता जोड़ता है जो हर बार सर्वर पर डेटा बदलने पर व्यू कंट्रोलर को अपडेट करेगा। हमें स्वचालित रूप से अपडेट मिलते हैं और परिवर्तनों को मैन्युअल रूप से पुश करने की आवश्यकता नहीं होती है। याद रखें, इस स्नैपशॉट श्रोता को किसी भी समय सर्वर-साइड परिवर्तन के परिणाम के रूप में लागू किया जा सकता है, इसलिए यह महत्वपूर्ण है कि हमारा ऐप परिवर्तनों को संभाल सके।
हमारे शब्दकोशों को स्ट्रक्चर्स में मैप करने के बाद (देखें Restaurant.swift
), डेटा प्रदर्शित करना केवल कुछ दृश्य गुणों को असाइन करने का मामला है। RestaurantsTableViewController.swift
में RestaurantTableViewCell.populate(restaurant:)
में निम्नलिखित पंक्तियां जोड़ें।
nameLabel.text = restaurant.name
cityLabel.text = restaurant.city
categoryLabel.text = restaurant.category
starsView.rating = Int(restaurant.averageRating.rounded())
priceLabel.text = priceString(from: restaurant.price)
यह पॉप्युलेट विधि तालिका दृश्य डेटा स्रोत की tableView(_:cellForRowAtIndexPath:)
विधि से कॉल की जाती है, जो पहले से अलग-अलग तालिका दृश्य कक्षों में मान प्रकारों के संग्रह को मैप करने का ख्याल रखती है।
ऐप को फिर से चलाएं और सत्यापित करें कि हमने पहले कंसोल में जो रेस्तरां देखे थे, वे अब सिम्युलेटर या डिवाइस पर दिखाई दे रहे हैं। यदि आपने इस अनुभाग को सफलतापूर्वक पूरा कर लिया है तो आपका ऐप अब क्लाउड फायरस्टोर के साथ डेटा पढ़ और लिख रहा है!
6. डेटा को छांटना और फ़िल्टर करना
वर्तमान में हमारा ऐप रेस्तरां की एक सूची प्रदर्शित करता है, लेकिन उपयोगकर्ता के पास अपनी आवश्यकताओं के आधार पर फ़िल्टर करने का कोई तरीका नहीं है। इस खंड में आप फ़िल्टरिंग को सक्षम करने के लिए फायरस्टोर की उन्नत क्वेरी का उपयोग करेंगे।
यहां सभी डिम सम रेस्तरां लाने के लिए एक सरल क्वेरी का उदाहरण दिया गया है:
let filteredQuery = query.whereField("category", isEqualTo: "Dim Sum")
जैसा कि इसके नाम से पता चलता है, whereField(_:isEqualTo:)
पद्धति हमारी क्वेरी को संग्रह के केवल उन सदस्यों को डाउनलोड करेगी जिनके क्षेत्र हमारे द्वारा निर्धारित प्रतिबंधों को पूरा करते हैं। इस मामले में, यह केवल उन्हीं रेस्तरां को डाउनलोड करेगा जिनकी category
"Dim Sum"
है।
इस ऐप में उपयोगकर्ता "सैन फ्रांसिस्को में पिज्जा" या "लोकप्रियता द्वारा ऑर्डर किए गए लॉस एंजिल्स में समुद्री भोजन" जैसे विशिष्ट प्रश्न बनाने के लिए कई फिल्टर की श्रृंखला बना सकता है।
RestaurantsTableViewController.swift
खोलें और निम्न कोड ब्लॉक को query(withCategory:city:price:sortBy:)
बीच में जोड़ें:
if let category = category, !category.isEmpty {
filtered = filtered.whereField("category", isEqualTo: category)
}
if let city = city, !city.isEmpty {
filtered = filtered.whereField("city", isEqualTo: city)
}
if let price = price {
filtered = filtered.whereField("price", isEqualTo: price)
}
if let sortBy = sortBy, !sortBy.isEmpty {
filtered = filtered.order(by: sortBy)
}
उपरोक्त स्निपेट उपयोगकर्ता इनपुट के आधार पर एकल कंपाउंड क्वेरी बनाने के लिए एकाधिक whereField
और order
क्लॉज जोड़ता है। अब हमारी क्वेरी केवल उन रेस्तरां को वापस करेगी जो उपयोगकर्ता की आवश्यकताओं से मेल खाते हैं।
अपना प्रोजेक्ट चलाएं और सत्यापित करें कि आप मूल्य, शहर और श्रेणी के आधार पर फ़िल्टर कर सकते हैं (श्रेणी और शहर के नाम बिल्कुल टाइप करना सुनिश्चित करें)। परीक्षण करते समय आपको अपने लॉग में ऐसी त्रुटियाँ दिखाई दे सकती हैं जो इस प्रकार दिखाई देती हैं:
Error fetching snapshot results: Error Domain=io.grpc Code=9 "The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_composite=..." UserInfo={NSLocalizedDescription=The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_composite=...}
ऐसा इसलिए है क्योंकि फायरस्टार को अधिकांश यौगिक प्रश्नों के लिए अनुक्रमणिका की आवश्यकता होती है। प्रश्नों पर अनुक्रमणिका की आवश्यकता होने से फायरस्टोर तेजी से बड़े पैमाने पर रहता है। त्रुटि संदेश से लिंक खोलने से स्वचालित रूप से फायरबेस कंसोल में इंडेक्स क्रिएशन यूआई खुल जाएगा, जिसमें सही पैरामीटर भरे होंगे। फायरस्टोर में इंडेक्स के बारे में अधिक जानने के लिए, दस्तावेज़ीकरण पर जाएं ।
7. लेन-देन में डेटा लिखना
इस अनुभाग में, हम उपयोगकर्ताओं के लिए रेस्तरां में समीक्षाएँ सबमिट करने की क्षमता जोड़ेंगे। अब तक, हमारे सभी लेखन परमाणु और अपेक्षाकृत सरल रहे हैं। यदि उनमें से कोई त्रुटि है, तो हम संभवतः उपयोगकर्ता को उन्हें फिर से प्रयास करने या स्वचालित रूप से पुनः प्रयास करने का संकेत देंगे।
एक रेस्तरां में रेटिंग जोड़ने के लिए हमें कई रीड्स और राइट्स को समन्वित करने की आवश्यकता होती है। पहले स्वयं समीक्षा सबमिट करनी होगी, और फिर रेस्तरां की रेटिंग संख्या और औसत रेटिंग को अपडेट करने की आवश्यकता होगी। यदि इनमें से एक विफल हो जाता है लेकिन दूसरा नहीं, तो हम एक असंगत स्थिति में रह जाते हैं जहां हमारे डेटाबेस के एक हिस्से का डेटा दूसरे के डेटा से मेल नहीं खाता है।
सौभाग्य से, फायरस्टार लेनदेन की कार्यक्षमता प्रदान करता है जो हमें एक एकल परमाणु ऑपरेशन में कई पढ़ने और लिखने देता है, यह सुनिश्चित करता है कि हमारा डेटा सुसंगत रहे।
RestaurantDetailViewController.reviewController(_:didSubmitFormWithReview:)
में सभी घोषणाओं के नीचे निम्नलिखित कोड जोड़ें।
let firestore = Firestore.firestore()
firestore.runTransaction({ (transaction, errorPointer) -> Any? in
// Read data from Firestore inside the transaction, so we don't accidentally
// update using stale client data. Error if we're unable to read here.
let restaurantSnapshot: DocumentSnapshot
do {
try restaurantSnapshot = transaction.getDocument(reference)
} catch let error as NSError {
errorPointer?.pointee = error
return nil
}
// Error if the restaurant data in Firestore has somehow changed or is malformed.
guard let data = restaurantSnapshot.data(),
let restaurant = Restaurant(dictionary: data) else {
let error = NSError(domain: "FireEatsErrorDomain", code: 0, userInfo: [
NSLocalizedDescriptionKey: "Unable to write to restaurant at Firestore path: \(reference.path)"
])
errorPointer?.pointee = error
return nil
}
// Update the restaurant's rating and rating count and post the new review at the
// same time.
let newAverage = (Float(restaurant.ratingCount) * restaurant.averageRating + Float(review.rating))
/ Float(restaurant.ratingCount + 1)
transaction.setData(review.dictionary, forDocument: newReviewReference)
transaction.updateData([
"numRatings": restaurant.ratingCount + 1,
"avgRating": newAverage
], forDocument: reference)
return nil
}) { (object, error) in
if let error = error {
print(error)
} else {
// Pop the review controller on success
if self.navigationController?.topViewController?.isKind(of: NewReviewViewController.self) ?? false {
self.navigationController?.popViewController(animated: true)
}
}
}
अपडेट ब्लॉक के अंदर, ट्रांजैक्शन ऑब्जेक्ट का उपयोग करके हम जो भी ऑपरेशन करते हैं, उन्हें फायरस्टोर द्वारा एकल परमाणु अपडेट के रूप में माना जाएगा। यदि सर्वर पर अपडेट विफल हो जाता है, तो फायरस्टार स्वचालित रूप से इसे कुछ बार पुनः प्रयास करेगा। इसका मतलब यह है कि हमारी त्रुटि की स्थिति सबसे अधिक बार होने वाली एक त्रुटि है, उदाहरण के लिए यदि डिवाइस पूरी तरह से ऑफ़लाइन है या उपयोगकर्ता उस पथ पर लिखने के लिए अधिकृत नहीं है जिस पर वे लिखने का प्रयास कर रहे हैं।
8. सुरक्षा नियम
हमारे ऐप के उपयोगकर्ता हमारे डेटाबेस में डेटा के प्रत्येक भाग को पढ़ने और लिखने में सक्षम नहीं होने चाहिए। उदाहरण के लिए सभी को रेस्तरां की रेटिंग देखने में सक्षम होना चाहिए, लेकिन केवल एक प्रमाणित उपयोगकर्ता को ही रेटिंग पोस्ट करने की अनुमति दी जानी चाहिए। क्लाइंट पर अच्छा कोड लिखना पर्याप्त नहीं है, हमें पूरी तरह से सुरक्षित होने के लिए बैकएंड पर अपने डेटा सुरक्षा मॉडल को निर्दिष्ट करने की आवश्यकता है। इस अनुभाग में हम सीखेंगे कि अपने डेटा की सुरक्षा के लिए फायरबेस सुरक्षा नियमों का उपयोग कैसे करें।
सबसे पहले, कोडलैब की शुरुआत में हमने जो सुरक्षा नियम लिखे थे, उन पर गहराई से नज़र डालते हैं। फायरबेस कंसोल खोलें और फायरस्टार टैब में डेटाबेस > रूल्स पर नेविगेट करें।
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
// Only authenticated users can read or write data
allow read, write: if request.auth != null;
}
}
}
उपरोक्त नियमों में request
चर सभी नियमों में उपलब्ध एक वैश्विक चर है, और हमने जो सशर्त जोड़ा है वह सुनिश्चित करता है कि उपयोगकर्ताओं को कुछ भी करने की अनुमति देने से पहले अनुरोध को प्रमाणित किया गया है। यह अप्रमाणित उपयोगकर्ताओं को आपके डेटा में अनधिकृत परिवर्तन करने के लिए Firestore API का उपयोग करने से रोकता है। यह एक अच्छी शुरुआत है, लेकिन हम अधिक शक्तिशाली चीजें करने के लिए फायरस्टोर नियमों का उपयोग कर सकते हैं।
आइए समीक्षा लेखन को प्रतिबंधित करते हैं ताकि समीक्षा की उपयोगकर्ता आईडी प्रमाणित उपयोगकर्ता की आईडी से मेल खाना चाहिए। यह सुनिश्चित करता है कि उपयोगकर्ता एक-दूसरे का प्रतिरूपण नहीं कर सकते हैं और कपटपूर्ण समीक्षाएं नहीं छोड़ सकते हैं। अपने सुरक्षा नियमों को निम्नलिखित से बदलें:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /restaurants/{any}/ratings/{rating} {
// Users can only write ratings with their user ID
allow read;
allow write: if request.auth != null
&& request.auth.uid == request.resource.data.userId;
}
match /restaurants/{any} {
// Only authenticated users can read or write data
allow read, write: if request.auth != null;
}
}
}
पहला मिलान विवरण restaurants
संग्रह से संबंधित किसी भी दस्तावेज़ के ratings
नाम के उपसंग्रह से मेल खाता है। यदि समीक्षा की उपयोगकर्ता आईडी उपयोगकर्ता की उपयोगकर्ता आईडी से मेल नहीं खाती है तो allow write
सशर्त तब किसी भी समीक्षा को सबमिट होने से रोकती है। दूसरा मैच स्टेटमेंट किसी भी प्रमाणित उपयोगकर्ता को डेटाबेस में रेस्तरां पढ़ने और लिखने की अनुमति देता है।
यह हमारी समीक्षाओं के लिए वास्तव में अच्छी तरह से काम करता है, क्योंकि हमने सुरक्षा नियमों का उपयोग स्पष्ट रूप से उस अंतर्निहित गारंटी को बताने के लिए किया है जिसे हमने अपने ऐप में पहले लिखा था- कि उपयोगकर्ता केवल अपनी समीक्षा ही लिख सकते हैं। यदि हम समीक्षाओं के लिए संपादन या हटाने का कार्य जोड़ते हैं, तो नियमों का ठीक यही सेट उपयोगकर्ताओं को अन्य उपयोगकर्ताओं की समीक्षाओं को संशोधित करने या हटाने से भी रोकेगा। लेकिन फायरस्टोर नियमों का उपयोग अधिक व्यापक रूप से दस्तावेजों के भीतर अलग-अलग क्षेत्रों पर लिखने को सीमित करने के लिए किया जा सकता है, बजाय पूरे दस्तावेजों के। हम इसका उपयोग उपयोगकर्ताओं को रेस्तरां के लिए केवल रेटिंग, औसत रेटिंग और रेटिंग की संख्या को अपडेट करने की अनुमति देने के लिए कर सकते हैं, जिससे किसी दुर्भावनापूर्ण उपयोगकर्ता द्वारा रेस्तरां का नाम या स्थान बदलने की संभावना समाप्त हो जाती है।
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /restaurants/{restaurant} {
match /ratings/{rating} {
allow read: if request.auth != null;
allow write: if request.auth != null
&& request.auth.uid == request.resource.data.userId;
}
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if request.auth != null
&& request.resource.data.name == resource.data.name
&& request.resource.data.city == resource.data.city
&& request.resource.data.price == resource.data.price
&& request.resource.data.category == resource.data.category;
}
}
}
यहां हमने अपनी लिखने की अनुमति को क्रिएट और अपडेट में विभाजित किया है ताकि हम इस बारे में अधिक विशिष्ट हो सकें कि किन कार्यों की अनुमति दी जानी चाहिए। कोई भी उपयोगकर्ता कोडलैब की शुरुआत में हमारे द्वारा बनाए गए पॉप्युलेट बटन की कार्यक्षमता को संरक्षित करते हुए, डेटाबेस में रेस्तरां लिख सकता है, लेकिन एक बार एक रेस्तरां लिखे जाने के बाद उसका नाम, स्थान, मूल्य और श्रेणी नहीं बदली जा सकती। अधिक विशेष रूप से, अंतिम नियम के लिए डेटाबेस में पहले से मौजूद फ़ील्ड के समान नाम, शहर, मूल्य और श्रेणी को बनाए रखने के लिए किसी भी रेस्तरां अपडेट ऑपरेशन की आवश्यकता होती है।
इस बारे में अधिक जानने के लिए कि आप सुरक्षा नियमों के साथ क्या कर सकते हैं, दस्तावेज़ देखें।
9. निष्कर्ष
इस कोडलैब में, आपने फायरस्टोर के साथ बुनियादी और उन्नत पढ़ने और लिखने के साथ-साथ सुरक्षा नियमों के साथ डेटा एक्सेस को सुरक्षित करने का तरीका सीखा। आप codelab-complete
शाखा पर पूरा समाधान पा सकते हैं।
फायरस्टोर के बारे में अधिक जानने के लिए, निम्नलिखित संसाधनों पर जाएँ:
1 अवलोकन
लक्ष्य
इस कोडलैब में आप स्विफ्ट में आईओएस पर एक फायरस्टार-समर्थित रेस्तरां सिफारिश ऐप बनाएंगे। आप जान जायेंगे कैसे:
- किसी iOS ऐप से Firestore में डेटा पढ़ें और लिखें
- रीयलटाइम में फायरस्टोर डेटा में परिवर्तन सुनें
- फायरस्टार डेटा को सुरक्षित करने के लिए फायरबेस प्रमाणीकरण और सुरक्षा नियमों का उपयोग करें
- जटिल फायरस्टार प्रश्न लिखें
आवश्यक शर्तें
इस कोडलैब को शुरू करने से पहले सुनिश्चित करें कि आपने इंस्टॉल किया है:
- Xcode संस्करण 13.0 (या उच्चतर)
- कोकोपोड्स 1.11.0 (या उच्चतर)
2. फायरबेस कंसोल प्रोजेक्ट बनाएं
प्रोजेक्ट में फायरबेस जोड़ें
- फायरबेस कंसोल पर जाएं।
- नया प्रोजेक्ट बनाएं चुनें और अपने प्रोजेक्ट का नाम "Firestore iOS Codelab" रखें।
3. नमूना परियोजना प्राप्त करें
कोड डाउनलोड करें
नमूना प्रोजेक्ट की क्लोनिंग और प्रोजेक्ट डायरेक्टरी में pod update
चलाकर शुरू करें:
git clone https://github.com/firebase/friendlyeats-ios cd friendlyeats-ios pod update
Xcode में FriendlyEats.xcworkspace
खोलें और इसे चलाएं (Cmd+R)। ऐप को सही ढंग से संकलित करना चाहिए और लॉन्च पर तुरंत क्रैश हो जाना चाहिए, क्योंकि इसमें GoogleService-Info.plist
फ़ाइल गुम है। हम इसे अगले चरण में ठीक कर देंगे।
फायरबेस सेट करें
एक नया फायरस्टार प्रोजेक्ट बनाने के लिए दस्तावेज़ीकरण का पालन करें। एक बार आपको अपना प्रोजेक्ट मिल जाने के बाद, अपने प्रोजेक्ट की GoogleService-Info.plist
फ़ाइल को Firebase कंसोल से डाउनलोड करें और इसे Xcode प्रोजेक्ट के रूट तक खींचें। यह सुनिश्चित करने के लिए प्रोजेक्ट को फिर से चलाएं कि ऐप सही तरीके से कॉन्फ़िगर हो और लॉन्च पर क्रैश न हो। लॉग इन करने के बाद, आपको नीचे दिए गए उदाहरण की तरह एक खाली स्क्रीन दिखनी चाहिए। यदि आप लॉग इन करने में असमर्थ हैं, तो सुनिश्चित करें कि आपने प्रमाणीकरण के तहत फायरबेस कंसोल में ईमेल/पासवर्ड साइन-इन विधि को सक्षम किया है।
4. फायरस्टोर को डेटा लिखें
इस सेक्शन में हम कुछ डेटा Firestore को लिखेंगे ताकि हम ऐप UI को पॉप्युलेट कर सकें। यह फायरबेस कंसोल के माध्यम से मैन्युअल रूप से किया जा सकता है, लेकिन हम इसे ऐप में ही एक बुनियादी फायरस्टार लेखन प्रदर्शित करने के लिए करेंगे।
हमारे ऐप में मुख्य मॉडल वस्तु एक रेस्तरां है। फायरस्टार डेटा दस्तावेजों, संग्रहों और उपसंग्रहों में विभाजित है। हम प्रत्येक रेस्तरां को restaurants
नामक एक शीर्ष-स्तरीय संग्रह में दस्तावेज़ के रूप में संग्रहीत करेंगे। अगर आप Firestore डेटा मॉडल के बारे में अधिक जानना चाहते हैं, तो दस्तावेज़ीकरण में दस्तावेज़ों और संग्रह के बारे में पढ़ें।
इससे पहले कि हम फायरस्टोर में डेटा जोड़ सकें, हमें रेस्तरां संग्रह का संदर्भ प्राप्त करना होगा। RestaurantsTableViewController.didTapPopulateButton(_:)
मेथड में इनर फॉर लूप में निम्नलिखित जोड़ें।
let collection = Firestore.firestore().collection("restaurants")
अब जब हमारे पास एक संग्रह संदर्भ है तो हम कुछ डेटा लिख सकते हैं। हमारे द्वारा जोड़े गए कोड की अंतिम पंक्ति के ठीक बाद निम्नलिखित जोड़ें:
let collection = Firestore.firestore().collection("restaurants")
// ====== ADD THIS ======
let restaurant = Restaurant(
name: name,
category: category,
city: city,
price: price,
ratingCount: 0,
averageRating: 0
)
collection.addDocument(data: restaurant.dictionary)
उपरोक्त कोड रेस्तरां संग्रह में एक नया दस्तावेज़ जोड़ता है। दस्तावेज़ डेटा एक शब्दकोश से आता है, जिसे हम एक रेस्तरां संरचना से प्राप्त करते हैं।
हम लगभग वहाँ हैं - इससे पहले कि हम फायरस्टोर को दस्तावेज़ लिख सकें, हमें फायरस्टोर के सुरक्षा नियमों को खोलना होगा और वर्णन करना होगा कि हमारे डेटाबेस के किन हिस्सों को किस उपयोगकर्ता द्वारा लिखने योग्य होना चाहिए। अभी के लिए, हम केवल प्रमाणीकृत उपयोगकर्ताओं को संपूर्ण डेटाबेस को पढ़ने और लिखने की अनुमति देंगे। यह एक प्रोडक्शन ऐप के लिए थोड़ा बहुत अनुमत है, लेकिन ऐप-बिल्डिंग प्रक्रिया के दौरान हम पर्याप्त आराम चाहते हैं, इसलिए हम प्रयोग करते समय लगातार प्रमाणीकरण मुद्दों में नहीं चलेंगे। इस कोडलैब के अंत में हम इस बारे में बात करेंगे कि आपके सुरक्षा नियमों को कैसे सख्त बनाया जाए और अनजाने में पढ़ने और लिखने की संभावना को सीमित किया जाए।
Firebase कंसोल के नियम टैब में निम्न नियम जोड़ें और फिर प्रकाशित करें पर क्लिक करें।
rules_version = '2'; 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; } } }
हम बाद में सुरक्षा नियमों के बारे में विस्तार से चर्चा करेंगे, लेकिन यदि आप जल्दी में हैं, तो सुरक्षा नियमों के दस्तावेज़ देखें।
ऐप चलाएँ और साइन इन करें। फिर ऊपरी बाएँ में " पॉप्युलेट " बटन पर टैप करें, जो रेस्तरां दस्तावेज़ों का एक बैच बनाएगा, हालाँकि आपको यह अभी ऐप में दिखाई नहीं देगा।
अगला, Firebase कंसोल में Firestore डेटा टैब पर नेविगेट करें। अब आपको रेस्तरां संग्रह में नई प्रविष्टियाँ देखनी चाहिए:
बधाई हो, आपने अभी-अभी iOS ऐप से Firestore को डेटा लिखा है! अगले भाग में आप सीखेंगे कि फायरस्टोर से डेटा कैसे प्राप्त करें और इसे ऐप में कैसे प्रदर्शित करें।
5. फायरस्टोर से डेटा प्रदर्शित करें
इस खंड में आप सीखेंगे कि फायरस्टोर से डेटा कैसे प्राप्त करें और इसे ऐप में कैसे प्रदर्शित करें। दो प्रमुख चरण एक क्वेरी बना रहे हैं और एक स्नैपशॉट श्रोता जोड़ रहे हैं। इस श्रोता को सभी मौजूदा डेटा के बारे में अधिसूचित किया जाएगा जो क्वेरी से मेल खाते हैं और वास्तविक समय में अपडेट प्राप्त करते हैं।
सबसे पहले, चलिए उस क्वेरी का निर्माण करते हैं जो रेस्तरां की डिफ़ॉल्ट, फ़िल्टर न की गई सूची प्रस्तुत करेगी। RestaurantsTableViewController.baseQuery()
के कार्यान्वयन पर एक नज़र डालें:
return Firestore.firestore().collection("restaurants").limit(to: 50)
यह क्वेरी "रेस्तरां" नामक शीर्ष-स्तरीय संग्रह के 50 रेस्तरां तक पुनः प्राप्त करती है। अब हमारे पास एक प्रश्न है, हमें अपने ऐप में फायरस्टोर से डेटा लोड करने के लिए एक स्नैपशॉट श्रोता संलग्न करना होगा। stopObserving()
को कॉल करने के तुरंत बाद RestaurantsTableViewController.observeQuery()
मेथड में निम्न कोड जोड़ें।
listener = query.addSnapshotListener { [unowned self] (snapshot, error) in
guard let snapshot = snapshot else {
print("Error fetching snapshot results: \(error!)")
return
}
let models = snapshot.documents.map { (document) -> Restaurant in
if let model = Restaurant(dictionary: document.data()) {
return model
} else {
// Don't use fatalError here in a real app.
fatalError("Unable to initialize type \(Restaurant.self) with dictionary \(document.data())")
}
}
self.restaurants = models
self.documents = snapshot.documents
if self.documents.count > 0 {
self.tableView.backgroundView = nil
} else {
self.tableView.backgroundView = self.backgroundView
}
self.tableView.reloadData()
}
उपरोक्त कोड फायरस्टार से संग्रह डाउनलोड करता है और इसे स्थानीय रूप से सरणी में संग्रहीत करता है। addSnapshotListener(_:)
कॉल क्वेरी में एक स्नैपशॉट श्रोता जोड़ता है जो हर बार सर्वर पर डेटा बदलने पर व्यू कंट्रोलर को अपडेट करेगा। हमें स्वचालित रूप से अपडेट मिलते हैं और परिवर्तनों को मैन्युअल रूप से पुश करने की आवश्यकता नहीं होती है। याद रखें, इस स्नैपशॉट श्रोता को किसी भी समय सर्वर-साइड परिवर्तन के परिणाम के रूप में लागू किया जा सकता है, इसलिए यह महत्वपूर्ण है कि हमारा ऐप परिवर्तनों को संभाल सके।
हमारे शब्दकोशों को स्ट्रक्चर्स में मैप करने के बाद (देखें Restaurant.swift
), डेटा प्रदर्शित करना केवल कुछ दृश्य गुणों को असाइन करने का मामला है। RestaurantsTableViewController.swift
में RestaurantTableViewCell.populate(restaurant:)
में निम्नलिखित पंक्तियां जोड़ें।
nameLabel.text = restaurant.name
cityLabel.text = restaurant.city
categoryLabel.text = restaurant.category
starsView.rating = Int(restaurant.averageRating.rounded())
priceLabel.text = priceString(from: restaurant.price)
यह पॉप्युलेट विधि तालिका दृश्य डेटा स्रोत की tableView(_:cellForRowAtIndexPath:)
विधि से कॉल की जाती है, जो पहले से अलग-अलग तालिका दृश्य कक्षों में मान प्रकारों के संग्रह को मैप करने का ख्याल रखती है।
ऐप को फिर से चलाएं और सत्यापित करें कि हमने पहले कंसोल में जो रेस्तरां देखे थे, वे अब सिम्युलेटर या डिवाइस पर दिखाई दे रहे हैं। यदि आपने इस अनुभाग को सफलतापूर्वक पूरा कर लिया है तो आपका ऐप अब क्लाउड फायरस्टोर के साथ डेटा पढ़ और लिख रहा है!
6. डेटा को छांटना और फ़िल्टर करना
वर्तमान में हमारा ऐप रेस्तरां की एक सूची प्रदर्शित करता है, लेकिन उपयोगकर्ता के पास अपनी आवश्यकताओं के आधार पर फ़िल्टर करने का कोई तरीका नहीं है। इस खंड में आप फ़िल्टरिंग को सक्षम करने के लिए फायरस्टोर की उन्नत क्वेरी का उपयोग करेंगे।
यहां सभी डिम सम रेस्तरां लाने के लिए एक सरल क्वेरी का उदाहरण दिया गया है:
let filteredQuery = query.whereField("category", isEqualTo: "Dim Sum")
जैसा कि इसके नाम से पता चलता है, whereField(_:isEqualTo:)
पद्धति हमारी क्वेरी को संग्रह के केवल उन सदस्यों को डाउनलोड करेगी जिनके क्षेत्र हमारे द्वारा निर्धारित प्रतिबंधों को पूरा करते हैं। इस मामले में, यह केवल उन्हीं रेस्तरां को डाउनलोड करेगा जिनकी category
"Dim Sum"
है।
इस ऐप में उपयोगकर्ता "सैन फ्रांसिस्को में पिज्जा" या "लोकप्रियता द्वारा ऑर्डर किए गए लॉस एंजिल्स में समुद्री भोजन" जैसे विशिष्ट प्रश्न बनाने के लिए कई फिल्टर की श्रृंखला बना सकता है।
RestaurantsTableViewController.swift
खोलें और निम्न कोड ब्लॉक को query(withCategory:city:price:sortBy:)
बीच में जोड़ें:
if let category = category, !category.isEmpty {
filtered = filtered.whereField("category", isEqualTo: category)
}
if let city = city, !city.isEmpty {
filtered = filtered.whereField("city", isEqualTo: city)
}
if let price = price {
filtered = filtered.whereField("price", isEqualTo: price)
}
if let sortBy = sortBy, !sortBy.isEmpty {
filtered = filtered.order(by: sortBy)
}
उपरोक्त स्निपेट उपयोगकर्ता इनपुट के आधार पर एकल कंपाउंड क्वेरी बनाने के लिए एकाधिक whereField
और order
क्लॉज जोड़ता है। अब हमारी क्वेरी केवल उन रेस्तरां को वापस करेगी जो उपयोगकर्ता की आवश्यकताओं से मेल खाते हैं।
अपना प्रोजेक्ट चलाएं और सत्यापित करें कि आप मूल्य, शहर और श्रेणी के आधार पर फ़िल्टर कर सकते हैं (श्रेणी और शहर के नाम बिल्कुल टाइप करना सुनिश्चित करें)। परीक्षण करते समय आपको अपने लॉग में ऐसी त्रुटियाँ दिखाई दे सकती हैं जो इस प्रकार दिखाई देती हैं:
Error fetching snapshot results: Error Domain=io.grpc Code=9 "The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_composite=..." UserInfo={NSLocalizedDescription=The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_composite=...}
ऐसा इसलिए है क्योंकि फायरस्टार को अधिकांश यौगिक प्रश्नों के लिए अनुक्रमणिका की आवश्यकता होती है। प्रश्नों पर अनुक्रमणिका की आवश्यकता होने से फायरस्टोर तेजी से बड़े पैमाने पर रहता है। त्रुटि संदेश से लिंक खोलने से स्वचालित रूप से फायरबेस कंसोल में इंडेक्स क्रिएशन यूआई खुल जाएगा, जिसमें सही पैरामीटर भरे होंगे। फायरस्टोर में इंडेक्स के बारे में अधिक जानने के लिए, दस्तावेज़ीकरण पर जाएं ।
7. लेन-देन में डेटा लिखना
इस अनुभाग में, हम उपयोगकर्ताओं के लिए रेस्तरां में समीक्षाएँ सबमिट करने की क्षमता जोड़ेंगे। अब तक, हमारे सभी लेखन परमाणु और अपेक्षाकृत सरल रहे हैं। यदि उनमें से कोई त्रुटि है, तो हम संभवतः उपयोगकर्ता को उन्हें फिर से प्रयास करने या स्वचालित रूप से पुनः प्रयास करने का संकेत देंगे।
एक रेस्तरां में रेटिंग जोड़ने के लिए हमें कई रीड्स और राइट्स को समन्वित करने की आवश्यकता होती है। पहले स्वयं समीक्षा सबमिट करनी होगी, और फिर रेस्तरां की रेटिंग संख्या और औसत रेटिंग को अपडेट करने की आवश्यकता होगी। यदि इनमें से एक विफल हो जाता है लेकिन दूसरा नहीं, तो हम एक असंगत स्थिति में रह जाते हैं जहां हमारे डेटाबेस के एक हिस्से का डेटा दूसरे के डेटा से मेल नहीं खाता है।
सौभाग्य से, फायरस्टार लेनदेन की कार्यक्षमता प्रदान करता है जो हमें एक एकल परमाणु ऑपरेशन में कई पढ़ने और लिखने देता है, यह सुनिश्चित करता है कि हमारा डेटा सुसंगत रहे।
RestaurantDetailViewController.reviewController(_:didSubmitFormWithReview:)
में सभी घोषणाओं के नीचे निम्नलिखित कोड जोड़ें।
let firestore = Firestore.firestore()
firestore.runTransaction({ (transaction, errorPointer) -> Any? in
// Read data from Firestore inside the transaction, so we don't accidentally
// update using stale client data. Error if we're unable to read here.
let restaurantSnapshot: DocumentSnapshot
do {
try restaurantSnapshot = transaction.getDocument(reference)
} catch let error as NSError {
errorPointer?.pointee = error
return nil
}
// Error if the restaurant data in Firestore has somehow changed or is malformed.
guard let data = restaurantSnapshot.data(),
let restaurant = Restaurant(dictionary: data) else {
let error = NSError(domain: "FireEatsErrorDomain", code: 0, userInfo: [
NSLocalizedDescriptionKey: "Unable to write to restaurant at Firestore path: \(reference.path)"
])
errorPointer?.pointee = error
return nil
}
// Update the restaurant's rating and rating count and post the new review at the
// same time.
let newAverage = (Float(restaurant.ratingCount) * restaurant.averageRating + Float(review.rating))
/ Float(restaurant.ratingCount + 1)
transaction.setData(review.dictionary, forDocument: newReviewReference)
transaction.updateData([
"numRatings": restaurant.ratingCount + 1,
"avgRating": newAverage
], forDocument: reference)
return nil
}) { (object, error) in
if let error = error {
print(error)
} else {
// Pop the review controller on success
if self.navigationController?.topViewController?.isKind(of: NewReviewViewController.self) ?? false {
self.navigationController?.popViewController(animated: true)
}
}
}
अपडेट ब्लॉक के अंदर, ट्रांजैक्शन ऑब्जेक्ट का उपयोग करके हम जो भी ऑपरेशन करते हैं, उन्हें फायरस्टोर द्वारा एकल परमाणु अपडेट के रूप में माना जाएगा। यदि सर्वर पर अपडेट विफल हो जाता है, तो फायरस्टार स्वचालित रूप से इसे कुछ बार पुनः प्रयास करेगा। इसका मतलब यह है कि हमारी त्रुटि की स्थिति सबसे अधिक बार होने वाली एक त्रुटि है, उदाहरण के लिए यदि डिवाइस पूरी तरह से ऑफ़लाइन है या उपयोगकर्ता उस पथ पर लिखने के लिए अधिकृत नहीं है जिस पर वे लिखने का प्रयास कर रहे हैं।
8. सुरक्षा नियम
हमारे ऐप के उपयोगकर्ता हमारे डेटाबेस में डेटा के प्रत्येक भाग को पढ़ने और लिखने में सक्षम नहीं होने चाहिए। उदाहरण के लिए सभी को रेस्तरां की रेटिंग देखने में सक्षम होना चाहिए, लेकिन केवल एक प्रमाणित उपयोगकर्ता को ही रेटिंग पोस्ट करने की अनुमति दी जानी चाहिए। क्लाइंट पर अच्छा कोड लिखना पर्याप्त नहीं है, हमें पूरी तरह से सुरक्षित होने के लिए बैकएंड पर अपने डेटा सुरक्षा मॉडल को निर्दिष्ट करने की आवश्यकता है। इस अनुभाग में हम सीखेंगे कि अपने डेटा की सुरक्षा के लिए फायरबेस सुरक्षा नियमों का उपयोग कैसे करें।
सबसे पहले, कोडलैब की शुरुआत में हमने जो सुरक्षा नियम लिखे थे, उन पर गहराई से नज़र डालते हैं। फायरबेस कंसोल खोलें और फायरस्टार टैब में डेटाबेस > रूल्स पर नेविगेट करें।
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
// Only authenticated users can read or write data
allow read, write: if request.auth != null;
}
}
}
उपरोक्त नियमों में request
चर सभी नियमों में उपलब्ध एक वैश्विक चर है, और हमने जो सशर्त जोड़ा है वह सुनिश्चित करता है कि उपयोगकर्ताओं को कुछ भी करने की अनुमति देने से पहले अनुरोध को प्रमाणित किया गया है। यह अप्रमाणित उपयोगकर्ताओं को आपके डेटा में अनधिकृत परिवर्तन करने के लिए Firestore API का उपयोग करने से रोकता है। यह एक अच्छी शुरुआत है, लेकिन हम अधिक शक्तिशाली चीजें करने के लिए फायरस्टोर नियमों का उपयोग कर सकते हैं।
आइए समीक्षा लेखन को प्रतिबंधित करते हैं ताकि समीक्षा की उपयोगकर्ता आईडी प्रमाणित उपयोगकर्ता की आईडी से मेल खाना चाहिए। यह सुनिश्चित करता है कि उपयोगकर्ता एक-दूसरे का प्रतिरूपण नहीं कर सकते हैं और कपटपूर्ण समीक्षाएं नहीं छोड़ सकते हैं। अपने सुरक्षा नियमों को निम्नलिखित से बदलें:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /restaurants/{any}/ratings/{rating} {
// Users can only write ratings with their user ID
allow read;
allow write: if request.auth != null
&& request.auth.uid == request.resource.data.userId;
}
match /restaurants/{any} {
// Only authenticated users can read or write data
allow read, write: if request.auth != null;
}
}
}
पहला मिलान विवरण restaurants
संग्रह से संबंधित किसी भी दस्तावेज़ के ratings
नाम के उपसंग्रह से मेल खाता है। यदि समीक्षा की उपयोगकर्ता आईडी उपयोगकर्ता की उपयोगकर्ता आईडी से मेल नहीं खाती है तो allow write
सशर्त तब किसी भी समीक्षा को सबमिट होने से रोकती है। दूसरा मैच स्टेटमेंट किसी भी प्रमाणित उपयोगकर्ता को डेटाबेस में रेस्तरां पढ़ने और लिखने की अनुमति देता है।
यह हमारी समीक्षाओं के लिए वास्तव में अच्छी तरह से काम करता है, क्योंकि हमने सुरक्षा नियमों का उपयोग स्पष्ट रूप से उस अंतर्निहित गारंटी को बताने के लिए किया है जिसे हमने अपने ऐप में पहले लिखा था- कि उपयोगकर्ता केवल अपनी समीक्षा ही लिख सकते हैं। यदि हम समीक्षाओं के लिए संपादन या हटाने का कार्य जोड़ते हैं, तो नियमों का ठीक यही सेट उपयोगकर्ताओं को अन्य उपयोगकर्ताओं की समीक्षाओं को संशोधित करने या हटाने से भी रोकेगा। लेकिन फायरस्टोर नियमों का उपयोग अधिक व्यापक रूप से दस्तावेजों के भीतर अलग-अलग क्षेत्रों पर लिखने को सीमित करने के लिए किया जा सकता है, बजाय पूरे दस्तावेजों के। हम इसका उपयोग उपयोगकर्ताओं को रेस्तरां के लिए केवल रेटिंग, औसत रेटिंग और रेटिंग की संख्या को अपडेट करने की अनुमति देने के लिए कर सकते हैं, जिससे किसी दुर्भावनापूर्ण उपयोगकर्ता द्वारा रेस्तरां का नाम या स्थान बदलने की संभावना समाप्त हो जाती है।
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /restaurants/{restaurant} {
match /ratings/{rating} {
allow read: if request.auth != null;
allow write: if request.auth != null
&& request.auth.uid == request.resource.data.userId;
}
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if request.auth != null
&& request.resource.data.name == resource.data.name
&& request.resource.data.city == resource.data.city
&& request.resource.data.price == resource.data.price
&& request.resource.data.category == resource.data.category;
}
}
}
यहां हमने अपनी लिखने की अनुमति को क्रिएट और अपडेट में विभाजित किया है ताकि हम इस बारे में अधिक विशिष्ट हो सकें कि किन कार्यों की अनुमति दी जानी चाहिए। कोई भी उपयोगकर्ता कोडलैब की शुरुआत में हमारे द्वारा बनाए गए पॉप्युलेट बटन की कार्यक्षमता को संरक्षित करते हुए, डेटाबेस में रेस्तरां लिख सकता है, लेकिन एक बार एक रेस्तरां लिखे जाने के बाद उसका नाम, स्थान, मूल्य और श्रेणी नहीं बदली जा सकती। अधिक विशेष रूप से, अंतिम नियम के लिए डेटाबेस में पहले से मौजूद फ़ील्ड के समान नाम, शहर, मूल्य और श्रेणी को बनाए रखने के लिए किसी भी रेस्तरां अपडेट ऑपरेशन की आवश्यकता होती है।
इस बारे में अधिक जानने के लिए कि आप सुरक्षा नियमों के साथ क्या कर सकते हैं, दस्तावेज़ देखें।
9. निष्कर्ष
इस कोडलैब में, आपने फायरस्टोर के साथ बुनियादी और उन्नत पढ़ने और लिखने के साथ-साथ सुरक्षा नियमों के साथ डेटा एक्सेस को सुरक्षित करने का तरीका सीखा। आप codelab-complete
शाखा पर पूरा समाधान पा सकते हैं।
फायरस्टोर के बारे में अधिक जानने के लिए, निम्नलिखित संसाधनों पर जाएँ: