public async Task <IActionResult> Login(SignInModel signInModel) { ViewData["ButtonID"] = ButtonID.Login; // Check if fields are entered and match checks. if (!ModelState.IsValid) { return(View(signInModel)); } // Model State is Valid; Check Captcha if (!await _captcha.IsCaptchaValidAsync()) { ModelState.AddModelError(_captcha.CaptchaValidationError().Key, _captcha.CaptchaValidationError().Value); return(View()); } // Attempt to sign the user in. SignInResult result = await _accountRepository.PasswordSignInAsync(signInModel, GetRemoteClientIPv4()); if (result.Succeeded) { _logger.LogInformation($"USER {signInModel.Username} has logged in."); // Store the fact that the CAPTCHA was completed successfully. await _captcha.CacheNewCaptchaValidateAsync(); // Change the time of last login. await _accountRepository.UpdateLastLoginAsync(signInModel.Username); // Redirect return(RedirectToAction(nameof(UserPanelController.Index), GoliathControllers.UserPanelController)); } // Result failed. Check for reason why. if (result.IsLockedOut) { ModelState.AddModelError(string.Empty, "Please try again later."); } else if (result.IsNotAllowed) { ModelState.AddModelError(string.Empty, "You must verify your email!"); } else if (result.RequiresTwoFactor) { await _twoFactorTokenRepository.CreateTokenAsync(signInModel.Username, GoliathHelper.GenerateSecureRandomNumber()); return(RedirectToAction(nameof(TwoFactorValidation), new { userName = signInModel.Username })); } else { ModelState.AddModelError(string.Empty, "Invalid Credentials."); } // Invalidate Captcha Cookie. _captcha.DeleteCaptchaCookie(); // Return view with errors. return(View(signInModel)); }
public async Task<IActionResult> Profile(ProfileSettingsModel model) { if (!ModelState.IsValid) { return View(model); } if (!await _captcha.IsCaptchaValidAsync()) { ModelState.AddModelError(_captcha.CaptchaValidationError().Key, _captcha.CaptchaValidationError().Value); return View(); } ApplicationUser goliathUser = await _accountRepository.GetUserFromContextAsync(User); if (!await _timeouts.CanRequestProfileSettingsUpdateAsync(goliathUser.Id)) { ModelState.AddModelError(string.Empty, "Please wait before updating your profile again."); return View(); } #region Simple value updates // ** Values which do not need database checking goliathUser.BackgroundColor = model.BackgroundColor; goliathUser.DarkTheme = model.DarkThemeEnabled; goliathUser.LogoutThreshold = int.Parse(model.LogoutThreshold); // ** If settings which require a two-factor code are updated. bool requiresTwoFactor = false; #endregion Simple value updates #region Validating email if (!string.IsNullOrWhiteSpace(model.NewEmail)) { if (await _accountRepository.DoesEmailExistAsync(model.NewEmail)) { ModelState.AddModelError(string.Empty, $"The email {model.NewEmail} is currently in use."); return View(); } else { goliathUser.UnverifiedNewEmail = model.NewEmail; requiresTwoFactor = true; } } #endregion Validating email #region Validating phone number if (!string.IsNullOrWhiteSpace(model.NewPhoneNumber)) { if (await _accountRepository.DoesPhoneNumberExistAsync(model.NewPhoneNumber)) { ModelState.AddModelError(string.Empty, $"The phone number {model.NewPhoneNumber} is currently in use."); return View(); } else { goliathUser.UnverifiedNewPhone = model.NewPhoneNumber; requiresTwoFactor = true; } } #endregion Validating phone number #region Validating password if (!string.IsNullOrWhiteSpace(model.NewPassword)) { if (await _accountRepository.IsPasswordValidAsync(goliathUser, model.NewPassword)) { ModelState.AddModelError(string.Empty, "Your new password must be different then your previous password."); return View(); } IdentityResult result = await _accountRepository.UpdatePasswordAsync(goliathUser, model.CurrentPassword, model.NewPassword); if (!result.Succeeded) { _captcha.DeleteCaptchaCookie(); ModelState.AddModelError(string.Empty, "Your entry in \"Current Password\" does not match your current password."); return View(); } goliathUser.LastPasswordUpdate = DateTime.UtcNow.ToString(); requiresTwoFactor = true; } #endregion Validating password #region Check two-factor codes if (goliathUser.TwoFactorEnabled && requiresTwoFactor) { if (string.IsNullOrWhiteSpace(model.TwoFactorCode)) { _captcha.DeleteCaptchaCookie(); ModelState.AddModelError(string.Empty, "Your two-factor code is invalid."); return View(); } if (!await _accountRepository.TwoFactorCodeValidAsync(goliathUser, model.TwoFactorCode)) { _captcha.DeleteCaptchaCookie(); ModelState.AddModelError(string.Empty, "Your two-factor code is invalid."); return View(); } } #endregion Check two-factor codes #region Sending potential verification emails // If all of the user settings are correct then check if we need to send messages to // update phone/email. if (!string.IsNullOrWhiteSpace(model.NewEmail)) { await _accountRepository.GenerateNewEmailConfirmationTokenAsync(goliathUser, new DeviceParser(GetClientUserAgent(), GetRemoteClientIPv4())); } if (!string.IsNullOrWhiteSpace(model.NewPhoneNumber)) { await _accountRepository.GenerateNewPhoneConfirmationTokenAsync(goliathUser, new DeviceParser(GetClientUserAgent(), GetRemoteClientIPv4())); } #endregion Sending potential verification emails #region Updating/Caching // Update all of the changed values. await _accountRepository.UpdateUserAsync(goliathUser); await _captcha.CacheNewCaptchaValidateAsync(); await _timeouts.UpdateRequestAsync(goliathUser.Id, UserRequest.UpdateProfileSettings); #endregion Updating/Caching ModelState.Clear(); _logger.LogInformation($"{goliathUser.Id} ({goliathUser.UserName}) - Updated profile settings successfully."); TempData[TempDataKeys.Redirect] = RedirectPurpose.SettingsUpdatedSuccess; return View(); }