Reputation: 912
Can you please suggest me which design pattern can be used for an application (Web application) having different user roles. My application has an Admin, HR, Managers, Assistant Mangers and Staffs
Admin has the right to access every page in the web application HR has only the right to access only few pages say page 1 and page 2 (Note that Admin can add privileged to more pages in future) Managers -Managers can view there corresponding staffs
etc
Is there any design pattern to implement the above feature. Since more user roles and pages can be added in future
Thanks
Upvotes: 1
Views: 4967
Reputation: 121
I know this is a very old post, but I was searching for the same answer and never found an acceptable answer. The Decorator pattern seems the most obvious at first, but it isn't really what I wanted because all roles would have to implement the same methods (do we really want a customer to have a BlockUserAccount() method even if it doesn't do anything?), and every role would have to be extended every time a new behavior is implemented.
Instead, I found through experimentation that a variation of the Delegation pattern seems to be best. I say "variation" because everything I've read about the Delegation pattern involves a superclass of the main object, but that is not what I ended up doing.
What I have done is to use a basic user object, and it contains a collection of roles. These roles are defined as a different type of class altogether, each with its own methods, and each with its own interface. Then the roles are delegated out, as needed.
public interface ICustomerAlaCarte
{
void AuthorizePayment(decimal paymentAmount);
}
public abstract class UserRole { }
public class CustomerAlaCarte : UserRole, ICustomerAlaCarte
{
public void AuthorizePayment(decimal paymentAmount)
{
// Logic here
}
}
public class User
{
private List<UserRole> _userRoles;
public void AddUserRole(UserRole newRole)
{
_userRoles.Add(newRole);
}
public ICustomerAlaCarte AsAlaCarteCustomer()
{
ICustomerAlaCarte alaCarteRole = _userRoles.OfType<ICustomerAlaCarte>().FirstOrDefault();
if (alaCarteRole != null)
{
return alaCarteRole;
}
else
{
throw new UserRoleNotAssignedException(); // Custom exception
}
}
}
Then to use:
var user = new User();
user.AddUserRole(new CustomerAlaCarte());
ICustomerAlaCarte customer = user.AsAlaCarteCustomer();
customer.AuthorizePayment(9.99);
Using this pattern, you could even have nested roles. For example, you could have a user admin and a reports admin, and each would inherit from Admin. When you only need basic admin functionality (or identity), you would pull an Admin delegate, but you could also specify IUserAdmin for the aforementioned BlockUserAccount() behavior, because each role only has methods that make sense for it.
Upvotes: 0
Reputation: 262
Well I know it's a old post.. but here's what I designed for something similar you can have any number of roles. Initially every user is a visitor after login in they can have any user role. I have used the decorator pattern for this.
plus I have added Database and Communication interfaces. (Most of the web applications need this) I have used Strategy design pattern so Users can have various database classes (Mysql,MsSql) and various communication methods (Email,SMS). Same way you can add your own Payment Interface to handle various type of payment options.
Upvotes: 2
Reputation: 1708
Generally, when designing user roles, the Decorator Pattern is the appropriate solution.
Upvotes: 4
Reputation: 1552
If you are blocking access on page level, you will find everything you need in one or the other security framework (like spring security).
If you want to be able to lock access to certain functionality, there are some options.
For most of those options it is better not the use the roles, but to use permissions. A role can have several permission. This allows for a lot of flexibility.
You can take a look at some MVC derivations. The methods on the controllers there can be secured. You can map each function to a permission.
If you combine this with the command pattern you can add the security at this level then a permission maps one to one to a command. With this it becomes very easy to let the UI controls reflect the permissions of the current user. (see Actions in Delphi and Spring)
This last option if to me the most beautiful and user friendly.
Upvotes: 1