নিরাপদে তথ্য অনুসন্ধান

এই পৃষ্ঠাটি Cloud Firestore Security Rules প্রশ্নের সাথে কীভাবে ইন্টারঅ্যাক্ট করে তা ব্যাখ্যা করার জন্য সুরক্ষা বিধি গঠন এবং সুরক্ষা বিধিগুলির লেখার শর্তগুলির ধারণাগুলির উপর তৈরি করে৷ আপনি যে প্রশ্নগুলি লিখতে পারেন সেগুলিকে কীভাবে সুরক্ষা নিয়মগুলি প্রভাবিত করে সেগুলিকে এটি ঘনিষ্ঠভাবে বিবেচনা করে এবং কীভাবে আপনার প্রশ্নগুলি আপনার সুরক্ষা নিয়মগুলির মতো একই সীমাবদ্ধতাগুলি ব্যবহার করে তা নিশ্চিত করা যায় তা বর্ণনা করে৷ এই পৃষ্ঠাটি limit এবং orderBy মতো ক্যোয়ারী বৈশিষ্ট্যের উপর ভিত্তি করে প্রশ্নগুলিকে অনুমতি বা অস্বীকার করার জন্য কীভাবে সুরক্ষা নিয়ম লিখতে হয় তাও বর্ণনা করে।

নিয়ম ফিল্টার নয়

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

প্রশ্ন এবং নিরাপত্তা নিয়ম

নীচের উদাহরণগুলি দেখায় যে, আপনার নিরাপত্তা নিয়মের সীমাবদ্ধতার সাথে মানানসই করার জন্য আপনাকে অবশ্যই আপনার প্রশ্নগুলি লিখতে হবে৷

auth.uid উপর ভিত্তি করে নথিগুলি সুরক্ষিত করুন এবং অনুসন্ধান করুন৷

নিম্নলিখিত উদাহরণ প্রদর্শন করে কিভাবে একটি নিরাপত্তা নিয়ম দ্বারা সুরক্ষিত নথি পুনরুদ্ধার করার জন্য একটি প্রশ্ন লিখতে হয়। একটি ডাটাবেস বিবেচনা করুন যেখানে story নথির সংগ্রহ রয়েছে:

/গল্প/{storyid}

{
  title: "A Great Story",
  content: "Once upon a time...",
  author: "some_auth_id",
  published: false
}

title এবং content ক্ষেত্রগুলি ছাড়াও, প্রতিটি নথি author এবং published ক্ষেত্রগুলিকে অ্যাক্সেস নিয়ন্ত্রণের জন্য ব্যবহার করার জন্য সংরক্ষণ করে। এই উদাহরণগুলি অনুমান করে যে অ্যাপটি ডকুমেন্ট তৈরি করেছে এমন ব্যবহারকারীর ইউআইডিতে author ক্ষেত্র সেট করতে Firebase প্রমাণীকরণ ব্যবহার করে। Firebase প্রমাণীকরণ নিরাপত্তা নিয়মে request.auth ভেরিয়েবলকেও পপুলেট করে।

নিম্নলিখিত নিরাপত্তা বিধি request.auth auth এবং resource.data ভেরিয়েবল ব্যবহার করে প্রতিটি story লেখকের পড়ার এবং লেখার অ্যাক্সেস সীমাবদ্ধ করতে:

service cloud.firestore {
  match /databases/{database}/documents {
    match /stories/{storyid} {
      // Only the authenticated user who authored the document can read or write
      allow read, write: if request.auth != null && request.auth.uid == resource.data.author;
    }
  }
}

ধরুন আপনার অ্যাপটিতে এমন একটি পৃষ্ঠা রয়েছে যা ব্যবহারকারীকে তাদের লেখা story নথির তালিকা দেখায়। আপনি আশা করতে পারেন যে আপনি এই পৃষ্ঠাটি পূরণ করতে নিম্নলিখিত প্রশ্নটি ব্যবহার করতে পারেন। যাইহোক, এই ক্যোয়ারীটি ব্যর্থ হবে, কারণ এতে আপনার নিরাপত্তা নিয়মের মতো একই সীমাবদ্ধতা অন্তর্ভুক্ত নয়:

অবৈধ : ক্যোয়ারী সীমাবদ্ধতা নিরাপত্তা নিয়মের সীমাবদ্ধতার সাথে মেলে না

// This query will fail
db.collection("stories").get()

বর্তমান ব্যবহারকারী প্রতিটি story নথির লেখক হলেও প্রশ্নটি ব্যর্থ হয়। এই আচরণের কারণ হল যে যখন Cloud Firestore আপনার নিরাপত্তা নিয়মগুলি প্রয়োগ করে, তখন এটি আপনার ডাটাবেসের নথির প্রকৃত বৈশিষ্ট্যগুলির বিরুদ্ধে নয়, তার সম্ভাব্য ফলাফল সেটের বিরুদ্ধে প্রশ্নটিকে মূল্যায়ন করে৷ যদি একটি প্রশ্ন সম্ভাব্যভাবে আপনার নিরাপত্তা বিধি লঙ্ঘন করে এমন নথি অন্তর্ভুক্ত করতে পারে, প্রশ্নটি ব্যর্থ হবে৷

বিপরীতে, নিম্নলিখিত ক্যোয়ারীটি সফল হয়, কারণ এটি author ক্ষেত্রের নিরাপত্তা নিয়মের মতো একই সীমাবদ্ধতা অন্তর্ভুক্ত করে:

বৈধ : ক্যোয়ারী সীমাবদ্ধতা নিরাপত্তা নিয়মের সীমাবদ্ধতার সাথে মেলে

var user = firebase.auth().currentUser;

db.collection("stories").where("author", "==", user.uid).get()

একটি ক্ষেত্রের উপর ভিত্তি করে নথিগুলিকে সুরক্ষিত করুন এবং অনুসন্ধান করুন৷

ক্যোয়ারী এবং নিয়মের মধ্যে মিথস্ক্রিয়াকে আরও প্রদর্শন করতে, নীচের নিরাপত্তা বিধিগুলি stories সংগ্রহের জন্য পড়ার অ্যাক্সেস প্রসারিত করে যেখানে published ক্ষেত্রটি true হিসাবে সেট করা হয়েছে এমন কোনও ব্যবহারকারীকে story নথিগুলি পড়তে অনুমতি দেয়৷

service cloud.firestore {
  match /databases/{database}/documents {
    match /stories/{storyid} {
      // Anyone can read a published story; only story authors can read unpublished stories
      allow read: if resource.data.published == true || (request.auth != null && request.auth.uid == resource.data.author);
      // Only story authors can write
      allow write: if request.auth != null && request.auth.uid == resource.data.author;
    }
  }
}

প্রকাশিত পৃষ্ঠাগুলির জন্য ক্যোয়ারীতে অবশ্যই নিরাপত্তা নিয়মগুলির মতো একই সীমাবদ্ধতা অন্তর্ভুক্ত থাকতে হবে:

db.collection("stories").where("published", "==", true).get()

ক্যোয়ারী সীমাবদ্ধতা .where("published", "==", true) গ্যারান্টি দেয় যে resource.data.published যেকোন ফলাফলের জন্য true । অতএব, এই ক্যোয়ারীটি নিরাপত্তা নিয়মগুলিকে সন্তুষ্ট করে এবং ডেটা পড়ার অনুমতি দেওয়া হয়৷

OR প্রশ্ন

একটি নিয়ম সেটের বিপরীতে একটি যৌক্তিক OR ক্যোয়ারী ( or , in , অথবা array-contains-any ) মূল্যায়ন করার সময়, Cloud Firestore প্রতিটি তুলনা মান আলাদাভাবে মূল্যায়ন করে। প্রতিটি তুলনা মান নিরাপত্তা নিয়মের সীমাবদ্ধতা পূরণ করতে হবে। উদাহরণস্বরূপ, নিম্নলিখিত নিয়মের জন্য:

match /mydocuments/{doc} {
  allow read: if resource.data.x > 5;
}

অবৈধ : কোয়েরি সমস্ত সম্ভাব্য নথির জন্য x > 5 এর গ্যারান্টি দেয় না

// These queries will fail
query(db.collection("mydocuments"),
      or(where("x", "==", 1),
         where("x", "==", 6)
      )
    )

query(db.collection("mydocuments"),
      where("x", "in", [1, 3, 6, 42, 99])
    )

বৈধ : কোয়েরি গ্যারান্টি দেয় যে সমস্ত সম্ভাব্য নথির জন্য x > 5

query(db.collection("mydocuments"),
      or(where("x", "==", 6),
         where("x", "==", 42)
      )
    )

query(db.collection("mydocuments"),
      where("x", "in", [6, 42, 99, 105, 200])
    )

প্রশ্নের উপর সীমাবদ্ধতা মূল্যায়ন

আপনার নিরাপত্তা নিয়মগুলি তাদের সীমাবদ্ধতার উপর ভিত্তি করে প্রশ্নগুলি গ্রহণ বা অস্বীকার করতে পারে। request.query ভেরিয়েবলটিতে একটি প্রশ্নের limit , offset এবং orderBy বৈশিষ্ট্য রয়েছে। উদাহরণ স্বরূপ, আপনার নিরাপত্তা বিধি এমন কোনো প্রশ্নকে অস্বীকার করতে পারে যা একটি নির্দিষ্ট পরিসরে পুনরুদ্ধারের সর্বোচ্চ সংখ্যক নথি সীমাবদ্ধ করে না:

allow list: if request.query.limit <= 10;

নিম্নোক্ত রুলসেট প্রদর্শন করে যে কীভাবে নিরাপত্তা বিধি লিখতে হয় যা প্রশ্নে রাখা সীমাবদ্ধতাগুলি মূল্যায়ন করে। এই উদাহরণটি নিম্নলিখিত পরিবর্তনগুলির সাথে পূর্ববর্তী stories নিয়মকে প্রসারিত করে:

  • রুলসেট পঠিত নিয়মকে get এবং list নিয়মে আলাদা করে।
  • get নিয়ম একক নথির পুনরুদ্ধারকে পাবলিক নথি বা ব্যবহারকারীর লেখা নথিগুলিতে সীমাবদ্ধ করে।
  • list নিয়মটি get মতো একই বিধিনিষেধ প্রয়োগ করে কিন্তু প্রশ্নের জন্য। এটি ক্যোয়ারী সীমাও চেক করে, তারপর সীমা ছাড়াই বা 10 এর বেশি সীমা সহ যেকোন কোয়েরি অস্বীকার করে।
  • কোড ডুপ্লিকেশন এড়াতে নিয়মসেট একটি authorOrPublished() ফাংশন সংজ্ঞায়িত করে।
service cloud.firestore {

  match /databases/{database}/documents {

    match /stories/{storyid} {

      // Returns `true` if the requested story is 'published'
      // or the user authored the story
      function authorOrPublished() {
        return resource.data.published == true || request.auth.uid == resource.data.author;
      }

      // Deny any query not limited to 10 or fewer documents
      // Anyone can query published stories
      // Authors can query their unpublished stories
      allow list: if request.query.limit <= 10 &&
                     authorOrPublished();

      // Anyone can retrieve a published story
      // Only a story's author can retrieve an unpublished story
      allow get: if authorOrPublished();

      // Only a story's author can write to a story
      allow write: if request.auth.uid == resource.data.author;
    }

  }
}

সংগ্রহ গ্রুপ প্রশ্ন এবং নিরাপত্তা নিয়ম

ডিফল্টরূপে, প্রশ্নগুলি একটি একক সংগ্রহে স্কোপ করা হয় এবং তারা শুধুমাত্র সেই সংগ্রহ থেকে ফলাফল পুনরুদ্ধার করে। সংগ্রহ গোষ্ঠীর প্রশ্নগুলির সাথে, আপনি একই ID সহ সমস্ত সংগ্রহ সমন্বিত একটি সংগ্রহ গোষ্ঠী থেকে ফলাফল পুনরুদ্ধার করতে পারেন৷ এই বিভাগটি বর্ণনা করে কিভাবে নিরাপত্তা নিয়ম ব্যবহার করে আপনার সংগ্রহের গ্রুপের প্রশ্নগুলিকে সুরক্ষিত করতে হয়।

সংগ্রহের গোষ্ঠীর উপর ভিত্তি করে নথিগুলি সুরক্ষিত এবং অনুসন্ধান করুন

আপনার নিরাপত্তা বিধিতে, আপনাকে অবশ্যই সংগ্রহ গ্রুপের জন্য একটি নিয়ম লিখে সংগ্রহের গ্রুপের প্রশ্নগুলিকে স্পষ্টভাবে অনুমতি দিতে হবে:

  1. নিশ্চিত করুন rules_version = '2'; আপনার নিয়মের প্রথম লাইন। সংগ্রহ গোষ্ঠীর প্রশ্নগুলির জন্য নিরাপত্তা নিয়ম সংস্করণ 2-এর নতুন পুনরাবৃত্ত ওয়াইল্ডকার্ড {name=**} আচরণ প্রয়োজন৷
  2. match /{path=**}/ [COLLECTION_ID] /{doc} ব্যবহার করে আপনার সংগ্রহ গোষ্ঠীর জন্য একটি নিয়ম লিখুন।

উদাহরণ স্বরূপ, posts সাবকলেকশন সহ forum নথিতে সংগঠিত একটি ফোরাম বিবেচনা করুন:

/forums/{forumid}/posts/{postid}

{
  author: "some_auth_id",
  authorname: "some_username",
  content: "I just read a great story.",
}

এই অ্যাপ্লিকেশানে, আমরা পোস্টগুলিকে তাদের মালিকদের দ্বারা সম্পাদনাযোগ্য এবং প্রমাণীকৃত ব্যবহারকারীদের দ্বারা পাঠযোগ্য করি:

service cloud.firestore {
  match /databases/{database}/documents {
    match /forums/{forumid}/posts/{post} {
      // Only authenticated users can read
      allow read: if request.auth != null;
      // Only the post author can write
      allow write: if request.auth != null && request.auth.uid == resource.data.author;
    }
  }
}

যেকোনো প্রমাণীকৃত ব্যবহারকারী যেকোনো একক ফোরামের পোস্ট পুনরুদ্ধার করতে পারে:

db.collection("forums/technology/posts").get()

কিন্তু আপনি যদি বর্তমান ব্যবহারকারীকে সমস্ত ফোরামে তাদের পোস্টগুলি দেখাতে চান? আপনি সমস্ত posts সংগ্রহ থেকে ফলাফল পুনরুদ্ধার করতে একটি সংগ্রহ গ্রুপ ক্যোয়ারী ব্যবহার করতে পারেন:

var user = firebase.auth().currentUser;

db.collectionGroup("posts").where("author", "==", user.uid).get()

আপনার নিরাপত্তা নিয়মে, আপনাকে অবশ্যই posts সংগ্রহের গ্রুপের জন্য একটি পঠিত বা তালিকার নিয়ম লিখে এই প্রশ্নের অনুমতি দিতে হবে:

rules_version = '2';
service cloud.firestore {

  match /databases/{database}/documents {
    // Authenticated users can query the posts collection group
    // Applies to collection queries, collection group queries, and
    // single document retrievals
    match /{path=**}/posts/{post} {
      allow read: if request.auth != null;
    }
    match /forums/{forumid}/posts/{postid} {
      // Only a post's author can write to a post
      allow write: if request.auth != null && request.auth.uid == resource.data.author;

    }
  }
}

উল্লেখ্য, যাইহোক, এই নিয়মগুলি আইডি posts সহ সমস্ত সংগ্রহের ক্ষেত্রে প্রযোজ্য হবে, অনুক্রম নির্বিশেষে। উদাহরণস্বরূপ, এই নিয়মগুলি নিম্নলিখিত সমস্ত posts সংগ্রহের ক্ষেত্রে প্রযোজ্য:

  • /posts/{postid}
  • /forums/{forumid}/posts/{postid}
  • /forums/{forumid}/subforum/{subforumid}/posts/{postid}

একটি ক্ষেত্রের উপর ভিত্তি করে নিরাপদ সংগ্রহ গ্রুপ প্রশ্ন

একক-সংগ্রহের প্রশ্নগুলির মতো, সংগ্রহের গোষ্ঠীর প্রশ্নগুলিকে অবশ্যই আপনার নিরাপত্তা নিয়ম দ্বারা নির্ধারিত সীমাবদ্ধতাগুলি পূরণ করতে হবে। উদাহরণস্বরূপ, আমরা প্রতিটি ফোরাম পোস্টে একটি published ক্ষেত্র যোগ করতে পারি যেমন আমরা উপরের stories উদাহরণে করেছি:

/forums/{forumid}/posts/{postid}

{
  author: "some_auth_id",
  authorname: "some_username",
  content: "I just read a great story.",
  published: false
}

আমরা তারপর published স্ট্যাটাস এবং পোস্ট author উপর ভিত্তি করে posts সংগ্রহ গ্রুপের জন্য নিয়ম লিখতে পারি:

