নির্দিষ্ট ফিল্ডে অ্যাক্সেস নিয়ন্ত্রণ করুন

এই পৃষ্ঠায় নিরাপত্তা সংক্রান্ত নিয়ম স্ট্রাকচার করা এবং নিরাপত্তা সংক্রান্ত নিয়মের জন্য শর্ত লেখা সংক্রান্ত ধারণার উপর ভিত্তি করে ব্যাখ্যা করা হয়েছে যে কীভাবে আপনি Cloud Firestore Security Rules ব্যবহার করে এমন নিয়ম তৈরি করতে পারেন যা ক্লায়েন্টকে ডকুমেন্টের কিছু ফিল্ডে অপারেশন করার অনুমতি দেয়, কিন্তু সব ফিল্ডে নয়।

এমন সময় আসতে পারে যখন আপনি ডকুমেন্টের লেভেলে নয়, ফিল্ডের লেভেলে ডকুমেন্টে করা পরিবর্তন কন্ট্রোল করতে চান।

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

AI-এর মাধ্যমে সহায়তা পেতে, নিচের প্রম্পটটি আপনার AI কোডিং এজেন্টে (যেমন, Android Studio-তে Gemini, Antigravity, Claude Code, Codex এবং Cursor) কপি করুন। আপনি প্রম্পট কাস্টমাইজ করতে এবং আপনার এজেন্টের সাথে আইটারেট করতে পারবেন। ইনস্টলেশন সংক্রান্ত বিস্তারিত তথ্যের জন্য Firebase এজেন্ট সংক্রান্ত দক্ষতা দেখুন।

Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's Firestore data.

শুধুমাত্র নির্দিষ্ট ফিল্ডের জন্য পড়ার অ্যাক্সেসের অনুমতি দেওয়া হচ্ছে

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

কোনও ডকুমেন্টের মধ্যে এমন কিছু ফিল্ড থাকলে যা আপনি কিছু ব্যবহারকারীর থেকে লুকিয়ে রাখতে চান, তাহলে সবচেয়ে ভালো উপায় হল সেগুলি আলাদা ডকুমেন্টে রাখা। যেমন, আপনি private সাবকালেকশনে ডকুমেন্ট তৈরি করার কথা বিবেচনা করতে পারেন, যেমন:

/employees/{emp_id}

  name: "Alice Hamilton",
  department: 461,
  start_date: <timestamp>

/employees/{emp_id}/private/finances

    salary: 80000,
    bonus_mult: 1.25,
    perf_review: 4.2

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

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

ডকুমেন্ট তৈরি করার সময় ফিল্ড সীমাবদ্ধ করা

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

আপনি request.resource.data অবজেক্টের keys পদ্ধতি পরীক্ষা করে এইসব নিয়ম তৈরি করতে পারবেন। এটি হল সেইসব ফিল্ডের তালিকা যা ক্লায়েন্ট এই নতুন ডকুমেন্টে লেখার চেষ্টা করছে। hasOnly() বা hasAny()-এর মতো ফাংশনের সাথে এই ফিল্ডের সেট একত্রিত করে, আপনি এমন লজিক যোগ করতে পারবেন যা কোনও ব্যবহারকারী Rules-এ যে ধরনের ডকুমেন্ট যোগ করতে পারবেন তা সীমাবদ্ধ করে।

নতুন ডকুমেন্টে নির্দিষ্ট ফিল্ডের প্রয়োজন

ধরা যাক, আপনি নিশ্চিত করতে চান যে 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() তালিকায় সেই ফিল্ড যোগ করেন।

ফিল্ডের ধরন এনফোর্স করা হচ্ছে

Rules স্কিমাহীন হওয়ার আরেকটি প্রভাব হল, নির্দিষ্ট ফিল্ডে কোন ধরনের ডেটা স্টোর করা যাবে, সেই ব্যাপারে ডেটাবেস লেভেলে কোনও এনফোর্সমেন্ট থাকে না। এটি এমন কিছু যা আপনি নিরাপত্তা নিয়মে প্রয়োগ করতে পারেন, তবে, 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 সম্পর্কে একটি চূড়ান্ত নোট হল যে তারা ক্লায়েন্টকে একটি ডকুমেন্টে পরিবর্তন করার অনুমতি দেয়, অথবা তারা সম্পূর্ণ এডিট প্রত্যাখ্যান করে। আপনি এমন নিরাপত্তা সংক্রান্ত নিয়ম তৈরি করতে পারবেন না যা আপনার ডকুমেন্টের কিছু ফিল্ডে লেখার অনুমতি দেয় এবং একই অপারেশনে অন্যান্য ফিল্ডে লেখার অনুমতি দেয় না।