2

I am building a C# application for a law firm. In every Form there are some Controls which only some of the users can access (for other users - those Controls will be disabled).

I have built it like this: There is a class called AuthorizedForm that inherits from Form. This class has a method called SetAuthorization, which enables all the Controls the user may access, and disables the rest. Each form in the application inherits from AuthorizedForm.

When the user logs in, the SetAuthorization method is called and receives as parameters the id of the logged in user, and a list of rules. Every rule consists of a Control, and a list of users that can access that Control.

The list is actually divided into two lists: user groups (such as lawyers, paralegals etc.) and individual users. So if, for example, I put the id of the group "Administrators" and the id of the group "lawyers" in the first list, and the id of one of the secretaries in the second list - then the Control will be defined as Enabled for all administrators and lawyers, and also for that secretary, while for the other office employees the Control will be defined as Disabled.

The list is called AuthorizationList and is actually a class that inherits from the List class of type Tuple, which receives a Control, a GroupList and a UserList (the last two are nothing but a List of type byte).

The definition of GroupList and UserList:

public class GroupList : List<byte> { }
public class UserList : List<byte> { }

The code of the AuthorizedList class (built with help from this answer):

public class AuthorizationList : List<Tuple<Control, GroupList, UserList>>
{
    public void Add(Control control, GroupList groups, UserList users)
    {
        Add(new Tuple<Control, GroupList, UserList>(control, groups, users));
    }
}

The AuthorizedForm class:

public class AuthorizedForm : Form
{
    public void SetAuthorization(User loggedInUser, AuthorizationList authorizationList)
    {
        foreach (var rule in authorizationList)
        {
            bool isAuthorized = false;

            foreach (byte group in rule.Item2)
            {
                if (group == loggedInUser.Group)
                {
                    isAuthorized = true;
                    break;
                }
            }

            if (!isAuthorized)
            {
                foreach (byte user in rule.Item3)
                {
                    if (user == loggedInUser.Id)
                    {
                        isAuthorized = true;
                        break;
                    }
                }
            }

            if(!isAuthorized)
            {
                rule.Item1.Enabled = false;
            }
        }
    }
}

The call for the SetAuthorization from the login function:

if (user.isLoggedIn)
{
    SetAuthorization(user, new AuthorizationList()
    {
        /*
          CONTROL  |    GROUPS IDS LIST    |     USER IDS LIST
        */        
        { textBox1, new GroupList() { 1, 2, 3 }, new UserList() { 4 } },
        { textBox2, new GroupList() { 1, 2 },    new UserList() { 4 } },
        { button1,  new GroupList() { 1 },       new UserList() { 4, 3 } },
    });
}

Now, I want to let AuthorizationList be also of type Tuple which receives a Control and a GroupList only, or a Control and a UserList only, so I can set permissions for user groups only, or for individual users only.

I can not think of a way to do this without significantly changing the code I have written. Is there a way to do this in a relatively easy and elegant way? If not, how would you suggest to do it?

Community
  • 1
  • 1
Michael Haddad
  • 4,085
  • 7
  • 42
  • 82

3 Answers3

4

How about using an object that isn't a Tuple to hold the Authorizations, it's more elegant than Tuple<>:

public class GroupList : List<byte> { }
public class UserList  : List<byte> { }

public class Authorization
{
    public Control    Control   { get; set; }
    public GroupList  Groups { get; set; }
    public UserList   Users { get; set; }
}

public class AuthorizationList : List<Authorization>
{
    public void Add(Control control, GroupList groupList, UserList userList)
    {
        Add(new Authorization
        {
            Control = control,
            Groups = groupList,
            Users = userList
        });
    }

    public void Add(Control control, GroupList groupList)
    {
        Add(control, groupList, null);
    }

    public void Add(Control control, UserList userList)
    {
        Add(control, null, userList);
    }
}
Max Sorin
  • 1,042
  • 6
  • 14
2

You can utilize the fact that passing an empty list does not affect your logic.

To make it "more elegant", add two more Add overloads to your AuthorizationList class:

public class AuthorizationList : List<Tuple<Control, GroupList, UserList>>
{
    public void Add(Control control, GroupList groups, UserList users)
    {
        Add(new Tuple<Control, GroupList, UserList>(control, groups, users));
    }
    public void Add(Control control, GroupList groups)
    {
        Add(new Tuple<Control, GroupList, UserList>(control, groups, new UserList()));
    }
    public void Add(Control control, UserList users)
    {
        Add(new Tuple<Control, GroupList, UserList>(control, new GroupList(), users));
    }
}

Now you can pass GroupList, UserList or both:

SetAuthorization(user, new AuthorizationList()
{
    { textBox1, new GroupList() { 1, 2, 3 }, new UserList() { 4 } },
    { textBox2, new GroupList() { 1, 2 } },
    { button1,  new UserList() { 4, 3 } },
});
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
0

I'm trying to understand your question... AuthorizationList is a List of Tuples

And you want it to receive only 2 parameters either a a COntrol and grouplist or a Control and User list

To me it seems like AuthorizationList should be a KeyValuePair>

or something similar. Then check the type to see if the List is a user list or group list

Jacob
  • 103
  • 6