Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identity 2.1 - Remove from all previous roles, then add to specific role? Plus error in calling UserManager when doing so

I am writing a user manager for a system administrator where you can perform various functions on the user object. My current dilemma is I want to be able to write something like

await UserManager.RemoveFromRoleAsync(userID, any);

and have that person removed from all previous roles.

Right now I've written this code, but it "feels" dirty and could be better. I also am getting a generic "object not set to instance of an object" error when testing it.

Controller code (userID and level are passed in from calling page):

var userID = "68790581-d2ae-4bc3-8db3-e4c8f4b0bb9f";
        string level = "FullAdmin";

//POST: /Account/MakeAdmin
        [HttpPost]
        [Authorize(Roles = "SuperAdmin")]
        public async Task<ActionResult> MakeAdmin(string userID, string level)
        {

        if(userID == null || level == null)
        {
            return View("Error");
        }

        if (level == "FullAdmin")
        {
            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "Admin1");
            }

            catch { }

            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "ReadOnly");
            }

            catch { }

            //Add to the desired role
            try
            {
                await UserManager.AddToRoleAsync(userID, "SuperAdmin");
            }
            catch (Exception ex)
            {
                ViewBag.Exception = ex;
            }



            return Content("Admin permissions activated");
        }

        if(level == "ReadOnlyAdmin")
        {
            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "SuperAdmin");
            }

            catch { }

            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "Admin1");
            }

            catch { }

    //Add to the desired role
            try
            {
                await UserManager.AddToRoleAsync(userID, "ReadOnly");
            }
            catch (Exception ex)
            {
                ViewBag.Exception = ex;
            }


            return Content("Read only admin permissions activated");
        }

        return View();
    }

This code fails - here's my stack trace:

 Test Name: PostMakeAdmin
Test FullName:  Testing.AccountTests.PostMakeAdmin
Test Source:    h:\app\Controllers\UnitTest1.cs : line 880
Test Outcome:   Failed
Test Duration:  0:00:00.5725984

Result Message: 
Test method Testing.AccountTests.PostMakeAdmin threw exception: 
System.NullReferenceException: Object reference not set to an instance of an object.
Result StackTrace:  
at System.Web.HttpContextBaseExtensions.GetOwinEnvironment(HttpContextBase context)
   at System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase context)
   at app.Controllers.AccountController.get_UserManager() in h:\app\Controllers\AccountController.cs:line 42
   at app.Controllers.AccountController.<MakeAdmin>d__c.MoveNext() in h:\app\Controllers\AccountController.cs:line 305
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at app.AccountTests.<PostMakeAdmin>d__d.MoveNext() in h:\app\Controllers\UnitTest1.cs:line 888
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

Thanks to anyone who can help!

UPDATE The initial iteration problem is solved. I'm getting an error about "Object reference not set to instance of an object" in relation to my UserManager.

Here's the code establishing UserManager:

 public AccountController()
    {
    }

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
    {
        UserManager = userManager;
        SignInManager = signInManager;
    }

    public ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }
like image 448
Dreamcasting Avatar asked Dec 01 '22 17:12

Dreamcasting


2 Answers

You can get all of the roles a user is part of, iterate them and remove.

   var user = await UserManager.FindByIdAsync(userId);
   await UserManager.RemoveFromRolesAsync(userId, UserManager.GetRoles(userId).ToArray());
   await UserManager.AddToRoleAsync(userId, "NewRole");
   await UserManager.UpdateAsync(user);
like image 107
Jacob Roberts Avatar answered Dec 04 '22 11:12

Jacob Roberts


For Asp.Net Core 2.2.0 use this instead of the accepted answer

(GetRoles no longer exists, use GetRolesAsync instead)

await _userManager.RemoveFromRolesAsync(userObj, await _userManager.GetRolesAsync(userObj));
await _userManager.AddToRoleAsync(userObj, roleName);
like image 26
Tim Gerhard Avatar answered Dec 04 '22 09:12

Tim Gerhard