Forgot Password (#1017)
* Implemented forgot password flow. Fixed a bug in manage user where admins were showing the Sharing With section. * Cleaned up the reset password flow. * Reverted some debug code * Fixed an issue with invites due to ImmutableArray not being set.
This commit is contained in:
parent
8564378b77
commit
8ff123e06c
27 changed files with 271 additions and 38 deletions
|
@ -394,6 +394,7 @@ namespace API.Controllers
|
|||
}
|
||||
|
||||
|
||||
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
[HttpPost("invite")]
|
||||
public async Task<ActionResult<string>> InviteUser(InviteUserDto dto)
|
||||
|
@ -439,7 +440,7 @@ namespace API.Controllers
|
|||
var roleResult = await _userManager.AddToRoleAsync(user, role);
|
||||
if (!roleResult.Succeeded)
|
||||
return
|
||||
BadRequest(roleResult.Errors); // TODO: Combine all these return BadRequest into one big thing
|
||||
BadRequest(roleResult.Errors);
|
||||
}
|
||||
|
||||
// Grant access to libraries
|
||||
|
@ -482,7 +483,7 @@ namespace API.Controllers
|
|||
}
|
||||
return Ok(emailLink);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
_unitOfWork.UserRepository.Delete(user);
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
@ -533,6 +534,56 @@ namespace API.Controllers
|
|||
};
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("confirm-password-reset")]
|
||||
public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordResetDto dto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (user == null)
|
||||
{
|
||||
return BadRequest("Invalid Details");
|
||||
}
|
||||
|
||||
var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, "ResetPassword", dto.Token);
|
||||
if (!result) return BadRequest("Unable to reset password");
|
||||
|
||||
var errors = await _accountService.ChangeUserPassword(user, dto.Password);
|
||||
return errors.Any() ? BadRequest(errors) : BadRequest("Unable to reset password");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Will send user a link to update their password to their email or prompt them if not accessible
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("forgot-password")]
|
||||
public async Task<ActionResult<string>> ForgotPassword([FromQuery] string email)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(email);
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogError("There are no users with email: {Email} but user is requesting password reset", email);
|
||||
return Ok("An email will be sent to the email if it exists in our database");
|
||||
}
|
||||
|
||||
var emailLink = GenerateEmailLink(await _userManager.GeneratePasswordResetTokenAsync(user), "confirm-reset-password", user.Email);
|
||||
_logger.LogInformation("[Forgot Password]: Email Link: {Link}", emailLink);
|
||||
var host = _environment.IsDevelopment() ? "localhost:4200" : Request.Host.ToString();
|
||||
if (await _emailService.CheckIfAccessible(host))
|
||||
{
|
||||
await _emailService.SendPasswordResetEmail(new PasswordResetEmailDto()
|
||||
{
|
||||
EmailAddress = user.Email,
|
||||
ServerConfirmationLink = emailLink
|
||||
});
|
||||
return Ok("Email sent");
|
||||
}
|
||||
|
||||
return Ok("Your server is not accessible. The Link to reset your password is in the logs.");
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("confirm-migration-email")]
|
||||
public async Task<ActionResult<UserDto>> ConfirmMigrationEmail(ConfirmMigrationEmailDto dto)
|
||||
|
@ -570,10 +621,7 @@ namespace API.Controllers
|
|||
"This user needs to migrate. Have them log out and login to trigger a migration flow");
|
||||
if (user.EmailConfirmed) return BadRequest("User already confirmed");
|
||||
|
||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var host = _environment.IsDevelopment() ? "localhost:4200" : Request.Host.ToString();
|
||||
var emailLink =
|
||||
$"{Request.Scheme}://{host}{Request.PathBase}/registration/confirm-migration-email?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(user.Email)}";
|
||||
var emailLink = GenerateEmailLink(await _userManager.GenerateEmailConfirmationTokenAsync(user), "confirm-migration-email", user.Email);
|
||||
_logger.LogInformation("[Email Migration]: Email Link: {Link}", emailLink);
|
||||
await _emailService.SendMigrationEmail(new EmailMigrationDto()
|
||||
{
|
||||
|
@ -586,6 +634,14 @@ namespace API.Controllers
|
|||
return Ok(emailLink);
|
||||
}
|
||||
|
||||
private string GenerateEmailLink(string token, string routePart, string email)
|
||||
{
|
||||
var host = _environment.IsDevelopment() ? "localhost:4200" : Request.Host.ToString();
|
||||
var emailLink =
|
||||
$"{Request.Scheme}://{host}{Request.PathBase}/registration/{routePart}?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(email)}";
|
||||
return emailLink;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is similar to invite. Essentially we authenticate the user's password then go through invite email flow
|
||||
/// </summary>
|
||||
|
@ -622,9 +678,7 @@ namespace API.Controllers
|
|||
_unitOfWork.UserRepository.Update(user);
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
||||
var host = _environment.IsDevelopment() ? "localhost:4200" : Request.Host.ToString();
|
||||
var emailLink =
|
||||
$"{Request.Scheme}://{host}{Request.PathBase}/registration/confirm-migration-email?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(dto.Email)}";
|
||||
var emailLink = GenerateEmailLink(await _userManager.GenerateEmailConfirmationTokenAsync(user), "confirm-migration-email", user.Email);
|
||||
_logger.LogInformation("[Email Migration]: Email Link: {Link}", emailLink);
|
||||
if (dto.SendEmail)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue