এই পৃষ্ঠাটি স্ট্রাকচারিং সিকিউরিটি রুলস এবং রাইটিং কন্ডিশনস ফর সিকিউরিটি রুলস- এর ধারণাগুলির উপর ভিত্তি করে তৈরি করা হয়েছে যাতে আপনি Cloud Firestore Security Rules ব্যবহার করে এমন নিয়ম তৈরি করতে পারেন যা ক্লায়েন্টদের একটি ডকুমেন্টের কিছু ক্ষেত্রে কাজ করার অনুমতি দেয় কিন্তু অন্য ক্ষেত্রে নয়।
এমন সময় আসতে পারে যখন আপনি কোনও নথিতে পরিবর্তনগুলি নথি স্তরে নয় বরং মাঠ স্তরে নিয়ন্ত্রণ করতে চান।
উদাহরণস্বরূপ, আপনি হয়তো একজন ক্লায়েন্টকে একটি ডকুমেন্ট তৈরি বা পরিবর্তন করার অনুমতি দিতে চাইতে পারেন, কিন্তু তাকে সেই ডকুমেন্টের কিছু নির্দিষ্ট ক্ষেত্র সম্পাদনা করার অনুমতি দিতে পারবেন না। অথবা আপনি হয়তো জোর করে বলতে চাইতে পারেন যে ক্লায়েন্ট সর্বদা যে ডকুমেন্ট তৈরি করে তাতে নির্দিষ্ট কিছু ক্ষেত্র থাকে। এই নির্দেশিকাটি Cloud Firestore Security Rules ব্যবহার করে আপনি কীভাবে এই কাজগুলির কিছু সম্পন্ন করতে পারেন তা কভার করে।
শুধুমাত্র নির্দিষ্ট ক্ষেত্রের জন্য পঠন অ্যাক্সেসের অনুমতি দেওয়া হচ্ছে
Cloud Firestore পঠনগুলি ডকুমেন্ট স্তরে সম্পাদিত হয়। আপনি হয় সম্পূর্ণ ডকুমেন্টটি পুনরুদ্ধার করতে পারবেন, অথবা আপনি কিছুই পুনরুদ্ধার করতে পারবেন না। আংশিক ডকুমেন্ট পুনরুদ্ধার করার কোনও উপায় নেই। শুধুমাত্র সুরক্ষা নিয়ম ব্যবহার করে ব্যবহারকারীদের ডকুমেন্টের মধ্যে নির্দিষ্ট ক্ষেত্রগুলি পড়া থেকে বিরত রাখা অসম্ভব।
যদি কোনও ডকুমেন্টের মধ্যে এমন কিছু ক্ষেত্র থাকে যা আপনি কিছু ব্যবহারকারীর কাছ থেকে গোপন রাখতে চান, তাহলে সবচেয়ে ভালো উপায় হবে সেগুলিকে একটি পৃথক ডকুমেন্টে রাখা। উদাহরণস্বরূপ, আপনি একটি private উপ-সংগ্রহে একটি ডকুমেন্ট তৈরি করার কথা বিবেচনা করতে পারেন যেমন:
/কর্মচারী/{emp_id}
name: "Alice Hamilton",
department: 461,
start_date: <timestamp>
/কর্মচারী/{emp_id}/ব্যক্তিগত/অর্থায়ন
salary: 80000,
bonus_mult: 1.25,
perf_review: 4.2
তারপর আপনি দুটি সংগ্রহের জন্য বিভিন্ন স্তরের অ্যাক্সেসের নিরাপত্তা নিয়ম যোগ করতে পারেন। এই উদাহরণে, আমরা কাস্টম প্রমাণীকরণ দাবি ব্যবহার করছি যাতে বলা যায় যে শুধুমাত্র Finance এর সমান কাস্টম প্রমাণীকরণ দাবির role সম্পন্ন ব্যবহারকারীরা একজন কর্মচারীর আর্থিক তথ্য দেখতে পারবেন।
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'
}
}
}
}
ডকুমেন্ট তৈরিতে ক্ষেত্র সীমাবদ্ধ করা
Cloud Firestore স্কিমালেস, অর্থাৎ ডাটাবেস স্তরে কোন ডকুমেন্টে কোন ফিল্ড আছে তার কোনও বিধিনিষেধ নেই। যদিও এই নমনীয়তা ডেভেলপমেন্টকে সহজ করে তুলতে পারে, এমন সময় আসবে যখন আপনি নিশ্চিত করতে চাইবেন যে ক্লায়েন্টরা কেবল এমন ডকুমেন্ট তৈরি করতে পারে যাতে নির্দিষ্ট ফিল্ড থাকে, অথবা অন্য কোনও ফিল্ড থাকে না।
আপনি request.resource.data অবজেক্টের keys পদ্ধতি পরীক্ষা করে এই নিয়মগুলি তৈরি করতে পারেন। এটি ক্লায়েন্ট এই নতুন ডকুমেন্টে লেখার চেষ্টা করছে এমন সমস্ত ফিল্ডের একটি তালিকা। এই ফিল্ডগুলির সেটটিকে hasOnly() বা hasAny() এর মতো ফাংশনের সাথে একত্রিত করে, আপনি লজিক যুক্ত করতে পারেন যা ব্যবহারকারী Cloud Firestore কী ধরণের ডকুমেন্ট যুক্ত করতে পারবেন তা সীমাবদ্ধ করে।
নতুন নথিতে নির্দিষ্ট ক্ষেত্রগুলির প্রয়োজনীয়তা
ধরুন আপনি নিশ্চিত করতে চান যে একটি 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() ব্যবহার করে আপনি ক্লায়েন্টদের নির্দিষ্ট ক্ষেত্রযুক্ত নথি তৈরি করা থেকে বিরত রাখতে পারেন। এই পদ্ধতিটি যদি কোনও নথিতে এই ক্ষেত্রগুলির কোনও থাকে তবে তা সত্য হিসাবে মূল্যায়ন করে, তাই আপনি সম্ভবত নির্দিষ্ট ক্ষেত্রগুলিকে নিষিদ্ধ করার জন্য ফলাফলটি অস্বীকার করতে চান।
উদাহরণস্বরূপ, নিম্নলিখিত উদাহরণে, ক্লায়েন্টদের এমন কোনও ডকুমেন্ট তৈরি করার অনুমতি নেই যাতে 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() তালিকায় সেই ক্ষেত্রটি যোগ করেন।
ক্ষেত্রের ধরণ প্রয়োগ করা
Cloud Firestore স্কিমালেস হওয়ার আরেকটি প্রভাব হল, নির্দিষ্ট ক্ষেত্রে কী ধরণের ডেটা সংরক্ষণ করা যেতে পারে তার জন্য ডাটাবেস স্তরে কোনও প্রয়োগ নেই। তবে, এটি এমন কিছু যা আপনি নিরাপত্তা নিয়মে প্রয়োগ করতে পারেন, তবে 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
}
}
}
}
ঐচ্ছিক ক্ষেত্রের জন্য প্রকার প্রয়োগ করা হচ্ছে
এটা মনে রাখা গুরুত্বপূর্ণ যে, foo অস্তিত্ব নেই এমন কোনও ডকুমেন্টে request.resource.data.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 সম্পর্কে একটি চূড়ান্ত নোট হল যে তারা হয় ক্লায়েন্টকে একটি ডকুমেন্টে পরিবর্তন করার অনুমতি দেয়, অথবা তারা সম্পূর্ণ সম্পাদনাটি প্রত্যাখ্যান করে। আপনি এমন নিরাপত্তা রুলস তৈরি করতে পারবেন না যা আপনার ডকুমেন্টের কিছু ক্ষেত্রে লেখা গ্রহণ করে এবং একই অপারেশনে অন্য ক্ষেত্রে প্রত্যাখ্যান করে।