पदानुक्रम संग्रहीत तालिका में पदानुक्रमित अनुमतियाँ


9

निम्नलिखित डेटाबेस संरचना (यदि आवश्यक हो तो परिवर्तनीय) मानकर ...

यहां छवि विवरण दर्ज करें

मैं एक दिए गए पृष्ठ पर किसी दिए गए उपयोगकर्ता के लिए "प्रभावी अनुमतियाँ" निर्धारित करने के लिए एक अच्छा तरीका ढूंढ रहा हूं जिससे मुझे पृष्ठ और प्रभावी अनुमतियों की एक पंक्ति वापस करने की अनुमति मिलती है।

मैं सोच रहा हूं कि आदर्श समाधान में एक फ़ंक्शन शामिल हो सकता है जो वर्तमान उपयोगकर्ता के लिए दिए गए पृष्ठ पंक्ति के लिए "प्रभावी अनुमतियों" का मूल्यांकन करने के लिए आवश्यक पुनरावृत्ति करने के लिए सीटीई का उपयोग करता है।

पृष्ठभूमि और कार्यान्वयन विवरण

उपरोक्त स्कीमा एक सामग्री प्रबंधन प्रणाली के लिए एक आरंभ बिंदु का प्रतिनिधित्व करता है जिसमें उपयोगकर्ताओं को जोड़कर और भूमिकाओं से हटाकर अनुमतियाँ दी जा सकती हैं।

सिस्टम में संसाधन (जैसे पृष्ठ) भूमिकाओं के साथ जुड़े हुए हैं, जो उस भूमिका से जुड़े उपयोगकर्ताओं के समूह को अनुमति देता है जो इसे अनुमति देता है।

यह विचार आसानी से एक उपयोगकर्ता को सभी भूमिका से वंचित करने और उस भूमिका में पेड़ में जड़ स्तर पृष्ठ जोड़ने और फिर उस भूमिका के लिए उपयोगकर्ता को जोड़ने में सक्षम होने के लिए है।

यह अनुमति संरचना को तब बनाए रखने की अनुमति देगा जब (उदाहरण के लिए) कंपनी के लिए काम करने वाला एक ठेकेदार लंबे समय के लिए उपलब्ध नहीं है, यह तब उपयोगकर्ता को केवल एक भूमिका से हटाकर अपनी मूल अनुमतियों के समान अनुदान के लिए भी अनुमति देगा। ।

अनुमतियाँ विशिष्ट ACL प्रकार के नियमों पर आधारित होती हैं जो इन नियमों का पालन करके फाइल सिस्टम पर लागू हो सकती हैं।

CRUD अनुमतियाँ अशक्त बिट्स हैं इसलिए उपलब्ध मान सत्य, असत्य, परिभाषित नहीं हैं जहां निम्नलिखित सत्य है:

  • झूठी + कुछ भी = झूठी
  • सत्य + परिभाषित नहीं = सत्य
  • सच्चा + सच्चा = सच्चा
  • परिभाषित नहीं + परिभाषित नहीं = परिभाषित नहीं
यदि कोई भी अनुमति गलत है -> झूठी है 
यदि कोई सत्य है -> सत्य
एल्स (सभी परिभाषित नहीं) -> गलत

दूसरे शब्दों में, आपको किसी भी चीज़ पर कोई अनुमति नहीं मिलती है जब तक कि आपको उन्हें भूमिका सदस्यता के माध्यम से प्रदान नहीं किया जाता है और एक इनकार नियम एक अनुमति नियम से आगे निकल जाता है।

अनुमतियों का "सेट" जो लागू होता है वह सभी अनुमतियाँ है जो पेड़ पर लागू होती है और वर्तमान पृष्ठ सहित, दूसरे शब्दों में: यदि कोई झूठा किसी भी भूमिका में पेड़ के किसी भी पृष्ठ पर इस पृष्ठ पर लागू होता है तो परिणाम गलत है , लेकिन अगर पूरे पेड़ को यहाँ तक परिभाषित नहीं किया गया है, तो वर्तमान पृष्ठ में एक सही नियम शामिल है, परिणाम यहाँ सच है, लेकिन माता-पिता के लिए गलत होगा।

यदि संभव हो तो मैं db संरचना को शिथिल रखना चाहूँगा, यह भी ध्यान रखें कि यहाँ मेरा लक्ष्य कुछ ऐसा करने में सक्षम होना है: select * from pages where effective permissions (read = true) and user = ?इसलिए कोई भी समाधान मुझे प्रभावी अनुमतियों के साथ एक क्वेरी सेट करने की अनुमति देने में सक्षम होना चाहिए। किसी तरह से (उन्हें वापस करना वैकल्पिक है जब तक कि मापदंड निर्दिष्ट किया जा सकता है)।

मान लें कि 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 इनलाइन तालिका-मान समारोह के परिणाम या तो एक खाली सेट या एक एकल-स्तंभ पंक्ति हो सकता है। जब परिणाम सेट खाली होता है, तो इसका मतलब है कि निर्दिष्ट पृष्ठ / उपयोगकर्ता / अनुमति संयोजन के लिए कोई गैर-पूर्ण प्रविष्टि नहीं है। संबंधित पृष्ठ पंक्ति स्वचालित रूप से फ़िल्टर की गई है।

यदि फ़ंक्शन एक पंक्ति लौटाता है, तो इसके एकमात्र कॉलम ( IsAllowed ) में 1 या ( सही अर्थ ) या 0 (मतलब गलत ) होगा। WHERE फ़िल्टर अतिरिक्त रूप से जांचता है कि पंक्ति को आउटपुट में शामिल करने के लिए मूल्य 1 होना चाहिए।

क्या कार्य करता है:

  • निर्दिष्ट पंक्ति और उसके सभी अभिभावकों को एक पंक्ति में सेट करने के लिए पदानुक्रम के ऊपर पृष्ठ तालिका चलती है ;

  • एक अन्य पंक्ति सेट बनाता है जिसमें निर्दिष्ट उपयोगकर्ता सभी भूमिकाओं को शामिल करता है, जिसमें एक अनुमति कॉलम (लेकिन केवल गैर-पूर्ण मान) के साथ शामिल है - विशेष रूप से तीसरे तर्क के रूप में निर्दिष्ट अनुमति के अनुरूप एक;

  • अंत में, पहला और दूसरा सेट, रोलपेज तालिका के माध्यम से दूसरे पृष्ठ या उसके किसी भी अभिभावक से मेल खाते हुए स्पष्ट अनुमतियों का पूरा सेट खोजने के लिए करता है।

परिणामी पंक्ति सेट को अनुमति मानों के आरोही क्रम में सॉर्ट किया जाता है और फ़ंक्शन के परिणाम के रूप में सबसे ऊपरी मान लौटाया जाता है। चूंकि नल को पहले चरण में फ़िल्टर किया जाता है, इसलिए सूची में केवल 0s और 1s शामिल हो सकते हैं। इस प्रकार, यदि अनुमतियों की सूची में कम से कम एक "इनकार" (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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.