ব্যবহারকারী এবং গোষ্ঠীর জন্য নিরাপদ ডেটা অ্যাক্সেস

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

সমাধান: ভূমিকা-ভিত্তিক অ্যাক্সেস নিয়ন্ত্রণ

আপনার অ্যাপে ভূমিকা-ভিত্তিক অ্যাক্সেস নিয়ন্ত্রণ বাস্তবায়নের জন্য আপনি ক্লাউড ফায়ারস্টোরের ডেটা মডেলের পাশাপাশি কাস্টম নিরাপত্তা নিয়মের সুবিধা নিতে পারেন।

ধরুন আপনি একটি সহযোগিতামূলক লেখার অ্যাপ্লিকেশন তৈরি করছেন যাতে ব্যবহারকারীরা নিম্নলিখিত নিরাপত্তা প্রয়োজনীয়তাগুলির সাথে "গল্প" এবং "মন্তব্য" তৈরি করতে পারে:

  • প্রতিটি গল্পের একজন মালিক থাকে এবং "লেখক", "মন্তব্যকারী" এবং "পাঠক" এর সাথে ভাগ করা যায়।
  • পাঠকরা শুধুমাত্র গল্প এবং মন্তব্য দেখতে পারেন. তারা কিছুই সম্পাদনা করতে পারে না।
  • মন্তব্যকারীদের পাঠকদের সমস্ত অ্যাক্সেস রয়েছে এবং তারা একটি গল্পে মন্তব্যও যোগ করতে পারে।
  • লেখকদের মন্তব্যকারীদের সমস্ত অ্যাক্সেস রয়েছে এবং তারা গল্পের বিষয়বস্তুও সম্পাদনা করতে পারে।
  • মালিকরা গল্পের যেকোনো অংশ সম্পাদনার পাশাপাশি অন্যান্য ব্যবহারকারীদের অ্যাক্সেস নিয়ন্ত্রণ করতে পারে।

ডেটা স্ট্রাকচার

ধরে নিন আপনার অ্যাপের একটি stories সংগ্রহ রয়েছে যেখানে প্রতিটি নথি একটি গল্পের প্রতিনিধিত্ব করে। প্রতিটি গল্পের একটি comments উপ-সংগ্রহও রয়েছে যেখানে প্রতিটি নথি সেই গল্পের একটি মন্তব্য।

অ্যাক্সেস রোলগুলির ট্র্যাক রাখতে, একটি roles ক্ষেত্র যুক্ত করুন যা ভূমিকাগুলিতে ব্যবহারকারী আইডিগুলির একটি মানচিত্র:

/গল্প/{storyid}

{
  title: "A Great Story",
  content: "Once upon a time ...",
  roles: {
    alice: "owner",
    bob: "reader",
    david: "writer",
    jane: "commenter"
    // ...
  }
}

মন্তব্যে শুধুমাত্র দুটি ক্ষেত্র রয়েছে, লেখকের ব্যবহারকারী আইডি এবং কিছু বিষয়বস্তু:

/story/{storyid}/comments/{commentid}

{
  user: "alice",
  content: "I think this is a great story!"
}

নিয়ম

এখন যেহেতু আপনার ডেটাবেসে ব্যবহারকারীদের ভূমিকা রেকর্ড করা আছে, সেগুলি যাচাই করার জন্য আপনাকে নিরাপত্তা নিয়ম লিখতে হবে। এই নিয়মগুলি অনুমান করে যে অ্যাপটি Firebase Auth ব্যবহার করে যাতে request.auth.uid ভেরিয়েবলটি ব্যবহারকারীর আইডি।

ধাপ 1 : একটি মৌলিক নিয়ম ফাইল দিয়ে শুরু করুন, যার মধ্যে গল্প এবং মন্তব্যের জন্য খালি নিয়ম রয়েছে:

service cloud.firestore {
   match /databases/{database}/documents {
     match /stories/{story} {
         // TODO: Story rules go here...

         match /comments/{comment} {
            // TODO: Comment rules go here...
         }
     }
   }
}

ধাপ 2 : একটি সাধারণ write নিয়ম যোগ করুন যা মালিকদের গল্পের উপর সম্পূর্ণ নিয়ন্ত্রণ দেয়। সংজ্ঞায়িত ফাংশনগুলি ব্যবহারকারীর ভূমিকা নির্ধারণ করতে এবং নতুন নথিগুলি বৈধ হলে:

service cloud.firestore {
   match /databases/{database}/documents {
     match /stories/{story} {
        function isSignedIn() {
          return request.auth != null;
        }

        function getRole(rsc) {
          // Read from the "roles" map in the resource (rsc).
          return rsc.data.roles[request.auth.uid];
        }

        function isOneOfRoles(rsc, array) {
          // Determine if the user is one of an array of roles
          return isSignedIn() && (getRole(rsc) in array);
        }

        function isValidNewStory() {
          // Valid if story does not exist and the new story has the correct owner.
          return resource == null && isOneOfRoles(request.resource, ['owner']);
        }

        // Owners can read, write, and delete stories
        allow write: if isValidNewStory() || isOneOfRoles(resource, ['owner']);

         match /comments/{comment} {
            // ...
         }
     }
   }
}

ধাপ 3 : এমন নিয়ম লিখুন যা যেকোনো ভূমিকার ব্যবহারকারীকে গল্প এবং মন্তব্য পড়তে দেয়। পূর্ববর্তী ধাপে সংজ্ঞায়িত ফাংশনগুলি ব্যবহার করে নিয়মগুলি সংক্ষিপ্ত এবং পাঠযোগ্য রাখে:

service cloud.firestore {
   match /databases/{database}/documents {
     match /stories/{story} {
        function isSignedIn() {
          return request.auth != null;
        }

        function getRole(rsc) {
          return rsc.data.roles[request.auth.uid];
        }

        function isOneOfRoles(rsc, array) {
          return isSignedIn() && (getRole(rsc) in array);
        }

        function isValidNewStory() {
          return resource == null
            && request.resource.data.roles[request.auth.uid] == 'owner';
        }

        allow write: if isValidNewStory() || isOneOfRoles(resource, ['owner']);

        // Any role can read stories.
        allow read: if isOneOfRoles(resource, ['owner', 'writer', 'commenter', 'reader']);

        match /comments/{comment} {
          // Any role can read comments.
          allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                                      ['owner', 'writer', 'commenter', 'reader']);
        }
     }
   }
}

ধাপ 4 : গল্প লেখক, মন্তব্যকারী এবং মালিকদের মন্তব্য পোস্ট করার অনুমতি দিন। মনে রাখবেন যে এই নিয়মটিও যাচাই করে যে মন্তব্যের owner অনুরোধকারী ব্যবহারকারীর সাথে মেলে, যা ব্যবহারকারীদের একে অপরের মন্তব্য লিখতে বাধা দেয়:

service cloud.firestore {
   match /databases/{database}/documents {
     match /stories/{story} {
        function isSignedIn() {
          return request.auth != null;
        }

        function getRole(rsc) {
          return rsc.data.roles[request.auth.uid];
        }

        function isOneOfRoles(rsc, array) {
          return isSignedIn() && (getRole(rsc) in array);
        }

        function isValidNewStory() {
          return resource == null
            && request.resource.data.roles[request.auth.uid] == 'owner';
        }

        allow write: if isValidNewStory() || isOneOfRoles(resource, ['owner'])
        allow read: if isOneOfRoles(resource, ['owner', 'writer', 'commenter', 'reader']);

        match /comments/{comment} {
          allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                                      ['owner', 'writer', 'commenter', 'reader']);

          // Owners, writers, and commenters can create comments. The
          // user id in the comment document must match the requesting
          // user's id.
          //
          // Note: we have to use get() here to retrieve the story
          // document so that we can check the user's role.
          allow create: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                                        ['owner', 'writer', 'commenter'])
                        && request.resource.data.user == request.auth.uid;
        }
     }
   }
}

ধাপ 5 : লেখকদের গল্পের বিষয়বস্তু সম্পাদনা করার ক্ষমতা দিন, কিন্তু গল্পের ভূমিকা সম্পাদনা করতে বা নথির অন্য কোনো বৈশিষ্ট্য পরিবর্তন করতে পারবেন না। এর জন্য গল্প write নিয়মকে create , update এবং delete জন্য আলাদা নিয়মে বিভক্ত করা প্রয়োজন কারণ লেখকরা শুধুমাত্র গল্প আপডেট করতে পারেন:

service cloud.firestore {
   match /databases/{database}/documents {
     match /stories/{story} {
        function isSignedIn() {
          return request.auth != null;
        }

        function getRole(rsc) {
          return rsc.data.roles[request.auth.uid];
        }

        function isOneOfRoles(rsc, array) {
          return isSignedIn() && (getRole(rsc) in array);
        }

        function isValidNewStory() {
          return request.resource.data.roles[request.auth.uid] == 'owner';
        }

        function onlyContentChanged() {
          // Ensure that title and roles are unchanged and that no new
          // fields are added to the document.
          return request.resource.data.title == resource.data.title
            && request.resource.data.roles == resource.data.roles
            && request.resource.data.keys() == resource.data.keys();
        }

        // Split writing into creation, deletion, and updating. Only an
        // owner can create or delete a story but a writer can update
        // story content.
        allow create: if isValidNewStory();
        allow delete: if isOneOfRoles(resource, ['owner']);
        allow update: if isOneOfRoles(resource, ['owner'])
                      || (isOneOfRoles(resource, ['writer']) && onlyContentChanged());
        allow read: if isOneOfRoles(resource, ['owner', 'writer', 'commenter', 'reader']);

        match /comments/{comment} {
          allow read: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                                      ['owner', 'writer', 'commenter', 'reader']);
          allow create: if isOneOfRoles(get(/databases/$(database)/documents/stories/$(story)),
                                        ['owner', 'writer', 'commenter'])
                        && request.resource.data.user == request.auth.uid;
        }
     }
   }
}

সীমাবদ্ধতা

উপরে দেখানো সমাধানটি নিরাপত্তা বিধি ব্যবহার করে ব্যবহারকারীর ডেটা সুরক্ষিত করার প্রদর্শন করে, তবে আপনাকে নিম্নলিখিত সীমাবদ্ধতা সম্পর্কে সচেতন হতে হবে:

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