Academatica.Api/Academatica.Api.Users/Controllers/UsersController.cs
/// <summary>
/// Endpoint used to change user email address.
/// </summary>
/// <param name="id">User ID.</param>
/// <param name="changeEmailRequestDTO">New email address and the confirmation code.</param>
Endpoint used to change user email address.
Endpoint used to change user email address .
[HttpPatch]
        [Route("{id}/email")]
        public async Task<IActionResult> SetUserEmail(Guid id, [FromBody] UserChangeEmailRequestDto changeEmailRequestDTO)
        {
            if (ModelState.IsValid) 
            {
                var userId = User.FindFirst("sub")?.Value;
                if (userId != id.ToString())
                {
                    return Forbid();
                }
                var user = _academaticaDbContext.Users.Where(x => x.Id == id).FirstOrDefault();
                if (user == null)
                {
                    return NotFound("Invalid user ID.");
                }
                if (string.IsNullOrEmpty(changeEmailRequestDTO.EMail))
                {
                    return Ok(new UserChangeEmailResponseDto()
                    {
                        Success = false,
                        ConfirmationPending = false,
                        Error = "Email was null."
                    });
                }
                var registeredUser = await _userManager.FindByEmailAsync(changeEmailRequestDTO.EMail);
                if (registeredUser != null)
                {
                    return Ok(new UserChangeEmailResponseDto()
                    {
                        Success = false,
                        ConfirmationPending = false,
                        Error = "Email already taken."
                    });
                }
                if (string.IsNullOrEmpty(changeEmailRequestDTO.ConfirmationCode))
                {
                    return Ok(new UserChangeEmailResponseDto()
                    {
                        Success = false,
                        ConfirmationPending = false,
                        Error = "Confirmation code was null."
                    });
                } else 
                {
                    var cachedCode = await _confirmationCodeManager.GetEmailConfirmationCode(user.Id);
                    if (string.IsNullOrEmpty(cachedCode)) 
                    {
                        return StatusCode(500, "Code cache was null.");
                    } else {
                        if (cachedCode != changeEmailRequestDTO.ConfirmationCode) 
                        {
                            return Ok(new UserChangeEmailResponseDto 
                            {
                                ConfirmationPending = true,
                                Success = false,
                                Error = "Invalid confirmation code."
                            });
                        }
                        var oldEmail = user.Email;
                        await _userManager.SetEmailAsync(user, changeEmailRequestDTO.EMail);
                        var rollbackCode = await _userManager.GenerateChangeEmailTokenAsync(user, oldEmail);
                        var rollbackUrl = Url.Action(nameof(RollbackUserEmailChange), "Users", new { id = user.Id, code = rollbackCode, oldEmail = oldEmail },
                            protocol: HttpContext.Request.Scheme);
                        await _userEmailService.SendEmailChangeNotification(user, oldEmail, changeEmailRequestDTO.EMail, rollbackUrl);
                        var confirmationCode = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                        var callbackUrl = Url.Action(nameof(ConfirmUserEmailChange), "Users", new { id = user.Id, code = confirmationCode }, protocol: HttpContext.Request.Scheme);
                        await _userEmailService.SendNewEmailConfirmation(user, changeEmailRequestDTO.EMail, callbackUrl);
                        await _confirmationCodeManager.RemoveEmailConfirmationCode(user.Id);
                        return Ok(new UserChangeEmailResponseDto 
                        {
                            ConfirmationPending = false,
                            Success = true
                        });
                    }
                }
            } else 
            {
                var message = string.Join(" | ", ModelState.Values
                                    .SelectMany(v => v.Errors)
                                    .Select(e => e.ErrorMessage));
                return BadRequest(message);
            }
        }
[ HttpPatch ] [ Route ( " " ) ] public async Task < IActionResult > SetUserEmail ( Guid id , [ FromBody ] UserChangeEmailRequestDto changeEmailRequestDTO ) { if ( ModelState . IsValid ) { var userId = User . FindFirst ( " " ) ? . Value ; if ( userId != id . ToString ( ) ) { return Forbid ( ) ; } var user = _academaticaDbContext . Users . Where ( x => x . Id == id ) . FirstOrDefault ( ) ; if ( user == null ) { return NotFound ( " " ) ; } if ( string . IsNullOrEmpty ( changeEmailRequestDTO . EMail ) ) { return Ok ( new UserChangeEmailResponseDto ( ) { Success = false , ConfirmationPending = false , Error = " " } ) ; } var registeredUser = await _userManager . FindByEmailAsync ( changeEmailRequestDTO . EMail ) ; if ( registeredUser != null ) { return Ok ( new UserChangeEmailResponseDto ( ) { Success = false , ConfirmationPending = false , Error = " " } ) ; } if ( string . IsNullOrEmpty ( changeEmailRequestDTO . ConfirmationCode ) ) { return Ok ( new UserChangeEmailResponseDto ( ) { Success = false , ConfirmationPending = false , Error = " " } ) ; } else { var cachedCode = await _confirmationCodeManager . GetEmailConfirmationCode ( user . Id ) ; if ( string . IsNullOrEmpty ( cachedCode ) ) { return StatusCode ( 500 , " " ) ; } else { if ( cachedCode != changeEmailRequestDTO . ConfirmationCode ) { return Ok ( new UserChangeEmailResponseDto { ConfirmationPending = true , Success = false , Error = " " } ) ; } var oldEmail = user . Email ; await _userManager . SetEmailAsync ( user , changeEmailRequestDTO . EMail ) ; var rollbackCode = await _userManager . GenerateChangeEmailTokenAsync ( user , oldEmail ) ; var rollbackUrl = Url . Action ( nameof ( RollbackUserEmailChange ) , " " , new { id = user . Id , code = rollbackCode , oldEmail = oldEmail } , protocol : HttpContext . Request . Scheme ) ; await _userEmailService . SendEmailChangeNotification ( user , oldEmail , changeEmailRequestDTO . EMail , rollbackUrl ) ; var confirmationCode = await _userManager . GenerateEmailConfirmationTokenAsync ( user ) ; var callbackUrl = Url . Action ( nameof ( ConfirmUserEmailChange ) , " " , new { id = user . Id , code = confirmationCode } , protocol : HttpContext . Request . Scheme ) ; await _userEmailService . SendNewEmailConfirmation ( user , changeEmailRequestDTO . EMail , callbackUrl ) ; await _confirmationCodeManager . RemoveEmailConfirmationCode ( user . Id ) ; return Ok ( new UserChangeEmailResponseDto { ConfirmationPending = false , Success = true } ) ; } } } else { var message = string . Join ( " " , ModelState . Values . SelectMany ( v => v . Errors ) . Select ( e => e . ErrorMessage ) ) ; return BadRequest ( message ) ; } }
Endpoint used to change user email address.
Endpoint used to change user email address .
id
Guid
None
UserChangeEmailRequestDto
[FromBody]
changeEmailRequestDTO
New email address and the confirmation code.
New email address and the confirmation code .