I am trying to lock my application down to each method where by users and admin can see the whole controller but only administrators can create, delete, and edit.
I have created a CustomAuthorize class which holds the method:
public class CustomAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
Debug.WriteLine("Show me the filterContext " + filterContext);
if (filterContext.Result is HttpUnauthorizedResult)
{
Debug.WriteLine("Why is this going to the redirect to AccessDenied?");
filterContext.Result = new RedirectResult("~/AccessDenied/Index");
}
}
}
My RoleProvider Class:
namespace Office.WebUI.Security {
public class OfficeRoleProvider : RoleProvider
{
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override string ApplicationName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
throw new NotImplementedException();
}
public override string[] GetRolesForUser(string username)
{
Debug.WriteLine("Get the username" + username);
using (EFDbContext db = new EFDbContext()) >
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, >stringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
//User user = db.TaskPrivilege.FirstOrDefault(u => >u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
//where ur.RoleID == r.RoleID
select r.Name;
if (roles != null)
return roles.ToArray();
else
return new string[] { }; ;
}
else
{
return new string[] { }; ;
}
}
}
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
public override bool IsUserInRole(string username, string roleName)
{
Debug.WriteLine("The username is " + username + " And the Role it is using is >" + roleName);
using (EFDbContext db = new EFDbContext())
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
//where ur.RoleID == r.RoleID
select r.Name;
if (user != null)
return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
else
return false;
}
else
{
return false;
}
}
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
}
}
In my Database I have a Roles table that holds Role and RoleID as columns, with 2 values Administrator and User as roles with a roleID as the PK, 1 = Administrator & 2 = User. Another table called Users, that contains UserID, Username and role_RoleID
When I assign a user to role_RoleID as 1 (administrator) and lock down a controller using
[CustomAuthorize(Roles = "Administrator"]
This works.
When I assign a role_RoldID = 2 and lock down using:
[CustomAuthorize(Roles = "User"]
This doesn't work?
Also another question is, how do I assign 2 roles to a controller?, I then want to lock down each method to 1 User Role.
Hope that makes sense and I hope someone can help me please.
Thanks
Steven
Basically I have a controller which I have put
[CustomAuthorize(Roles = "Administrators, Support")]
to lock it down so both roles can see the controller.
Then I have create/delete and edit methods I have:
[CustomAuthorize(Roles = "Administrators")]
so basically I want to show the whole controller to both roles but only administrators can create/edit/delete.
When I assign a roleID in the user table = 2(User) the whole application breaks for that user. Assigning RoldID = 1 (Administators) it works for all the people that is assigned roldID 1.
Currently I have the methods
public override string[] GetRolesForUser(string username)
{
using (EFDbContext db = new EFDbContext())
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
select r.Name;
if (roles != null)
return roles.ToArray();
else
return new string[] { }; ;
}
else
{
return new string[] { }; ;
}
}
}
> public override bool IsUserInRole(string username, string roleName)
> {
>
> using (EFDbContext db = new EFDbContext())
> {
> User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase)
> || u.Email.Equals(username,
> StringComparison.CurrentCultureIgnoreCase));
>
> if (user != null)
> {
> var roles = from ur in user.UserRoles
> from r in db.Roles
> where user.role.RoleID == r.RoleID
> //where ur.RoleID == r.RoleID
> select r.Name;
> if (user != null)
> return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
> else
> return false;
> }
> else
> {
> return false;
> }
> }
> }
I know I have to change the IsUserInRole method so it handles a array parameter like so, public override bool IsUserInRole(string username, string[] roleName)
But don't know how to handle that in the linq and mainly in the IsUserInRole method:
return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
Currently it is failing at the GetRolesForUser method, at the where clause i believe,
where user.role.RoleID == r.RoleID
the error message is displayed below:
There is already an open DataReader associated with this Command which must be closed first. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
Source Error:
Line 66: var roles = from ur in user.UserRoles Line 67: from r in db.Roles Line 68: where user.role.RoleID == r.RoleID
Thanks