开发者

Dealing with allowed commands per access level?

I have a set of commands like:

  • .kick
  • .unban
  • .ban
  • .unvouch
  • .vouch
  • .add
  • .del
  • .say

Those commands are used in a chat room where I have several users with different access, for example:

  • Admin is allowed to use all commands.
  • Moderator is allowed to use .kick, .vouch .unvouch .say
  • Vip is allowed to use .say
  • Basic cannot use any command

When a command is used it goes to a bot that is present in the room, that bot will them verify the user, access and everything before performing the command.

Initially I have a user class assigned to a list:

public class Users
{
    public string Name { get; set; }
    public string Comments { get; set; }
    public string Access { get; set; }
}

public List<Users> userList = new List<Users>();

Now I want to implement an easy way to query/check/verify if a given user has access to use a given command, but I am not sure on how to approach it.

I was thinking about having a second class assigned to a list something like the this:

public class UserAccess
{开发者_Go百科
    public string AccessLevel { get; set; }
    public List<string> Commands = new List<string>();
}

public List<UserAccess> accessList = new List<UserAccess>();

And query it with something like:

var user = userList.Find(x => x.Name == currentUser);
if (user != null && accessList.Exists(x => x.AccessLevel == user.Access && x.Commands.Contains(str_cmd))
{
    // use the command
}
else
{
    // cannot use the command
}

As I mentioned above, I have a background worker that is constantly reading the chat messages to capture when a user has typed a command which will then verify and process everything in a queue.

Registered users and access level are filled from my website API which returns JSON to my application when it starts and updates data every now and then when major commands are issued.

This is just an example, I could be over thinking the idea but I did like to hear some advices and ideas of how I could deal with this ?


You can try something like this. Although you may want to define your access list through a Db or through attributes/properties on where your actual commands are defined.

public class User
{
    public static readonly UserAccess[] AccessList = {
            new UserAccess() { AccessLevel = "Admin",
                               Commands = {".kick",".ban",".unban"}
            },
            new UserAccess() { AccessLevel = "User",
                               Commands = {".add",".del"}
            },
            new UserAccess() { AccessLevel = "Vip",
                               Commands = {".say"}
            }};

    public string Name { get; set; }
    public string Comments { get; set; }
    public string Access { get; private set; } //Assuming you can't modify this so we add the next property
    public UserAccess AccessLevel { get; private set; }

    public User(string access)
    {
        this.Access = access;
        this.AccessLevel = AccessList.FirstOrDefault(x => x.AccessLevel == access);
    }
}

public class UserAccess
{
    public string AccessLevel { get; set; }
    public List<string> Commands = new List<string>();
    public bool HasCommand(string command)
    {
        return this.Commands.Any(x => x == command);
    }
}


looks like an IRC bot or services application. the "usual" approach for this is to have a list of commands/privileges with an int representing the needed access level, and a list of users with the corresponding access-level ... whenever a command/privilege is used, try to get the users accesslevel from the list, or a default value (0) if the user is not on the list. then compare that value to the value of the used command/privilege

advantage: rather easy to implement
disadvantage: restricts commands/privileges levels to be somewhat hierarchical

alternative that would allow arbitrary complex permissions:

used Types:

User - represents a user
Group - represents a group of User-Objects
Context - represents the context of the ruleset (in terms of IRC this could be a channel)
Privilege - represents a privilege or command that can be used
Permission - says that a Privilege is either granted or denied

User- and Group-Objects can be associated with a list of Permissions by the context

a context stores a list of effective permissions for users that hold permissions in this context, or Users that are members of groups that hold permissions in this context. those effective permissions are determined the following way:

for each user itterate all group memberships  
   for each group itterate all permissions  
      if the permission is denying a Privilege, add this privilege as denied to the effective permissions of this user, overwriting any permission for this privilege that may already be present in that list
      else, if the permission is granting a privilege add it to the effective permissions only if no permission for this privilege is present in the list

finally itterate over the users permissions
add the permission to the effective permissions list, overwriting any permission for this privilege that may already be present in the list.

all privileges get a default permission, initialized as "denied" (stored in the context)

when permissions are changed at runtime, the effective permissions are to be rebuilt.

when the system has to check a permission, it looks up the user and eventually does authentication. if the user is authenticated, the effective permissions are looked up by the context. if effective permissons are found for that user, the requested privilege is looked up, and the corresponding permission is checked. if we either get granted or denied, the check is completed. if no permission is found, the default permission for that privilege is used.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