একটি সারণীতে শ্রেণিবদ্ধ অনুমতিগুলি হায়ারার্কিকাল অনুমতি stored


9

নিম্নলিখিত ডাটাবেস কাঠামো ধরে নিচ্ছেন (প্রয়োজনে সংশোধনযোগ্য) ...

এখানে চিত্র বর্ণনা লিখুন

প্রদত্ত পৃষ্ঠায় প্রদত্ত ব্যবহারকারীর জন্য "কার্যকর অনুমতিগুলি" নির্ধারণ করার জন্য আমি একটি দুর্দান্ত উপায় সন্ধান করছি যা আমাকে পৃষ্ঠা এবং কার্যকর অনুমতি সহ একটি সারি ফেরত দিতে দেয়।

আমি ভাবছি যে আদর্শ সমাধানটিতে এমন একটি ফাংশন অন্তর্ভুক্ত থাকতে পারে যা বর্তমান ব্যবহারকারীর জন্য প্রদত্ত পৃষ্ঠার সারির জন্য "কার্যকর অনুমতিগুলি" মূল্যায়নের জন্য প্রয়োজনীয় পুনরাবৃত্তি সম্পাদনের জন্য একটি সিটিই ব্যবহার করে।

পটভূমি এবং বাস্তবায়নের বিশদ

উপরোক্ত স্কিমাটি একটি বিষয়বস্তু পরিচালনা সিস্টেমের জন্য একটি সূচনা পয়েন্ট উপস্থাপন করে যাতে ব্যবহারকারীদের ভূমিকা থেকে সরানো এবং মুছে ফেলার মাধ্যমে অনুমতি দেওয়া যেতে পারে।

সিস্টেমের সংস্থানসমূহ (উদাহরণস্বরূপ পৃষ্ঠাগুলি) সেই ভূমিকার সাথে যুক্ত ব্যবহারকারীদের গোষ্ঠী যা অনুমতি দেয় তা মঞ্জুর করার জন্য ভূমিকার সাথে জড়িত।

ধারণাটি হ'ল কোনও ব্যবহারকারীকে সমস্ত ভূমিকা অস্বীকার করে এবং গাছের মূল স্তরের পৃষ্ঠাটিকে সেই ভূমিকার সাথে যুক্ত করে এবং তারপরে সেই ভূমিকার সাথে ব্যবহারকারীকে যুক্ত করে সহজেই লকআপ করতে সক্ষম হয়।

এটি (যেমন উদাহরণস্বরূপ) কোম্পানির জন্য কাজ করা কোনও ঠিকাদার দীর্ঘকাল ধরে উপলব্ধ না থাকায় অনুমতি কাঠামোটি স্থানে থাকার অনুমতি দেয়, এটি তখন কেবল সেই ভূমিকা থেকে ব্যবহারকারীকে সরিয়ে দিয়ে তাদের মূল অনুমতিগুলি একই মঞ্জুরি দেবে allow ।

অনুমতিগুলি নিয়মিত ACL ধরণের বিধিগুলির ভিত্তিতে হয় যা এই নিয়মগুলি অনুসরণ করে ফাইল সিস্টেমে প্রয়োগ হতে পারে।

সিআরইউডি অনুমতিগুলি হ্রাসযোগ্য বিট হতে হবে যাতে উপলভ্য মানগুলি সত্য, মিথ্যা, যেখানে নিম্নলিখিতটি সত্য তা সংজ্ঞায়িত হয় না:

  • false + काहीही = মিথ্যা
  • সত্য + সংজ্ঞায়িত = সত্য
  • সত্য + সত্য = সত্য
  • সংজ্ঞায়িত না + সংজ্ঞায়িত = সংজ্ঞায়িত নয়
অনুমতিগুলির মধ্যে যদি কোনওটি মিথ্যা হয় -> মিথ্যা 
অন্য কোনও যদি সত্য হয় -> সত্য
অন্য (সমস্ত সংজ্ঞায়িত নয়) -> মিথ্যা

অন্য কথায় আপনি যদি কোনও ভূমিকা সদস্যতার মাধ্যমে মঞ্জুর না হন এবং কোনও অস্বীকৃত নিয়ম একটি অনুমতি নিয়মকে ওভাররাইড না করে আপনি কোনও কিছুর জন্য অনুমতি পাবেন না।

এই প্রয়োগ করা অনুমতিগুলির "সেট" হ'ল গাছের উপর প্রয়োগ করা হয় এবং বর্তমান পৃষ্ঠায় অন্তর্ভুক্ত সমস্ত অনুমতি থাকে, অন্য কথায়: যদি এই পৃষ্ঠায় গাছের কোনও পৃষ্ঠায় কোনও মিথ্যা প্রয়োগ হয় তবে ফলাফলটি মিথ্যা তবে এখানে পুরো গাছটিকে যদি সংজ্ঞায়িত না করা হয় তবে বর্তমান পৃষ্ঠায় একটি সত্য নিয়ম রয়েছে ফলাফল এখানে সত্য হলেও এটি পিতামাতার পক্ষে মিথ্যা।

আমি সম্ভব হলে ডিবি কাঠামোটি আলগাভাবে রাখতে চাই, এও মনে রাখবেন যে আমার লক্ষ্যটি এখানে কিছু করতে সক্ষম হ'ল: select * from pages where effective permissions (read = true) and user = ?সুতরাং যে কোনও সমাধানে আমাকে কার্যকর অনুমতিগুলির সাথে একটি অনুসন্ধানযোগ্য সেট রাখতে সক্ষম হতে হবে কোনও উপায়ে (যতক্ষণ না মানদণ্ডগুলি নির্দিষ্ট করা যায় সেগুলি তাদের ফিরিয়ে দেওয়া alচ্ছিক)।

ধরে নেওয়া 2 পৃষ্ঠাগুলি যেখানে 1 টি অন্যের সন্তানের এবং 2 টি ভূমিকা বিদ্যমান, একটি প্রশাসক ব্যবহারকারীদের জন্য 1 এবং কেবলমাত্র পঠিত ব্যবহারকারীদের জন্য, উভয়ই কেবলমাত্র মূল স্তরের পৃষ্ঠায় লিঙ্কযুক্ত আমি প্রত্যাশিত আউটপুট হিসাবে এই জাতীয় কিছু দেখার আশা করব:

Admin user:
Id, Parent, Name, Create, Read, Update, Delete
1,  null,   Root, True  , True, True  , True 
2,  1,      Child,True  , True, True  , True 

Read only user:
Id, Parent, Name, Create, Read, Update, Delete
1,  null,   Root, False , True, False , False 
2,  1,      Child,False , True, False , False

এই প্রশ্নটি সম্পর্কে আরও আলোচনা এখানে থেকে শুরু করে মূল সাইট চ্যাট রুমে পাওয়া যাবে

উত্তর:


11

এই মডেলটি ব্যবহার করে, আমি নিম্নলিখিত উপায়ে পৃষ্ঠাগুলি সারণীকে জিজ্ঞাসা করার একটি উপায় নিয়ে এসেছি :

SELECT
  p.*
FROM
  dbo.Pages AS p
  CROSS APPLY dbo.GetPermissionStatus(p.Id, @CurrentUserId, @PermissionName) AS ps
WHERE
  ps.IsAllowed = 1
;

GetPermissionStatus ইনলাইন সারণীর-মূল্যবান ফাংশনের ফলাফলের পারেন একটি খালি সেট অথবা এক একক-কলাম সারি হতে পারে। যখন ফলাফল সেটটি খালি থাকে, তার মানে নির্দিষ্ট পৃষ্ঠা / ব্যবহারকারী / অনুমতি সংমিশ্রণের জন্য কোনও নন-নুল এন্ট্রি নেই। সম্পর্কিত পৃষ্ঠাগুলি সারিটি স্বয়ংক্রিয়ভাবে ফিল্টার হয়ে যায়।

যদি ফাংশনটি একটি সারিতে ফিরে আসে, তবে এর একমাত্র কলামে ( ইসলিউড ) একটি হয় (অর্থ সত্য ) বা 0 (অর্থ মিথ্যা )। সার্বজনীন ফিল্টার অতিরিক্তভাবে পরীক্ষা করে যে আউটপুটটিতে সারি অন্তর্ভুক্ত করার জন্য মানটি 1 হতে হবে।

ফাংশনটি কী করে:

  • নির্দিষ্ট পৃষ্ঠা এবং এর সমস্ত পিতামাতাকে এক সারি সেটে সংগ্রহ করার জন্য পৃষ্ঠাগুলির সারণিতে উপরে পদচারণা ;

  • অনুমতি কলামগুলির একটির সাথে নির্দিষ্ট ব্যবহারকারীকে অন্তর্ভুক্ত করা সমস্ত ভূমিকা সম্বলিত একটি সারি সেট তৈরি করে (তবে কেবল নন-নুল মান নয়) - বিশেষত তৃতীয় আর্গুমেন্ট হিসাবে নির্ধারিত অনুমতিের সাথে সম্পর্কিত;

  • অবশেষে, নির্দিষ্ট পৃষ্ঠায় বা এর যে কোনও পিতামাতার সাথে মেলে সুস্পষ্ট অনুমতিগুলির সম্পূর্ণ সেটটি খুঁজে পেতে RolePages টেবিলের মাধ্যমে প্রথম এবং দ্বিতীয় সেটটিতে যোগ দেয় ।

ফলাফলের সারি সেটটি অনুমতি মানগুলির আরোহী ক্রম অনুসারে বাছাই করা হয় এবং ফাংশনের ফলস্বরূপ শীর্ষতম মানটি ফিরে আসে। যেহেতু নালগুলি প্রথম পর্যায়ে ফিল্টার করা হয়, সুতরাং তালিকায় কেবল 0 ও 1 এস থাকতে পারে। সুতরাং, অনুমতিগুলির তালিকায় যদি কমপক্ষে একটি "অস্বীকার" (0) থাকে তবে এটি ফাংশনের ফলাফল হবে। অন্যথায় শীর্ষস্থানীয় ফলাফলটি 1 হবে, যদি না নির্বাচিত পৃষ্ঠাগুলির সাথে সম্পর্কিত ভূমিকাগুলি সুস্পষ্টভাবে "অনুমতি দেয়" না ঘটে বা নির্দিষ্ট পৃষ্ঠা এবং ব্যবহারকারীর জন্য মোটামুটি কোনও মিলে যাওয়া এন্ট্রি না থাকে, সেক্ষেত্রে ফলাফলটি খালি হবে সারি সেট।

এটি ফাংশন:

CREATE FUNCTION dbo.GetPermissionStatus
(
  @PageId int,
  @UserId int,
  @PermissionName varchar(50)
)
RETURNS TABLE
AS
RETURN
(
  WITH
    Hierarchy AS
    (
      SELECT
        p.Id,
        p.ParentId
      FROM
        dbo.Pages AS p
      WHERE
        p.Id = @PageId

      UNION ALL

      SELECT
        p.Id,
        p.ParentId
      FROM
        dbo.Pages AS p
        INNER JOIN hierarchy AS h ON p.Id = h.ParentId
    ),
    Permissions AS
    (
      SELECT
        ur.Role_Id,
        x.IsAllowed
      FROM
        dbo.UserRoles AS ur
        INNER JOIN Roles AS r ON ur.Role_Id = r.Id
        CROSS APPLY
        (
          SELECT
            CASE @PermissionName
              WHEN 'Create' THEN [Create]
              WHEN 'Read'   THEN [Read]
              WHEN 'Update' THEN [Update]
              WHEN 'Delete' THEN [Delete]
            END
        ) AS x (IsAllowed)
      WHERE
        ur.User_Id = @UserId AND
        x.IsAllowed IS NOT NULL
    )
  SELECT TOP (1)
    perm.IsAllowed
  FROM
    Hierarchy AS h
    INNER JOIN dbo.RolePages AS rp ON h.Id = rp.Page_Id
    INNER JOIN Permissions AS perm ON rp.Role_Id = perm.Role_Id
  ORDER BY
    perm.IsAllowed ASC
);

পরীক্ষা ক্ষেত্রে

  • DDL:

    CREATE TABLE dbo.Users (
      Id       int          PRIMARY KEY,
      Name     varchar(50)  NOT NULL,
      Email    varchar(100)
    );
    
    CREATE TABLE dbo.Roles (
      Id       int          PRIMARY KEY,
      Name     varchar(50)  NOT NULL,
      [Create] bit,
      [Read]   bit,
      [Update] bit,
      [Delete] bit
    );
    
    CREATE TABLE dbo.Pages (
      Id       int          PRIMARY KEY,
      ParentId int          FOREIGN KEY REFERENCES dbo.Pages (Id),
      Name     varchar(50)  NOT NULL
    );
    
    CREATE TABLE dbo.UserRoles (
      User_Id  int          NOT NULL  FOREIGN KEY REFERENCES dbo.Users (Id),
      Role_Id  int          NOT NULL  FOREIGN KEY REFERENCES dbo.Roles (Id),
      PRIMARY KEY (User_Id, Role_Id)
    );
    
    CREATE TABLE dbo.RolePages (
      Role_Id  int          NOT NULL  FOREIGN KEY REFERENCES dbo.Roles (Id),
      Page_Id  int          NOT NULL  FOREIGN KEY REFERENCES dbo.Pages (Id),
      PRIMARY KEY (Role_Id, Page_Id)
    );
    GO
  • ডেটা সন্নিবেশ:

    INSERT INTO
      dbo.Users (ID, Name)
    VALUES
      (1, 'User A')
    ;
    INSERT INTO
      dbo.Roles (ID, Name, [Create], [Read], [Update], [Delete])
    VALUES
      (1, 'Role R', NULL, 1, 1, NULL),
      (2, 'Role S', 1   , 1, 0, NULL)
    ;
    INSERT INTO
      dbo.Pages (Id, ParentId, Name)
    VALUES
      (1, NULL, 'Page 1'),
      (2, 1, 'Page 1.1'),
      (3, 1, 'Page 1.2')
    ;
    INSERT INTO
      dbo.UserRoles (User_Id, Role_Id)
    VALUES
      (1, 1),
      (1, 2)
    ;
    INSERT INTO
      dbo.RolePages (Role_Id, Page_Id)
    VALUES
      (1, 1),
      (2, 3)
    ;
    GO

    সুতরাং, কেবলমাত্র একজন ব্যবহারকারী ব্যবহৃত হয়েছে তবে এটি দুটি চরিত্রের জন্য বরাদ্দ করা হয়েছে, শিশু অবজেক্টগুলিতে মিশ্রিত যুক্তি পরীক্ষা করতে দুটি ভূমিকার মধ্যে অনুমতি মানের বিভিন্ন সংমিশ্রণ রয়েছে।

    পৃষ্ঠার শ্রেণিবিন্যাস খুব সহজ: একটি পিতা বা মাতা এবং দুটি শিশু। পিতামাতার একটি ভূমিকা সঙ্গে জড়িত, অন্য ভূমিকা সঙ্গে শিশুদের এক।

  • পরীক্ষার স্ক্রিপ্ট:

    DECLARE @CurrentUserId int = 1;
    SELECT p.* FROM dbo.Pages AS p CROSS APPLY dbo.GetPermissionStatus(p.Id, @CurrentUserId, 'Create') AS perm WHERE perm.IsAllowed = 1;
    SELECT p.* FROM dbo.Pages AS p CROSS APPLY dbo.GetPermissionStatus(p.Id, @CurrentUserId, 'Read'  ) AS perm WHERE perm.IsAllowed = 1;
    SELECT p.* FROM dbo.Pages AS p CROSS APPLY dbo.GetPermissionStatus(p.Id, @CurrentUserId, 'Update') AS perm WHERE perm.IsAllowed = 1;
    SELECT p.* FROM dbo.Pages AS p CROSS APPLY dbo.GetPermissionStatus(p.Id, @CurrentUserId, 'Delete') AS perm WHERE perm.IsAllowed = 1;
  • পরিষ্কার কর:

    DROP FUNCTION dbo.GetPermissionStatus;
    GO
    DROP TABLE dbo.UserRoles, dbo.RolePages, dbo.Users, dbo.Roles, dbo.Pages;
    GO

ফলাফল

  • তৈরির জন্য :

    Id  ParentId  Name
    --  --------  --------
    2   1         Page 1.1

    শুধুমাত্র জন্য একটি স্পষ্ট সত্য ছিল Page 1.1। পৃষ্ঠাটি "সত্য + সংজ্ঞায়িত" যুক্তি অনুসারে ফিরিয়ে দেওয়া হয়েছিল। অন্যদের "সংজ্ঞায়িত" এবং "সংজ্ঞায়িত + সংজ্ঞায়িত নয়" - তাই বাদ দেওয়া হয়েছিল।

  • পড়ার জন্য :

    Id  ParentId  Name
    --  --------  --------
    1   NULL      Page 1
    2   1         Page 1.1
    3   1         Page 1.2

    এর জন্য এবং এর জন্য সেটিংসে একটি স্পষ্ট সত্য পাওয়া গেল । সুতরাং, প্রাক্তনদের পক্ষে এটি কেবল একটি একক "সত্য" ছিল এবং পরবর্তীকালে "সত্য + সত্য" ছিল। এর জন্য স্পষ্টভাবে কোনও পড়ার অনুমতি ছিল না , সুতরাং এটি অন্য একটি "সত্য + সংজ্ঞায়িত" কেস ছিল। সুতরাং, তিনটি পৃষ্ঠাই ফিরে এসেছিল।Page 1Page 1.1Page 1.2

  • আপডেটের জন্য :

    Id  ParentId  Name
    --  --------  --------
    1   NULL      Page 1
    3   1         Page 1.2

    সেটিংস থেকে, একটি সুনির্দিষ্ট সত্য ফিরে ছিল Page 1এবং একটি মিথ্যা জন্য Page 1.1। যে পৃষ্ঠাগুলি এটি আউটপুটে তৈরি করেছিল তাদের জন্য যুক্তি পড়ার ক্ষেত্রে একই ছিল । বাদ দেওয়া সারির জন্য মিথ্যাসত্য উভয়ই পাওয়া গেল এবং সুতরাং "মিথ্যা + যে কোনও কিছু" যুক্তি কাজ করেছিল।

  • মোছার জন্য কোনও সারি ফিরে আসেনি। পিতা-মাতা এবং একটি সন্তানের সেটিংসে সুস্পষ্ট শূন্যতা ছিল এবং অন্য সন্তানের কিছুই ছিল না।

সমস্ত অনুমতি পান

এখন আপনি যদি কেবল সমস্ত কার্যকর অনুমতি ফিরিয়ে দিতে চান তবে আপনি getPermissionStatus ফাংশনটি মানিয়ে নিতে পারেন :

CREATE FUNCTION dbo.GetPermissions(@PageId int, @UserId int)
RETURNS TABLE
AS
RETURN
(
  WITH
    Hierarchy AS
    (
      SELECT
        p.Id,
        p.ParentId
      FROM
        dbo.Pages AS p
      WHERE
        p.Id = @PageId

      UNION ALL

      SELECT
        p.Id,
        p.ParentId
      FROM
        dbo.Pages AS p
        INNER JOIN hierarchy AS h ON p.Id = h.ParentId
    ),
    Permissions AS
    (
      SELECT
        ur.Role_Id,
        r.[Create],
        r.[Read],
        r.[Update],
        r.[Delete]
      FROM
        dbo.UserRoles AS ur
        INNER JOIN Roles AS r ON ur.Role_Id = r.Id
      WHERE
        ur.User_Id = @UserId
    )
  SELECT
    [Create] = ISNULL(CAST(MIN(CAST([Create] AS int)) AS bit), 0),
    [Read]   = ISNULL(CAST(MIN(CAST([Read]   AS int)) AS bit), 0),
    [Update] = ISNULL(CAST(MIN(CAST([Update] AS int)) AS bit), 0),
    [Delete] = ISNULL(CAST(MIN(CAST([Delete] AS int)) AS bit), 0)
  FROM
    Hierarchy AS h
    INNER JOIN dbo.RolePages AS rp ON h.Id = rp.Page_Id
    INNER JOIN Permissions AS perm ON rp.Role_Id = perm.Role_Id
);

ফাংশনটি চারটি কলাম রিটার্ন করে - নির্দিষ্ট পৃষ্ঠা এবং ব্যবহারকারীর জন্য কার্যকর অনুমতি। ব্যবহারের উদাহরণ:

DECLARE @CurrentUserId int = 1;
SELECT
  *
FROM
  dbo.Pages AS p
  CROSS APPLY dbo.GetPermissions(p.Id, @CurrentUserId) AS perm
;

আউটপুট:

Id  ParentId  Name      Create Read  Update Delete
--  --------  --------  ------ ----- ------ ------
1   NULL      Page 1    0      1     1      0
2   1         Page 1.1  1      1     0      0
3   1         Page 1.2  0      1     1      0
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.