ক্লাউড ফায়ারস্টোর আইওএস কোডল্যাব

1। সংক্ষিপ্ত বিবরণ

গোল

এই কোডল্যাবে আপনি Swift-এ iOS-এ ফায়ারস্টোর-সমর্থিত রেস্তোরাঁর সুপারিশ অ্যাপ তৈরি করবেন। আপনি শিখবেন কিভাবে:

  1. একটি iOS অ্যাপ থেকে Firestore-এ ডেটা পড়ুন এবং লিখুন
  2. রিয়েলটাইমে Firestore ডেটার পরিবর্তনগুলি শুনুন
  3. Firestore ডেটা সুরক্ষিত করতে Firebase প্রমাণীকরণ এবং নিরাপত্তা নিয়ম ব্যবহার করুন
  4. জটিল Firestore প্রশ্ন লিখুন

পূর্বশর্ত

এই কোডল্যাব শুরু করার আগে নিশ্চিত করুন যে আপনি ইনস্টল করেছেন:

  • Xcode সংস্করণ 8.3 (বা উচ্চতর)
  • CocoaPods 1.2.1 (বা উচ্চতর)

2. ফায়ারবেস কনসোল প্রকল্প তৈরি করুন

প্রকল্পে Firebase যোগ করুন

  1. যান Firebase কনসোল
  2. নতুন প্রকল্প তৈরি করুন এবং আপনার প্রকল্পের "Firestore আইওএস Codelab" নাম নির্বাচন করুন।

3. নমুনা প্রকল্প পান

কোডটি ডাউনলোড করুন

ক্লোন করে শুরু করুন নমুনা প্রকল্প এবং চলমান pod update প্রকল্পের ডিরেক্টরির মধ্যে:

git clone https://github.com/firebase/friendlyeats-ios
cd friendlyeats-ios
pod update

ওপেন FriendlyEats.xcworkspace Xcode এবং এটি চালানোর (উঠলে Cmd + আর)। অ্যাপ্লিকেশন সঠিকভাবে কম্পাইল করা উচিত এবং অবিলম্বে লঞ্চ উপর বিপর্যস্ত যেহেতু এটি একটি অনুপস্থিত GoogleService-Info.plist ফাইল। আমরা পরবর্তী ধাপে এটি সংশোধন করব।

Firebase সেট আপ করুন

অনুসরণ ডকুমেন্টেশন একটি নতুন Firestore প্রকল্পের তৈরি করুন। একবার আপনি আপনার প্রকল্পের পেয়েছেন, আপনার প্রকল্পের ডাউনলোড GoogleService-Info.plist থেকে ফাইল Firebase কনসোল Xcode প্রকল্পের রুট প্রয়োজন এবং টেনে আনুন। অ্যাপটি সঠিকভাবে কনফিগার করেছে এবং লঞ্চের সময় আর ক্র্যাশ হচ্ছে না তা নিশ্চিত করতে প্রকল্পটি আবার চালান। লগ ইন করার পরে, আপনি নীচের উদাহরণের মত একটি ফাঁকা স্ক্রীন দেখতে পাবেন। আপনি লগ ইন করতে অক্ষম হলে, নিশ্চিত করুন যে আপনি প্রমাণীকরণের অধীনে Firebase কনসোলে ইমেল/পাসওয়ার্ড সাইন-ইন পদ্ধতি সক্রিয় করেছেন।

10a0671ce8f99704.png

4. ফায়ারস্টোরে ডেটা লিখুন

এই বিভাগে আমরা Firestore-এ কিছু ডেটা লিখব যাতে আমরা অ্যাপ UI পূরণ করতে পারি। এর মাধ্যমে নিজে কাজ করা যেতে পারে Firebase কনসোল , কিন্তু আমরা অ্যাপ্লিকেশন নিজেই একটি মৌলিক Firestore লেখার প্রকট এটা চেষ্টা করবো।

আমাদের অ্যাপের প্রধান মডেল বস্তু হল একটি রেস্টুরেন্ট। ফায়ারস্টোর ডেটা নথি, সংগ্রহ এবং উপ-সংগ্রহগুলিতে বিভক্ত। আমরা একটি টপ লেভেল সংগ্রহ নামক একটি নথি হিসাবে একে রেস্টুরেন্টে সংরক্ষণ করবে restaurants । আপনি Firestore তথ্য মডেল সম্পর্কে আরো জানতে চান তাহলে, নথি এবং সংগ্রহের সম্পর্কে পড়তে ডকুমেন্টেশন

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)

উপরের কোডটি রেস্টুরেন্ট সংগ্রহে একটি নতুন নথি যোগ করে। নথির ডেটা একটি অভিধান থেকে আসে, যা আমরা একটি রেস্তোরাঁর কাঠামো থেকে পাই।

