1. ภาพรวม
เป้าหมาย
ใน Codelab นี้ คุณจะสร้างแอปแนะนำร้านอาหารที่ได้รับการสนับสนุนจาก Firestore บน iOS ใน Swift คุณจะได้เรียนรู้วิธีการ:
- อ่านและเขียนข้อมูลไปยัง Firestore จากแอป iOS
- ฟังการเปลี่ยนแปลงในข้อมูล Firestore แบบเรียลไทม์
- ใช้การตรวจสอบสิทธิ์ Firebase และกฎความปลอดภัยเพื่อรักษาความปลอดภัยข้อมูล Firestore
- เขียนคำสั่ง Firestore ที่ซับซ้อน
ข้อกำหนดเบื้องต้น
ก่อนที่จะเริ่ม Codelab นี้ ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้ง:
- Xcode เวอร์ชัน 14.0 (หรือสูงกว่า)
- CocoaPods 1.12.0 (หรือสูงกว่า)
2. สร้างโครงการคอนโซล Firebase
เพิ่ม Firebase ให้กับโปรเจ็กต์
- ไปที่ คอนโซล Firebase
- เลือก สร้างโปรเจ็กต์ใหม่ แล้วตั้งชื่อโปรเจ็กต์ของคุณ "Firestore iOS Codelab"
3. รับโครงการตัวอย่าง
ดาวน์โหลดรหัส
เริ่มต้นด้วยการโคลน โปรเจ็กต์ตัวอย่าง และรัน pod update
ในไดเร็กทอรีโปรเจ็กต์:
git clone https://github.com/firebase/friendlyeats-ios cd friendlyeats-ios pod update
เปิด FriendlyEats.xcworkspace
ใน Xcode แล้วเรียกใช้ (Cmd+R) แอปควรคอมไพล์อย่างถูกต้องและขัดข้องทันทีเมื่อเปิดตัว เนื่องจากไม่มีไฟล์ GoogleService-Info.plist
เราจะแก้ไขให้ถูกต้องในขั้นตอนถัดไป
ตั้งค่า Firebase
ทำตาม เอกสารประกอบ เพื่อสร้างโปรเจ็กต์ Firestore ใหม่ เมื่อคุณมีโปรเจ็กต์แล้ว ให้ดาวน์โหลดไฟล์ GoogleService-Info.plist
ของโปรเจ็กต์จาก คอนโซล Firebase แล้วลากไปที่รูทของโปรเจ็กต์ Xcode รันโปรเจ็กต์อีกครั้งเพื่อให้แน่ใจว่าแอปกำหนดค่าอย่างถูกต้องและไม่ขัดข้องเมื่อเปิดใช้งานอีกต่อไป หลังจากเข้าสู่ระบบแล้ว คุณจะเห็นหน้าจอว่างตามตัวอย่างด้านล่าง หากคุณไม่สามารถเข้าสู่ระบบได้ ตรวจสอบให้แน่ใจว่าคุณได้เปิดใช้งานวิธีการลงชื่อเข้าใช้อีเมล/รหัสผ่านในคอนโซล Firebase ภายใต้การตรวจสอบสิทธิ์
4. เขียนข้อมูลไปยัง Firestore
ในส่วนนี้ เราจะเขียนข้อมูลบางส่วนลงใน Firestore เพื่อให้เราสามารถเติม UI ของแอปได้ ซึ่งสามารถทำได้ด้วยตนเองผ่าน คอนโซล Firebase แต่เราจะทำในแอปเองเพื่อสาธิตการเขียน Firestore ขั้นพื้นฐาน
วัตถุโมเดลหลักในแอปของเราคือร้านอาหาร ข้อมูล Firestore จะแบ่งออกเป็นเอกสาร คอลเล็กชัน และคอลเล็กชันย่อย เราจะจัดเก็บร้านอาหารแต่ละแห่งเป็นเอกสารในคอลเลกชันระดับบนสุดที่เรียกว่า restaurants
หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับโมเดลข้อมูล Firestore โปรดอ่านเกี่ยวกับเอกสารและคอลเล็กชันใน เอกสารประกอบ
ก่อนที่เราจะเพิ่มข้อมูลลงใน Firestore เราจำเป็นต้องได้รับการอ้างอิงถึงคอลเล็กชันร้านอาหารก่อน เพิ่มสิ่งต่อไปนี้ลงใน for loop ภายในในเมธอด 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)
โค้ดด้านบนจะเพิ่มเอกสารใหม่ให้กับคอลเลกชั่นร้านอาหาร ข้อมูลเอกสารมาจากพจนานุกรม ซึ่งเราได้รับจากโครงสร้างร้านอาหาร
เราเกือบจะถึงจุดนั้นแล้ว ก่อนที่เราจะสามารถเขียนเอกสารไปยัง Firestore ได้ เราจำเป็นต้องเปิดกฎความปลอดภัยของ Firestore และอธิบายว่าส่วนใดของฐานข้อมูลของเราที่ผู้ใช้คนใดควรเขียนได้ ในตอนนี้ เราจะอนุญาตให้เฉพาะผู้ใช้ที่ได้รับการรับรองความถูกต้องเท่านั้นที่สามารถอ่านและเขียนฐานข้อมูลทั้งหมดได้ นี่เป็นการอนุญาตเล็กน้อยเกินไปสำหรับแอปเวอร์ชันที่ใช้งานจริง แต่ในระหว่างกระบวนการสร้างแอป เราต้องการบางสิ่งที่ผ่อนคลายเพียงพอ เพื่อที่เราจะไม่ประสบปัญหาการตรวจสอบสิทธิ์อย่างต่อเนื่องขณะทำการทดลอง ในตอนท้ายของ Codelab นี้ เราจะพูดถึงวิธีทำให้กฎความปลอดภัยเข้มงวดขึ้น และจำกัดความเป็นไปได้ของการอ่านและเขียนโดยไม่ได้ตั้งใจ
ใน แท็บกฎ ของคอนโซล 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; } } }
เราจะหารือเกี่ยวกับกฎความปลอดภัยโดยละเอียดในภายหลัง แต่หากคุณรีบ โปรดดู เอกสารกฎความปลอดภัย
เรียกใช้แอปและลงชื่อเข้าใช้ จากนั้นแตะปุ่ม " เติมข้อมูล " ที่ด้านซ้ายบน ซึ่งจะสร้างชุดเอกสารร้านอาหาร แม้ว่าคุณจะยังไม่เห็นสิ่งนี้ในแอปก็ตาม
จากนั้นไปที่ แท็บข้อมูล Firestore ในคอนโซล Firebase ตอนนี้คุณควรเห็นรายการใหม่ในคอลเลกชั่นร้านอาหาร:
ยินดีด้วย คุณเพิ่งเขียนข้อมูลไปยัง Firestore จากแอป iOS! ในส่วนถัดไป คุณจะได้เรียนรู้วิธีดึงข้อมูลจาก Firestore และแสดงในแอป
5. แสดงข้อมูลจาก Firestore
ในส่วนนี้ คุณจะได้เรียนรู้วิธีดึงข้อมูลจาก Firestore และแสดงในแอป สองขั้นตอนสำคัญคือการสร้างแบบสอบถามและเพิ่ม Listener สแน็ปช็อต ผู้ฟังรายนี้จะได้รับแจ้งข้อมูลที่มีอยู่ทั้งหมดที่ตรงกับข้อความค้นหา และรับการอัปเดตแบบเรียลไทม์
ขั้นแรก เรามาสร้างคำค้นหาที่จะแสดงรายการร้านอาหารเริ่มต้นที่ไม่มีการกรอง ดูการใช้งานของ RestaurantsTableViewController.baseQuery()
:
return Firestore.firestore().collection("restaurants").limit(to: 50)
ข้อความค้นหานี้จะดึงข้อมูลร้านอาหารสูงสุด 50 ร้านจากคอลเลกชั่นระดับบนสุดชื่อ "ร้านอาหาร" ตอนนี้เรามีคำถามแล้ว เราต้องแนบ Snapshot Listener เพื่อโหลดข้อมูลจาก Firestore ลงในแอปของเรา เพิ่มโค้ดต่อไปนี้ลงในเมธอด RestaurantsTableViewController.observeQuery()
หลังจากการเรียกไปยัง stopObserving()
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()
}
โค้ดด้านบนดาวน์โหลดคอลเลกชันจาก Firestore และจัดเก็บไว้ในอาร์เรย์ภายในเครื่อง การเรียก addSnapshotListener(_:)
จะเพิ่มตัวฟังสแน็ปช็อตในแบบสอบถามที่จะอัปเดตตัวควบคุมมุมมองทุกครั้งที่ข้อมูลเปลี่ยนแปลงบนเซิร์ฟเวอร์ เราได้รับการอัปเดตโดยอัตโนมัติและไม่จำเป็นต้องผลักดันการเปลี่ยนแปลงด้วยตนเอง โปรดจำไว้ว่า Listener สแน็ปช็อตนี้สามารถเรียกใช้เมื่อใดก็ได้อันเป็นผลมาจากการเปลี่ยนแปลงฝั่งเซิร์ฟเวอร์ ดังนั้นจึงเป็นเรื่องสำคัญที่แอปของเราจะสามารถจัดการกับการเปลี่ยนแปลงได้
หลังจากจับคู่พจนานุกรมของเรากับโครงสร้างแล้ว (ดูที่ Restaurant.swift
) การแสดงข้อมูลเป็นเพียงเรื่องของการกำหนดคุณสมบัติมุมมองบางส่วนเท่านั้น เพิ่มบรรทัดต่อไปนี้ใน RestaurantTableViewCell.populate(restaurant:)
ใน RestaurantsTableViewController.swift
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:)
ของแหล่งข้อมูลวิวตาราง ซึ่งดูแลการแมปการรวบรวมประเภทค่าจากก่อนหน้าไปยังเซลล์มุมมองตารางแต่ละเซลล์
เรียกใช้แอปอีกครั้งและตรวจสอบว่าร้านอาหารที่เราเห็นก่อนหน้านี้ในคอนโซลตอนนี้มองเห็นได้บนเครื่องจำลองหรืออุปกรณ์แล้ว หากคุณทำส่วนนี้สำเร็จแล้ว แอปของคุณก็กำลังอ่านและเขียนข้อมูลด้วย Cloud Firestore!
6. การเรียงลำดับและการกรองข้อมูล
ขณะนี้แอปของเราแสดงรายการร้านอาหาร แต่ไม่มีวิธีใดที่ผู้ใช้จะกรองตามความต้องการได้ ในส่วนนี้ คุณจะใช้การสืบค้นขั้นสูงของ Firestore เพื่อเปิดใช้งานการกรอง
ต่อไปนี้คือตัวอย่างข้อความค้นหาง่ายๆ เพื่อเรียกร้านติ่มซำทั้งหมด:
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=...}
เนื่องจาก Firestore ต้องการดัชนีสำหรับการสืบค้นแบบผสมส่วนใหญ่ การร้องขอดัชนีในการสืบค้นช่วยให้ Firestore รวดเร็วในวงกว้าง การเปิดลิงก์จากข้อความแสดงข้อผิดพลาดจะเปิด UI การสร้างดัชนีในคอนโซล Firebase พร้อมพารามิเตอร์ที่ถูกต้องโดยอัตโนมัติ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับดัชนีใน Firestore โปรดไปที่เอกสารประกอบ
7. การเขียนข้อมูลในธุรกรรม
ในส่วนนี้ เราจะเพิ่มความสามารถสำหรับผู้ใช้ในการส่งรีวิวร้านอาหาร จนถึงตอนนี้ การเขียนทั้งหมดของเราเป็นแบบอะตอมมิกและค่อนข้างเรียบง่าย หากมีข้อผิดพลาดใดๆ เราอาจแจ้งให้ผู้ใช้ลองอีกครั้งหรือลองอีกครั้งโดยอัตโนมัติ
ในการเพิ่มการให้คะแนนให้กับร้านอาหาร เราจำเป็นต้องประสานการอ่านและเขียนหลายรายการ ก่อนอื่นจะต้องส่งรีวิว จากนั้นจะต้องอัปเดตจำนวนคะแนนของร้านอาหารและคะแนนเฉลี่ย หากข้อใดข้อหนึ่งล้มเหลวแต่ไม่ตรงกับข้ออื่น เราจะอยู่ในสถานะที่ไม่สอดคล้องกันโดยที่ข้อมูลในฐานข้อมูลส่วนหนึ่งของเราไม่ตรงกับข้อมูลในอีกส่วนหนึ่ง
โชคดีที่ Firestore มีฟังก์ชันธุรกรรมที่ช่วยให้เราทำการอ่านและเขียนได้หลายครั้งในการดำเนินการแบบอะตอมมิกเดียว ทำให้มั่นใจได้ว่าข้อมูลของเรายังคงสอดคล้องกัน
เพิ่มโค้ดต่อไปนี้ด้านล่างการประกาศ Let ทั้งหมดใน 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)
}
}
}
ภายในบล็อกการอัปเดต การดำเนินการทั้งหมดที่เราทำโดยใช้อ็อบเจ็กต์ธุรกรรมจะถือเป็นการอัปเดตอะตอมมิกเดียวโดย Firestore หากการอัปเดตล้มเหลวบนเซิร์ฟเวอร์ Firestore จะลองอีกครั้งโดยอัตโนมัติสองสามครั้ง ซึ่งหมายความว่าเงื่อนไขข้อผิดพลาดของเรามีแนวโน้มที่จะเกิดข้อผิดพลาดเดียวเกิดขึ้นซ้ำๆ เช่น หากอุปกรณ์ออฟไลน์โดยสมบูรณ์หรือผู้ใช้ไม่ได้รับอนุญาตให้เขียนไปยังเส้นทางที่พวกเขากำลังพยายามเขียนถึง
8. กฎความปลอดภัย
ผู้ใช้แอปของเราไม่ควรสามารถอ่านและเขียนข้อมูลทุกชิ้นในฐานข้อมูลของเราได้ ตัวอย่างเช่น ทุกคนควรเห็นการให้คะแนนของร้านอาหาร แต่ควรอนุญาตให้เฉพาะผู้ใช้ที่ผ่านการรับรองความถูกต้องเท่านั้นจึงจะโพสต์การให้คะแนนได้ การเขียนโค้ดที่ดีบนไคลเอนต์นั้นไม่เพียงพอ เราจำเป็นต้องระบุโมเดลความปลอดภัยของข้อมูลบนแบ็กเอนด์ให้มีความปลอดภัยอย่างสมบูรณ์ ในส่วนนี้ เราจะได้เรียนรู้วิธีใช้กฎความปลอดภัยของ Firebase เพื่อปกป้องข้อมูลของเรา
ก่อนอื่น เรามาดูรายละเอียดกฎความปลอดภัยที่เราเขียนไว้ตอนเริ่มต้น Codelab กันก่อน เปิดคอนโซล Firebase และไปที่ ฐานข้อมูล > กฎในแท็บ Firestore
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 เพื่อทำการเปลี่ยนแปลงข้อมูลของคุณโดยไม่ได้รับอนุญาต นี่เป็นการเริ่มต้นที่ดี แต่เราสามารถใช้กฎของ Firestore เพื่อทำสิ่งที่มีประสิทธิภาพมากขึ้นได้
มาจำกัดการเขียนบทวิจารณ์เพื่อให้ ID ผู้ใช้ของบทวิจารณ์ต้องตรงกับ ID ของผู้ใช้ที่ได้รับการรับรองความถูกต้อง เพื่อให้แน่ใจว่าผู้ใช้ไม่สามารถแอบอ้างบุคคลอื่นและเขียนรีวิวที่เป็นการฉ้อโกงได้ แทนที่กฎความปลอดภัยของคุณด้วยสิ่งต่อไปนี้:
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;
}
}
}
ข้อความที่ตรงกันรายการแรกจะตรงกับคอลเลกชันย่อยที่มีชื่อ ratings
ของเอกสารใดๆ ที่เป็นของคอลเลกชัน restaurants
เงื่อนไข allow write
จะป้องกันไม่ให้ส่งการตรวจสอบใดๆ หากรหัสผู้ใช้ของการตรวจสอบไม่ตรงกับรหัสของผู้ใช้ คำสั่งการจับคู่ที่สองช่วยให้ผู้ใช้ที่ได้รับการรับรองความถูกต้องสามารถอ่านและเขียนร้านอาหารลงในฐานข้อมูลได้
วิธีนี้ใช้ได้ผลดีมากสำหรับรีวิวของเรา เนื่องจากเราใช้กฎความปลอดภัยเพื่อระบุการรับประกันโดยนัยที่เราเขียนไว้ในแอปของเราก่อนหน้านี้อย่างชัดเจน โดยที่ผู้ใช้สามารถเขียนได้เพียงรีวิวของตนเองเท่านั้น หากเราต้องเพิ่มฟังก์ชันแก้ไขหรือลบบทวิจารณ์ กฎชุดเดียวกันนี้จะป้องกันไม่ให้ผู้ใช้แก้ไขหรือลบบทวิจารณ์ของผู้ใช้รายอื่นเช่นกัน แต่กฎของ Firestore ยังสามารถนำมาใช้ในรูปแบบที่ละเอียดยิ่งขึ้นเพื่อจำกัดการเขียนในแต่ละฟิลด์ภายในเอกสาร แทนที่จะใช้ทั้งเอกสารเอง เราสามารถใช้สิ่งนี้เพื่อให้ผู้ใช้สามารถอัปเดตเฉพาะการให้คะแนน คะแนนเฉลี่ย และจำนวนการให้คะแนนสำหรับร้านอาหาร โดยลบความเป็นไปได้ที่ผู้ใช้ที่เป็นอันตรายจะเปลี่ยนชื่อร้านอาหารหรือที่ตั้ง
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;
}
}
}
ที่นี่เราได้แบ่งสิทธิ์ในการเขียนออกเป็นการสร้างและอัปเดต เพื่อให้เราระบุเจาะจงมากขึ้นว่าการดำเนินการใดควรได้รับอนุญาต ผู้ใช้ทุกคนสามารถเขียนร้านอาหารลงในฐานข้อมูล โดยคงฟังก์ชันการทำงานของปุ่ม Populate ที่เราสร้างไว้ตอนเริ่มต้น Codelab แต่เมื่อเขียนร้านอาหารแล้ว ชื่อ สถานที่ ราคา และหมวดหมู่จะไม่สามารถเปลี่ยนแปลงได้ โดยเฉพาะอย่างยิ่ง กฎข้อสุดท้ายกำหนดให้การดำเนินการอัปเดตร้านอาหารเพื่อรักษาชื่อ เมือง ราคา และหมวดหมู่ของฟิลด์ที่มีอยู่แล้วในฐานข้อมูลให้เหมือนเดิม
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับสิ่งที่คุณสามารถทำได้ด้วยกฎความปลอดภัย โปรดดูที่ เอกสารประกอบ
9. บทสรุป
ใน Codelab นี้ คุณได้เรียนรู้วิธีการอ่านและเขียนขั้นพื้นฐานและขั้นสูงด้วย Firestore รวมถึงวิธีรักษาความปลอดภัยการเข้าถึงข้อมูลด้วยกฎความปลอดภัย คุณสามารถค้นหาโซลูชันฉบับเต็มได้ที่ สาขา codelab-complete
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ Firestore โปรดไปที่แหล่งข้อมูลต่อไปนี้: