2014-07-09 13 views
7

Chúng tôi đã phát triển mã về cơ bản trả về dữ liệu cho quyền của người dùng trên một thực thể. Ví dụ, một thực thể có thể là một trong những cách sau:Loại dữ liệu nào để sử dụng để lưu trữ quyền của người dùng

-Company 
-Contact 
-Project 
-Issue etc... 

Sau đó chúng ta có thể gán các chính sách (và một người có thể nhận được nhiều chính sách) cho phép người dùng thực hiện một hành động:

-Create 
-Edit 
-Delete 
-Export 

Vì vậy, về cơ bản, một chính sách có thể nói rằng người dùng A có quyền tạo công ty, nhưng một chính sách khác mà cùng một người dùng này đã nói rằng anh ta không có quyền tạo công ty. Trong trường hợp này, chúng tôi có các quyền cho phép trước các quyền không cho phép. Trong ví dụ này, anh/cô ấy sẽ được phép tạo một công ty.

Vì vậy, về cơ bản bạn kết thúc với dữ liệu như vậy:

Policy1 Company Create Yes 
Policy1 Company Edit Yes 
Policy1 Company Delete No 
Policy2 Company Create No 
Policy2 Company Edit Yes 
Policy2 Company Delete No 

Tôi có một câu hỏi mà chúng tôi sử dụng để quay trở lại sự cho phép của người dùng này dựa trên các quy tắc chúng tôi đã thảo luận là gì.

Trong trường hợp này chạy truy vấn kết quả sẽ là:

Company create yes 
Company edit yes 
Company delete no 

ứng dụng của chúng tôi không chỉ là một chút yes/no cho dù họ có thể thực hiện hành động hay không. Chúng tôi chỉ có/không/chỉ chủ sở hữu (đối với hồ sơ chỉ nên được chủ sở hữu chỉnh sửa/xóa. Truy vấn của chúng tôi rất tuyệt và đang trả lại dữ liệu chính xác của chúng tôi. về cơ bản nói:

với một thực thể (công ty) đưa ra một hành động (tạo) giá trị là những gì cơ bản vào cuối ngày tôi muốn xây dựng một ma trận mà trông như thế này:.

  Create  Edit  Delete 
Company  Yes  Owner Only Yes 
Contact  No  No   No 
Project  Yes  Yes   Owner Only 

các các hàng trên cột đầu tiên đại diện cho thực thể, các cột sau đó đại diện cho các hành động (tạo, chỉnh sửa, xóa) Kết hợp của chỉ mục 2 cho ví dụ: [Company][Create] = Yes sẽ cung cấp cho bạn quyền của hành động dựa trên pháp nhân.

Vì vậy, kiểu dữ liệu nào phù hợp với mô hình này, nơi tôi có thể thực hiện một số chỉ mục như: [Contact][Edit]=No. Chúng tôi cũng phải phiên đối tượng này/đưa ra một cách (có thể động) để có được kết quả dựa trên một thực thể và hành động.

Tôi nghĩ rằng phiên sẽ tốt để chúng tôi có thể kiểm tra các quyền một lần và chỉ một lần cho đến khi người dùng đăng xuất.

Trả lời

2

Chúng tôi đã kết thúc với:

public class EntityPermission 
    { 
     private readonly List<GetUserPermissionsResult> _userPermissionDataSet; 
     private readonly Dictionary<int, Dictionary<int, int>> _permissions; 
     /// <summary> 
     /// Constructor to generate permissions for a user 
     /// </summary> 
     /// <param name="ds"> 
     /// Dataset of type List GetUserPermissionsResult 
     /// based on a stored procedure which brings back the 
     /// valid permissions of a user. 
     /// The result is a matrix of size [Enitities] * [Actions] 
     /// Where each entity action [index] is the value (right). 
     /// In general terms, the entity e with action a has right r. 
     /// </param> 
     public EntityPermission(List<GetUserPermissionsResult> ds) 
     { 
      _userPermissionDataSet = ds; 
      _permissions = new Dictionary<int, Dictionary<int, int>>(); 
      SetPermissions(); 
     } 

     /// <summary> 
     /// Called from the constructor of EntityPermission. 
     /// This method fills our matrix of size entity * action with 
     /// the valid rights. 
     /// </summary> 
     public void SetPermissions() 
     { 
      var dt = _userPermissionDataSet; 
      for (int i = 1; i<=Enum.GetNames(typeof(Module)).Length; i++) 
      { 
       var actionDictionary = new Dictionary<int, int>(); 
       for (int j = 1; j<=Enum.GetNames(typeof(ActionEnum)).Length; j++) 
       { 
        var value = (from a in dt where a.EntityID == i && a.ActionID == j select a.Answer).FirstOrDefault(); 
        if (value != null) 
         actionDictionary.Add(j , (int) value); 
        else actionDictionary.Add(j, (int)Answer.No); 
       } 
       _permissions.Add(i, actionDictionary); 
      } 
     } 

     /// <summary> 
     /// Method to get the rights provided an entity (a module) 
     /// and an action on that module. 
     /// </summary> 
     /// <param name="entityIdKey"></param> 
     /// <param name="actionIdKey"></param> 
     /// <returns></returns> 
     public int GetPermission(int entityIdKey, int actionIdKey) 
     { 
      return _permissions[entityIdKey][actionIdKey]; 
     } 
    } 

Các readonly List<GetUserPermissionsResult> là một loại trở về từ một sproc đó quay trở lại một ma trận dựa trên câu hỏi của tôi - mà không cần quá nhiều chi tiết:

SELECT 
    e.EntityID AS EntityID, 
    a.ActionID AS ActionID, 
    CASE MAX(ar.[Rank]) 
     WHEN 3 THEN 1 --yes 
     WHEN 2 THEN 3 --originator only 
     WHEN 1 THEN 2 --no 
    END AS [Answer] 
FROM 
.... 

sproc này đã có một loạt các tham gia nhưng về cơ bản được phân nhóm theo những điều sau đây:

GROUP BY 
    e.EntityID, 
    a.ActionID 

Điều này đảm bảo chúng tôi nhận được một hành động cho mỗi mô-đun (thực thể).

Chúng tôi lưu trữ đối tượng này như một phần của phiên của người dùng:

public EntityPermission Permission { get; set; }

Và sau đó chúng tôi chỉ đơn giản là có thể thực hiện cuộc gọi đến GetPermission để có được kết quả:

if (((int)Answer.Yes == 
       MySession.Current.Permission.GetPermission((int)Module.SubProject, (int)ActionEnum.Edit)) 
3

Đây không phải là câu trả lời cuối cùng, nhưng tôi đã nghĩ về điều này và có lẽ tôi có thể nhận được một số phản hồi. Dưới đây là những gì tôi đã đưa ra:

Tôi đã suy nghĩ về cách lưu trữ các quyền và tôi tin rằng tôi đã đưa ra một cái gì đó mà chỉ có thể làm việc.

Tôi tiếp tục suy nghĩ trong tất cả những điều này - tất cả những gì tôi cần là ma trận 2d ... sau đó hiển nhiên đánh tôi, tại sao chúng ta không sử dụng ma trận int 2d đơn giản? Nó hoạt động, ít nhất là trên giấy nó.
Như bạn đã biết, chúng tôi có một số enums:

Modules   Answer     Action 
Contact = 1  Yes = 1    Create = 1 
Corp = 2   No = 2     Edit = 2 
Company = 3  Originator Only = 3 Delete = 3 
Program = 4        View = 4 
Project = 5        List =5 
SubProject = 6       Export = 6 
Issue = 7  
LL = 8  
User = 9   

Trong trường hợp này chúng ta có 9 mô-đun với 6 loại hành động, do đó chúng ta cần một ma trận kích thước [9x6] để tạo ra 54 mục có thể dựa vào ma trận [ i, j]. Điều này sẽ hoạt động ngay cả khi chúng tôi đã thêm nhiều mô-đun và nhiều hành động khác.

Các loại chỉ đơn giản là: int[,] permissions = new int[Enum.GetNames(typeof(Modules)).Length, Enum.GetNames(typeof(Action)).Length];

: dịch chỉ đơn giản là để: int[,] permissions = new int[9,6]

Cho đến nay điều này sẽ cho chúng ta những ma trận như một ma trận rỗng. Chúng ta phải nhớ rằng các mảng/ma trận trong C# là số không dựa trên ... đó là tốt. Chúng tôi đã có một thủ tục lưu trữ mà trả về dữ liệu như vậy:

Module  Action   Answer 
1 (Contact) 1 (Create)  1 (Yes) 
1 (Contact) 2 (Edit)  1 (Yes) 
1 (Contact) 3 (Delete)  2 (No) 
…..  
2 (Corp)  1 (Create)  1 (Yes) 
2 (Corp)  2 (Edit)  1 (Yes) 
Etc…etc… 

Vì vậy bây giờ để điền vào mảng chúng ta có những điều sau đây, đây chỉ là C# mã giả:

for(int i=0; i<Enum.GetNames(typeof(Modules)).Length; i++) { 
    Reader.read(); //read the first row from the database 
    For(int j=0; j<Enum.GetNames(typeof(Action)).Length; j++) { 
     Permissions[i,j] = reader[“Answer”]; //assign the answer from the returned row to the array 
     If(j<Enum.GetNames(typeof(Action)).Length-1) { 
      Reader.read(); //read next row in database 
     } //end if condition 
    } //end for j 
} //end for i 

Vòng lặp này sẽ chỉ đơn giản là sản xuất kết quả của việc này:

   1 Create 2 Edit 3 Delete 4 View 5 List 6 Export 
1(Contact)  1   1  2   1 1   1 
2(Corp)  1   3  2   1 1   1 
3(Company)  1   1  1   1 1   1 
4(Program)  1   1  1   1 1   1 
5(Project)  1   1  2   1 1   1 
6(SubProject) 1   1  2   1 1   1 
7(Issues)  1   1  1   2 1   1 
8(LL)   1   1  1   1 1   1 
9(User)  2   2  2   1 2   2 

Đây sẽ là mỗi người dùng ... Và đây chính xác là những gì tôi muốn vì tôi muốn viết mã tương tự như này (nhớ đây chỉ là pseduo):

If(MySession.Current.Permission[(int)Module.Contact – 1, (int)Action.Create] == (int)Answer.Yes) 
{ 
    //this allows contact create 
} 

Điều này rất linh hoạt vì chúng tôi có khả năng thêm bất kỳ mô-đun mới nào mà không ảnh hưởng gì. Tôi có thể tham khảo mọi thứ chỉ đơn giản bằng cách Permission[Module.ModuleIWant – 1, Action.ActionIWant – 1].

Chúng tôi chỉ đơn giản đảm bảo rằng chúng tôi lấy 1 cách xa vì mảng không dựa trên… Chúng tôi không cần bất kỳ điều gì khác. Đó có lẽ không phải là giải pháp tốt nhất nhưng tôi nghĩ rằng nó có thể làm việc ...

Các vấn đề liên quan