rules_version = '2';
service cloud.firestore {

  match /databases/{database}/documents {

    // Returns `true` if the requested post is 'published'
    // or the user authored the post
    function authorOrPublished() {
      return resource.data.published == true || request.auth.uid == resource.data.author;
    }

    match /{path=**}/posts/{post} {

      // Anyone can query published posts
      // Authors can query their unpublished posts
      allow list: if authorOrPublished();

      // Anyone can retrieve a published post
      // Authors can retrieve an unpublished post
      allow get: if authorOrPublished();
    }

    match /forums/{forumid}/posts/{postid} {
      // Only a post's author can write to a post
      allow write: if request.auth.uid == resource.data.author;
    }
  }
}

এই নিয়মগুলির সাহায্যে, ওয়েব, অ্যাপল এবং অ্যান্ড্রয়েড ক্লায়েন্টরা নিম্নলিখিত প্রশ্নগুলি করতে পারে:

  • যে কেউ একটি ফোরামে প্রকাশিত পোস্ট পুনরুদ্ধার করতে পারেন:

    db.collection("forums/technology/posts").where('published', '==', true).get()
    
  • যে কেউ সমস্ত ফোরাম জুড়ে একজন লেখকের প্রকাশিত পোস্ট পুনরুদ্ধার করতে পারেন:

    db.collectionGroup("posts").where("author", "==", "some_auth_id").where('published', '==', true).get()
    
  • লেখকরা সমস্ত ফোরাম জুড়ে তাদের প্রকাশিত এবং অপ্রকাশিত পোস্টগুলি পুনরুদ্ধার করতে পারেন:

    var user = firebase.auth().currentUser;
    
    db.collectionGroup("posts").where("author", "==", user.uid).get()
    

সংগ্রহের গোষ্ঠী এবং নথির পথের উপর ভিত্তি করে নথিগুলি সুরক্ষিত এবং অনুসন্ধান করুন

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

একটি অ্যাপ্লিকেশন বিবেচনা করুন যা বেশ কয়েকটি স্টক এবং ক্রিপ্টোকারেন্সি এক্সচেঞ্জের মধ্যে প্রতিটি ব্যবহারকারীর লেনদেনের ট্র্যাক রাখে:

/users/{userid}/exchange/{exchangeid}/transactions/{transaction}

{
  amount: 100,
  exchange: 'some_exchange_name',
  timestamp: April 1, 2019 at 12:00:00 PM UTC-7,
  user: "some_auth_id",
}

user ক্ষেত্রটি লক্ষ্য করুন। যদিও আমরা জানি কোন ব্যবহারকারী নথির পথ থেকে একটি transaction নথির মালিক, আমরা প্রতিটি transaction নথিতে এই তথ্যটি নকল করি কারণ এটি আমাদের দুটি জিনিস করতে দেয়:

  • সংগ্রহের গোষ্ঠীর প্রশ্নগুলি লিখুন যা নথিগুলির মধ্যে সীমাবদ্ধ যা তাদের নথির পাথে একটি নির্দিষ্ট /users/{userid} অন্তর্ভুক্ত করে৷ যেমন:

    var user = firebase.auth().currentUser;
    // Return current user's last five transactions across all exchanges
    db.collectionGroup("transactions").where("user", "==", user).orderBy('timestamp').limit(5)
    
  • transactions সংগ্রহ গ্রুপের সমস্ত প্রশ্নের জন্য এই সীমাবদ্ধতা প্রয়োগ করুন যাতে একজন ব্যবহারকারী অন্য ব্যবহারকারীর transaction নথি পুনরুদ্ধার করতে না পারে৷

আমরা আমাদের নিরাপত্তা নিয়মে এই বিধিনিষেধ প্রয়োগ করি এবং user ক্ষেত্রের জন্য ডেটা বৈধতা অন্তর্ভুক্ত করি:

rules_version = '2';
service cloud.firestore {

  match /databases/{database}/documents {

    match /{path=**}/transactions/{transaction} {
      // Authenticated users can retrieve only their own transactions
      allow read: if resource.data.user == request.auth.uid;
    }

    match /users/{userid}/exchange/{exchangeid}/transactions/{transaction} {
      // Authenticated users can write to their own transactions subcollections
      // Writes must populate the user field with the correct auth id
      allow write: if userid == request.auth.uid && request.data.user == request.auth.uid
    }
  }
}

পরবর্তী পদক্ষেপ