আমরা প্রায় সেখানেই আছি– আমরা Firestore-এ নথি লিখতে পারার আগে আমাদের Firestore-এর নিরাপত্তা নিয়মগুলি খুলতে হবে এবং আমাদের ডাটাবেসের কোন অংশগুলি কোন ব্যবহারকারীদের দ্বারা লেখার যোগ্য হবে তা বর্ণনা করতে হবে। আপাতত, আমরা শুধুমাত্র প্রমাণীকৃত ব্যবহারকারীদের সমগ্র ডাটাবেসে পড়তে এবং লিখতে অনুমতি দেব। এটি একটি প্রোডাকশন অ্যাপের জন্য একটু বেশিই অনুমোদনযোগ্য, কিন্তু অ্যাপ-বিল্ডিং প্রক্রিয়া চলাকালীন আমরা যথেষ্ট শিথিল কিছু চাই তাই পরীক্ষা করার সময় আমরা ক্রমাগত প্রমাণীকরণের সমস্যায় পড়ব না। এই কোডল্যাবের শেষে আমরা কীভাবে আপনার নিরাপত্তা বিধিগুলিকে কঠোর করতে এবং অনিচ্ছাকৃত পঠন এবং লেখার সম্ভাবনা সীমিত করতে পারি সে সম্পর্কে কথা বলব৷

ইন বিধি ট্যাব 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 কনসোলে। আপনি এখন রেস্টুরেন্ট সংগ্রহে নতুন এন্ট্রি দেখতে হবে:

স্ক্রীন শট 2017-07-06 12.45.38 PM.png

অভিনন্দন, আপনি এইমাত্র একটি iOS অ্যাপ থেকে Firestore-এ ডেটা লিখেছেন! পরবর্তী বিভাগে আপনি শিখবেন কীভাবে ফায়ারস্টোর থেকে ডেটা পুনরুদ্ধার করতে হয় এবং এটি অ্যাপে প্রদর্শন করতে হয়।

5. ফায়ারস্টোর থেকে ডেটা প্রদর্শন করুন

এই বিভাগে আপনি শিখবেন কিভাবে ফায়ারস্টোর থেকে ডেটা পুনরুদ্ধার করতে হয় এবং অ্যাপে এটি প্রদর্শন করতে হয়। দুটি মূল ধাপ হল একটি ক্যোয়ারী তৈরি করা এবং একটি স্ন্যাপশট লিসেনার যোগ করা। এই শ্রোতাকে সমস্ত বিদ্যমান ডেটা সম্পর্কে অবহিত করা হবে যা প্রশ্নের সাথে মেলে এবং রিয়েল টাইমে আপডেটগুলি পাবে।

প্রথমে, চলুন এমন একটি ক্যোয়ারী তৈরি করি যা রেস্তোরাঁর ডিফল্ট, আনফিল্টার করা তালিকা পরিবেশন করবে। বাস্তবায়ন কটাক্ষপাত RestaurantsTableViewController.baseQuery() :

return Firestore.firestore().collection("restaurants").limit(to: 50)

এই প্রশ্নটি "রেস্তোরাঁ" নামে শীর্ষ-স্তরের সংগ্রহের 50টি পর্যন্ত রেস্তোরাঁ পুনরুদ্ধার করে৷ এখন যেহেতু আমাদের কাছে একটি প্রশ্ন আছে, আমাদের অ্যাপে 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(_:) কল একটি স্ন্যাপশট শ্রোতা ক্যোয়ারী যে দৃশ্য নিয়ামক প্রত্যেক সময় ডেটা সার্ভারে পরিবর্তন আপডেট হবে যোগ করা। আমরা স্বয়ংক্রিয়ভাবে আপডেট পাই এবং ম্যানুয়ালি পরিবর্তন করতে হবে না। মনে রাখবেন, সার্ভার-সাইড পরিবর্তনের ফলে এই স্ন্যাপশট শ্রোতাকে যে কোনো সময় আহ্বান করা যেতে পারে তাই এটি গুরুত্বপূর্ণ যে আমাদের অ্যাপ পরিবর্তনগুলি পরিচালনা করতে পারে।

আমাদের অভিধান ম্যাপিং structs মধ্যে (দেখুন পরে 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:) পৃথক টেবিল ভিউ কোষ সামনে পদ্ধতি, যা থেকে মান ধরনের সংগ্রহ ম্যাপিং যত্ন নেয়।

অ্যাপটি আবার চালান এবং যাচাই করুন যে আমরা আগে কনসোলে যে রেস্তোরাঁগুলি দেখেছিলাম সেগুলি এখন সিমুলেটর বা ডিভাইসে দৃশ্যমান৷ আপনি যদি এই বিভাগটি সফলভাবে সম্পন্ন করেন তবে আপনার অ্যাপ এখন ক্লাউড ফায়ারস্টোরের সাথে ডেটা পড়ছে এবং লিখছে!

2ca7f8c6052f7f79.png

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/testapp-5d356/database/firestore/indexes?create_index=..." 
UserInfo={NSLocalizedDescription=The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_index=...}

এর কারণ হল Firestore-এর বেশিরভাগ যৌগিক প্রশ্নের জন্য সূচী প্রয়োজন। ক্যোয়ারীতে ইনডেক্সের প্রয়োজন ফায়ারস্টোরকে স্কেলে দ্রুত রাখে। ত্রুটি বার্তা থেকে লিঙ্ক খোলা স্বয়ংক্রিয়ভাবে ঠিক পূরণ পরামিতি সঙ্গে Firebase কনসোলে সূচক সৃষ্টি UI 'তে খুলবে।, Firestore মধ্যে ইনডেক্স সম্পর্কে আরো জানতে ডকুমেন্টেশন যান

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)
    }
  }
}

