I am creating an ASP.NET MVC application and this is my problem:
When accesing an action in controller, beside checking if logged user in in allowed role with Authorize attribute, i need to include logic conserning if user i want to edit(it's id comes as a parameter of action) has lower role than the logged user( i dont want to allow regular users to edit admins etc.)
Where should i implement this logic? I wanted to override methods in AuthorizeAttribute and simply add this logic there, but in that case i would have to send the user i want to edit in parameter of the attribute, but that is not allowed.
Another option would be to create private method in the controller, but if i want to use this logic in other controllers i would have to repeat this code again and again.
What is the right solution please?
[AttributeUsageAttribute( AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true )]
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
private string _roles { get; set; }
private UserEntity _user { get; set; }
private UserEntity _loggedUser { get; set; }
public AuthorizeRolesAttribute(string Roles, string User, int Id)
{
_user = new UserEntity();
_loggedUser = new UserEntity();
_roles = Roles;
}
//Called when access is denied
protected override void HandleUnauthorizedRequest( AuthorizationContext filterContext )
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary( new { controller = "Account", action = "LogOn" } )
);
}
//Core authentication, called before each action
protected override bool AuthorizeCore( HttpContextBase httpContext )
{
bool b = false;
string[] roles = _roles.Split(',');
//Is user logged in?
if ( httpContext.User.Identity.IsAuthenticated )
{
//If user is logged in and we need a custom check:
if ( roles.Any(r => httpContext.User.IsInRole(r)) && HasPermission(_user, _loggedUser))
b = true;
}
//Returns true or false, meaning allow or deny. False will call HandleUnauthorizedRequest above
return b;
}
private bool HasPermission(UserEntity user, UserEntity loggedUser)
{
if (user.IsAdmin) return false;
if (loggedUser.IsAdmin || loggedUser.IsApplicationAdmin) return true;
if (loggedUser.IsAmbassador)
{
if (user.IsApplicationAdmin)
{ return false; }
else
{ return true; }
}
return false;
}
}
As you can see, at the moment im just creating empty fake objects _user and _loggedUser in constructor because i dont know how to pass them.