```cshtml Login - Amtech Technologies ltd
``` ### Important: one change to the last part There is one thing I would **not** keep from the code above if Bootstrap's modal needs to close programmatically after a successful save. This section: ```javascript modalElement.addEventListener( "hide.bs.modal", function (event) { event.preventDefault(); } ); ``` will prevent **even your successful `modal.hide()`** from closing the modal. So instead, **remove that entire `hide.bs.modal` listener**. The Bootstrap options already make the modal non-dismissible: ```javascript backdrop: "static", keyboard: false ``` Therefore your final `DOMContentLoaded` section should only be: ```javascript document.addEventListener( "DOMContentLoaded", function () { $("#confirmPassword").on( "keypress", function (e) { if (e.which === 13) { e.preventDefault(); saveNewPassword(); } } ); } ); ``` ### Also make sure your controller returns this Your `Login` action must return: ```csharp if (string.IsNullOrWhiteSpace(user.PasswordHash)) { return Json(new { success = true, requirePasswordChange = true, userid = user.Userid, message = "You must create a new password before continuing." }); } ``` And **not** redirect at that point. Then your `SaveNewPassword` in `HomeController` should be: ```csharp [HttpPost] [ValidateAntiForgeryToken] public async Task SaveNewPassword( [FromBody] ChangePasswordVm model) { try { if (model == null) { return Json(new { success = false, message = "Invalid request." }); } if (string.IsNullOrWhiteSpace(model.NewPassword)) { return Json(new { success = false, message = "Please enter a new password." }); } if (model.NewPassword.Length < 6) { return Json(new { success = false, message = "Password must be at least 6 characters." }); } if (model.NewPassword != model.ConfirmPassword) { return Json(new { success = false, message = "Passwords do not match." }); } var user = await _context.UserAccounts .FirstOrDefaultAsync(x => x.Userid == model.Userid); if (user == null) { return Json(new { success = false, message = "User account not found." }); } if (!user.Active) { return Json(new { success = false, message = "User account is inactive." }); } /* * This is specifically for accounts * that don't have a password yet. */ if (!string.IsNullOrWhiteSpace(user.PasswordHash)) { return Json(new { success = false, message = "This account already has a password." }); } /* * HASH THE PASSWORD */ var passwordHasher = new PasswordHasher(); user.PasswordHash = passwordHasher.HashPassword( user, model.NewPassword ); await _context.SaveChangesAsync(); /* * Find company */ var company = await _context.DCompanies .FirstOrDefaultAsync(x => x.Name.ToUpper() == user.Branchcode.ToUpper()); /* * Create session if OTP is not required */ if (company != null && !company.ToReceiveOTP) { _sessionService.SetUserSession( user, company); } return Json(new { success = true, message = "Password created successfully.", redirectUrl = Url.Action( "Index2", "Home") }); } catch (Exception ex) { return Json(new { success = false, message = ex.Message }); } } ``` And your ViewModel should be: ```csharp public class ChangePasswordVm { public long Userid { get; set; } public string NewPassword { get; set; } public string ConfirmPassword { get; set; } } ``` ### One final important point Your current login page still has: ```cshtml asp-for="Password" ``` and sends: ```javascript Password: password ``` That is **fine for the login request**. It does **not** mean you need a `Password` column in `UserAccount`. The `Password` here is simply the password the user typed into the login form. Your database should only contain: ```csharp public string? PasswordHash { get; set; } ``` The flow will therefore be: **Existing user with hash:** ```text Username + Password ↓ VerifyHashedPassword() ↓ Login ``` **User with `PasswordHash = NULL`:** ```text Username + Password ↓ PasswordHash is NULL ↓ Open Create Your Password popup ↓ New Password + Confirm Password ↓ HashPassword() ↓ Save PasswordHash ↓ Continue to system ``` This specifically avoids using `Reset` for the migration, as you requested.