1

I have developed a package program 3 tiers architecture. Persistence layer is developed by using Repository Pattern and Entity Framework 6 Code First Approach.

This package program has many features and I define a Super User(Admin), who has all rights, in initial creation script. So, the operation of the company can create required data(users, roles etc.) by Super User account for initial use and can also manage them when needed.

But, Super User account should be ignored from all business features. For example, this user should not be shown on user list page or can not assign any task.

The question is 'What is the best way of avoiding Super User account from business functions?'.

To illustrate something better, we can think about 'Community' user from Software Engineering site.

How to avoid 'Community' user from earning reputation?

Using static helper class is shown as:

public static class Checker
{
    public static bool CanUserGoFurther(string username)
    {
        var superUserList = GetSuperUsers();
        return !superUserList.Any(u => u.UserName == username);
    }

    public static bool CanUserGoFurther(int userId)
    {
        var superUserList = GetSuperUsers();
        return !superUserList.Any(u => u.Id == userId);
    }

    public static List<User> FilterUsers(IEnumerable<User> users)
    {
        return users.Except(GetSuperUsers()).ToList();
    }

    private static List<User> GetSuperUsers()
    {
        return new List<User>();
    }
}

public class ReputationService
{   

    public void AddReputation(string userName, int rep)
    {
        if (!Checker.CanUserGoFurther(userName))
            return;

        //...
    }

    public void AddReputation(int userId, int rep)
    {
        if (!Checker.CanUserGoFurther(userId))
            return;

        //...
    }
}

Also should I provide two function which one includes Super User and other does not include Super User method and let the other service to determine which one to use?

public class UserService
{
    private readonly UserRepository _userRepository;

    public UserService(UserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public List<User> GetUsersWithSuperUsers()
    {
        return _userRepository.GetAll();
    }

    public List<User> GetUsersWithoutSuperUsers()
    {
        return Checker.FilterUsers(_userRepository.GetAll());
    }
}

public class SomeService
{
    private readonly UserService _userService;

    public SomeService(UserService userService)
    {
        _userService = userService;
    }

    public void SomeFunction1()
    {
        var users = _userService.GetUsersWithoutSuperUsers();

        //..
    }

    public void SomeFunction2()
    {
        var users = _userService.GetUsersWithSuperUsers();

        //..
    }
}

Maybe it seems good when there are 2 or 3 services but when there are more than 30 services it's painful and feel something wrong.

Is there any better way to overcome this issue or can improve current?

  • 4
    "Super User" isn't a user; it is a permission. Treat it as you would any other permission. – Robert Harvey Mar 22 at 14:12
  • 4
    Look into security architectures that support the idea of roles. User identifies a person. Their role identifies the set of permissions currently assigned to that user. – candied_orange Mar 22 at 14:14
  • 2
    I see your edit, but apparently you didn't hear us. Super User is not an account; it is a security role. Your difficulties arise directly from this fact. The way you solve the problem is by removing Super User as an account and making it a part of your role-based security system instead. – Robert Harvey Mar 22 at 15:14
6

Your questions lists several things which in your system could be permitted to someone, or not:

  1. can create other users and roles

  2. manage users and roles (and their permissions)

  3. should be shown on user list page

  4. can assign tasks

  5. can earn reputation

You can make these properties part of a permission table in your database, and allow to give or retract these permissions to every account or role in your system. When implementing the system, check the permissions from that table to control certain functions in your system, nothing else. Don't check for "special accounts" or something like that.

For example, a "business user" may have the permissions 3, 4, and 5, but not 1 and 2. What you call a "super user" may have only the permissions 1 and 2, but not the other ones. You may also find permissions which are suitable for both, "super users" and "business users", but not for other ones like "guest users", or whatever requirements you have.

If there are many permission types, for ease of use, you may not assign or retract those permissions individually for each account, but to predefined roles with certain combinations of permissions enabled or disabled. For example, a "business user" role, a "super user" role, and so on. Then, these roles get assigned to the accounts.

  • This permission table is a database table, right? If so, how would you search specific permission in this permission table? By enum or constant key that define for each method? – Engineert Mar 22 at 17:13
  • @Engineert: my answer is just sketching the concept. How you implement this exactly (maybe as a database table with permissions as fixed columns, maybe with an additional table for permissions types which may be extended), is up to you, whatever fits best to the size and scale of your system. And how to search for specific permissions depends on those implemention details. Said that, having a specific, fixed key string for each permission which can be used for searching may be a sensible solution, but one has to know your system more deeply, currently I am only guessing on this. – Doc Brown Mar 22 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.