আপডেট ব্লকের ভিতরে, লেনদেন বস্তু ব্যবহার করে আমরা যে সমস্ত ক্রিয়াকলাপ করি তা Firestore দ্বারা একক পারমাণবিক আপডেট হিসাবে গণ্য হবে। সার্ভারে আপডেট ব্যর্থ হলে, Firestore স্বয়ংক্রিয়ভাবে এটি কয়েকবার পুনরায় চেষ্টা করবে। এর মানে হল যে আমাদের ত্রুটির অবস্থাটি সম্ভবত একটি একক ত্রুটি বারবার ঘটতে পারে, উদাহরণস্বরূপ যদি ডিভাইসটি সম্পূর্ণ অফলাইনে থাকে বা ব্যবহারকারী যে পথে লেখার চেষ্টা করছেন তাতে লেখার জন্য অনুমোদিত না হয়৷

8. নিরাপত্তা নিয়ম

আমাদের অ্যাপের ব্যবহারকারীরা আমাদের ডাটাবেসের প্রতিটি ডেটা পড়তে এবং লিখতে সক্ষম হবেন না। উদাহরণস্বরূপ, প্রত্যেকেরই একটি রেস্তোরাঁর রেটিং দেখতে সক্ষম হওয়া উচিত, তবে শুধুমাত্র একজন প্রমাণীকৃত ব্যবহারকারীকে একটি রেটিং পোস্ট করার অনুমতি দেওয়া উচিত। ক্লায়েন্টে ভাল কোড লেখার জন্য এটি যথেষ্ট নয়, সম্পূর্ণ সুরক্ষিত হওয়ার জন্য ব্যাকএন্ডে আমাদের ডেটা সুরক্ষা মডেলটি নির্দিষ্ট করতে হবে। এই বিভাগে আমরা শিখব কিভাবে আমাদের ডেটা সুরক্ষিত রাখতে Firebase নিরাপত্তা নিয়মগুলি ব্যবহার করতে হয়।

প্রথমত, কোডল্যাবের শুরুতে আমরা যে নিরাপত্তা বিধিগুলি লিখেছিলাম তার গভীরে নজর দেওয়া যাক৷ থেকে 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 নিয়মগুলি ব্যবহার করতে পারি৷

আসুন পর্যালোচনা লেখাগুলিকে সীমাবদ্ধ করি যাতে পর্যালোচনার ব্যবহারকারী আইডি অবশ্যই প্রমাণীকৃত ব্যবহারকারীর আইডির সাথে মেলে। এটি নিশ্চিত করে যে ব্যবহারকারীরা একে অপরের ছদ্মবেশ ধারণ করতে পারবে না এবং প্রতারণামূলক পর্যালোচনাগুলি ছেড়ে যেতে পারবে না৷ নিম্নলিখিত দিয়ে আপনার নিরাপত্তা নিয়ম প্রতিস্থাপন করুন:

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;
    }
  }
}

প্রথম ম্যাচে বিবৃতি subcollection নামে মিলে যায় 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;
    }
  }
}

এখানে আমরা আমাদের লেখার অনুমতি তৈরি এবং আপডেটে বিভক্ত করেছি যাতে আমরা কোন ক্রিয়াকলাপগুলির অনুমতি দেওয়া উচিত সে সম্পর্কে আরও নির্দিষ্ট হতে পারি। কোডল্যাবের শুরুতে আমরা যে পপুলেট বোতামটি তৈরি করেছি তার কার্যকারিতা সংরক্ষণ করে যেকোন ব্যবহারকারী ডাটাবেসে রেস্টুরেন্ট লিখতে পারে, কিন্তু একবার রেস্তোরাঁর নাম, অবস্থান, মূল্য এবং বিভাগ পরিবর্তন করা যাবে না। আরও নির্দিষ্টভাবে, শেষ নিয়মে ডাটাবেসে ইতিমধ্যে বিদ্যমান ক্ষেত্রগুলির একই নাম, শহর, মূল্য এবং বিভাগ বজায় রাখার জন্য যে কোনও রেস্তোরাঁর আপডেট অপারেশন প্রয়োজন।

আপনি নিরাপত্তা নিয়ম কি করতে পারি সে সম্পর্কে আরো জানতে, কটাক্ষপাত করা ডকুমেন্টেশন

9. উপসংহার

এই কোডল্যাবে, আপনি শিখেছেন কিভাবে ফায়ারস্টোরের সাথে প্রাথমিক এবং উন্নত পঠন এবং লিখতে হয়, সেইসাথে কীভাবে সুরক্ষা নিয়মের সাথে ডেটা অ্যাক্সেস সুরক্ষিত করা যায়। আপনি পূর্ণ সমাধান জানতে পারেন codelab-complete শাখা

ফায়ারস্টোর সম্পর্কে আরও জানতে, নিম্নলিখিত সংস্থানগুলি দেখুন: