HDuck
HDuck

Reputation: 395

Can't update SQL Bit column with ASP .NET Core

I have an ASP .NET Core web app, and when I created the project the authentication was set up automatically using the individual user accounts option. The database tables for user accounts/roles were also created automatically.

I created my own ApplicationUser class which inherits from IdentityUser, and I added parameters for FirstName, LastName and LockoutReason. (I added these fields to the DB table as well) Now I'm trying to add a feature to allow someone to manually lock out a user, and I can't seem to update the LockoutEnabled field in the database. Every time I do, it automatically gets reset to false.

Here is a picture of the form: enter image description here

And the GET/POST code for it:

//GET Users lock
    public async Task<IActionResult> Lock(string id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var userFromDb = await _db.ApplicationUser.SingleOrDefaultAsync(m => m.Id == id);
        if (userFromDb == null)
        {
            return NotFound();
        }
        else
        {
            return View(userFromDb);
        }
    }

    //POST Users lock
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Lock(string Id, ApplicationUser model)
    {
        var userFromDb = await _db.Users.Where(u => u.Id == Id).FirstOrDefaultAsync();

        userFromDb.LockoutEnd = model.LockoutEnd;
        userFromDb.LockoutEnabled = true;
        userFromDb.AccessFailedCount = model.AccessFailedCount;
        userFromDb.LockoutReason = model.LockoutReason;

        _db.ApplicationUser.Update(userFromDb);
        await _db.SaveChangesAsync();

        return RedirectToAction(nameof(Index));           
    }

ApplicationUser.cs

public class ApplicationUser : IdentityUser
{        
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string LockoutReason { get; set; }
}

When I click the Lock button, the LockoutEnd and LockoutReason fields are updated correctly, but the LockoutEnabled field remains false and the account isn't locked out.

New POST method after trying to implement solution:

//POST Users lock
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Lock(string Id, ApplicationUser model)
    {
        var userFromDb = await _db.Users.Where(u => u.Id == Id).FirstOrDefaultAsync();

        userFromDb.LockoutEnd = model.LockoutEnd;            
        userFromDb.AccessFailedCount = model.AccessFailedCount;
        userFromDb.LockoutReason = model.LockoutReason;

        _db.ApplicationUser.Update(userFromDb);            
        await _db.SaveChangesAsync();

        var user2 = await _userManager.FindByIdAsync(userFromDb.Id);
        var result = await _userManager.SetLockoutEnabledAsync(user2, true);

        return RedirectToAction(nameof(Index));           
    }

Upvotes: 3

Views: 1355

Answers (3)

Hameed
Hameed

Reputation: 1615

You need the combination of the two proprieties The LockoutEnabled and LockoutEnd.

The LockoutEnabled is an indicator to see if the user could be locked out or not, and the LockoutEnd is a DateTimeOffset. So in order to lock the user set the lockout to true and put the value of LockoutEnd in the future, because A value in the past means the user is not locked out.

Upvotes: 2

mvermef
mvermef

Reputation: 3914

UserManager<ApplicationUser> _userManager

_userManager = userManager; //DI'd via CTOR for the class

it is never done with direct access with the table from the user table.

in your case you might need to grab the user with a call to var user = await _userManager.FindByIdAsync(model.Id)

because you might not have enough information with the pass through from the post populated within the model variable.

//used from with in method
//model.LockoutEnabled will be either true or false depending on your selection
//from the view.
var result = await _userManager.SetLockoutEnabledAsync(user, model.LockoutEnabled); 

this returns IdentityResult which has Errors collection Or bool Succeeded properties, can be handled as you like.

Upvotes: 2

Derviş Kayımbaşıoğlu
Derviş Kayımbaşıoğlu

Reputation: 30565

you cannot achieve this by altering LockoutEnabled property.

Instead, you need to add custom property such as IsEnabled

  • On Register Action Modify Application user

    var user = new ApplicationUser { UserName = model.Email, Email = model.Email, IsEnabled = true };

  • On PasswordSigninAsync add IsEnabled check

'

if (user.IsEnabled)
     return base.PasswordSignInAsync(userName, password, rememberMe, shouldLockout);

return Task.FromResult<SignInStatus>(SignInStatus.LockedOut);

Upvotes: 2

Related Questions