Reputation: 395
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:
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
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
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
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