I have set the app to allow each user to have multiple roles.
public class SelectRoleViewModel
{
public string Id { get; set; }
public bool Checked { get; set; }
public string RoleName { get; set; }
public string Description { get; set; }
}
public class EditUser
{
// other properties
public List<SelectRoleViewModel> Roles { get; set; }
}
now in the Controlles, in the Edit get method I wrote this
[CustomAuthorize(Roles = ("Admin,Manager"))]
public ActionResult Edit(string Id)
{
var editUser = GetEditUser(Id);
bool isAdmin = User.IsInRole("Admin");
if (!isAdmin)
{
if (editUser.Roles.Exists(x => x.RoleName == "Admin"))
{
return RedirectToAction("AccessNotAllowed", "Errors");
}
}
// Here just edit what you want
return View(editUser);
}
private EditUser GetEditUser(string Id)
{
var dbUser = UserManager.Users.Where(x => x.Id == Id).FirstOrDefault();
var currentRoles = dbUser.Roles.Select(x => x.RoleId).ToList();
var allRoles = _roleManager.Roles.ToList();
EditUser editUser = new EditUser();
foreach (var x in allRoles)
{
if (currentRoles.Contains(x.Id))
editUser.Roles.Add(new SelectRoleViewModel { Id = x.Id, RoleName = x.Name, Description = x.Description, Checked = true });
else
editUser.Roles.Add(new SelectRoleViewModel { Id = x.Id, RoleName = x.Name, Description = x.Description, Checked = false });
}
if (User.IsInRole("Manager"))
{
// don't show the admin role to set for users if authenticated user is manager
var adm = editUser.Roles
.Where(x => x.RoleName.Equals("Admin", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (adm != null)
{
editUser.Roles.Remove(adm);
}
}
editUser.FirstName = dbUser.FirstName;
editUser.LastName = dbUser.LastName;
editUser.Email = dbUser.Email;
editUser.UserName = dbUser.UserName;
editUser.Id = dbUser.Id;
return editUser;
}
So, the manager has the right to edit users and to create them, but manager can't create users with admin role. What I'm trying to do is to deny access for the manager to edit the admin users. The code I wrote, it takes the whole list of user roles, and since there is an admin role, it always denies access to edit users. This happens when I comment out this code in the GetEditUser method:
if (User.IsInRole("Manager"))
{
// don't show the admin role to set for users if authenticated user is manager
var adm = editUser.Roles
.Where(x => x.RoleName.Equals("Admin", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (adm != null)
{
editUser.Roles.Remove(adm);
}
}
and with this code (uncommented), it totally removes the admin role from the list, so the manager can still edit the admin users since it don't find the admin role to compare in the if condition.
Can someone help me find a solution to limit manager access for editing admin users and to hide the admin role for managers when creating new user, without changing the users to assign only 1 role? The logic of the app needs to have multiple roles per user.
Move the indicated section of code to the Edit method inside the if(!isAdmin):
if (!isAdmin)
{
if (editUser.Roles.Exists(x => x.RoleName == "Admin" && x.Checked))
{
return RedirectToAction("AccessNotAllowed", "Errors");
}
var adm = editUser.Roles
.Where(x => x.RoleName.Equals("Admin", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (adm != null)
{
editUser.Roles.Remove(adm);
}
}