email and password change panels added
This commit is contained in:
@@ -114,6 +114,20 @@ public class AccountsController(IAccountsControllerService accountsControllerSer
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ActionResult> PatchAccountUsername([FromBody]AccountUsernameRequest data) => await accountsControllerService.PatchAccountUsername(data);
|
||||
|
||||
[HttpPatch("email")]
|
||||
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ActionResult> PatchAccountEmail([FromBody]AccountEmailRequest data) => await accountsControllerService.PatchAccountEmail(data);
|
||||
|
||||
[HttpPatch("password")]
|
||||
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ActionResult> PatchAccountPassword([FromBody]AccountPasswordRequest data) => await accountsControllerService.PatchAccountPassword(data);
|
||||
|
||||
#endregion
|
||||
|
||||
[HttpGet("{id}/movies")]
|
||||
|
||||
@@ -37,18 +37,13 @@ public class AccountsControllerService(
|
||||
|
||||
public async Task<RequestResult> Register(RegisterRequest data)
|
||||
{
|
||||
string leftSalt = StringExtensions.CreateRandom(20);
|
||||
string rightSalt = StringExtensions.CreateRandom(20);
|
||||
byte[] hash = ComputeHash(data.Password, leftSalt, rightSalt);
|
||||
|
||||
Account account = new Account
|
||||
{
|
||||
Username = data.Username,
|
||||
Email = data.Email,
|
||||
Password = hash,
|
||||
LeftSalt = leftSalt,
|
||||
RightSalt = rightSalt,
|
||||
};
|
||||
|
||||
SetPassword(account, data.Password);
|
||||
await database.Accounts.AddAsync(account);
|
||||
await database.SaveChangesAsync();
|
||||
|
||||
@@ -283,6 +278,36 @@ public class AccountsControllerService(
|
||||
|
||||
return RequestResult.Ok();
|
||||
}
|
||||
|
||||
public async Task<RequestResult> PatchAccountEmail(AccountEmailRequest data)
|
||||
{
|
||||
Account account = await database.Accounts.FirstAsync(x => x.Id == userService.GetUserId());
|
||||
|
||||
if (!ComputeHash(data.Password, account.LeftSalt, account.RightSalt).SequenceEqual(account.Password))
|
||||
{
|
||||
return RequestResult.Unauthorized();
|
||||
}
|
||||
|
||||
data.UpdateAccount(account);
|
||||
await database.SaveChangesAsync();
|
||||
|
||||
return RequestResult.Ok();
|
||||
}
|
||||
|
||||
public async Task<RequestResult> PatchAccountPassword(AccountPasswordRequest data)
|
||||
{
|
||||
Account account = await database.Accounts.FirstAsync(x => x.Id == userService.GetUserId());
|
||||
|
||||
if (!ComputeHash(data.OldPassword, account.LeftSalt, account.RightSalt).SequenceEqual(account.Password))
|
||||
{
|
||||
return RequestResult.Unauthorized();
|
||||
}
|
||||
|
||||
SetPassword(account, data.NewPassword);
|
||||
await database.SaveChangesAsync();
|
||||
|
||||
return RequestResult.Ok();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -338,5 +363,16 @@ public class AccountsControllerService(
|
||||
|
||||
protected byte[] ComputeHash(string password, string leftSalt, string rightSalt) => SHA512.HashData(Encoding.UTF8.GetBytes($"{leftSalt}{password}{rightSalt}"));
|
||||
|
||||
private void SetPassword(Account account, string password)
|
||||
{
|
||||
string leftSalt = StringExtensions.CreateRandom(20);
|
||||
string rightSalt = StringExtensions.CreateRandom(20);
|
||||
byte[] hash = ComputeHash(password, leftSalt, rightSalt);
|
||||
|
||||
account.Password = hash;
|
||||
account.LeftSalt = leftSalt;
|
||||
account.RightSalt = rightSalt;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -22,6 +22,8 @@ public interface IAccountsControllerService
|
||||
Task<RequestResult> GetAccountInfo(long id);
|
||||
Task<RequestResult> PutAccountProfileInfo(AccountProfileInfoRequest data);
|
||||
Task<RequestResult> PatchAccountUsername(AccountUsernameRequest data);
|
||||
Task<RequestResult> PatchAccountEmail(AccountEmailRequest data);
|
||||
Task<RequestResult> PatchAccountPassword(AccountPasswordRequest data);
|
||||
Task<RequestResult> GetAccountRatedMovies(long id, MovieRatedQueryParameters query);
|
||||
Task<RequestResult> GetAccountRatedSeries(long id, SeriesRatedQueryParameters query);
|
||||
Task<RequestResult> GetAccountRatedPersons(long id, PersonRatedQueryParameters query);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Common.Model.Accounts;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.WebAPI.Validators.Accounts;
|
||||
|
||||
public class AccountEmailRequestValidator : AbstractValidator<AccountEmailRequest>
|
||||
{
|
||||
public AccountEmailRequestValidator(DatabaseContext database)
|
||||
{
|
||||
RuleFor(x => x.NewEmail).EmailAddress()
|
||||
.CannotBeIn(database.Accounts, x => x.Email)
|
||||
.WithMessage("Email was already used");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Common.Model.Accounts;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.WebAPI.Validators.Accounts;
|
||||
|
||||
public class AccountPasswordRequestValidator : AbstractValidator<AccountPasswordRequest>
|
||||
{
|
||||
public AccountPasswordRequestValidator(DatabaseContext database)
|
||||
{
|
||||
RuleFor(x => x.NewPassword).MinimumLength(8)
|
||||
.Must(x => x.Any(char.IsUpper)).WithMessage("Password must contain at least one uppercase letter.")
|
||||
.Must(x => x.Any(char.IsLower)).WithMessage("Password must contain at least one lowercase letter.")
|
||||
.Must(x => x.Any(char.IsDigit)).WithMessage("Password must contain at least one digit.")
|
||||
.Equal(x => x.NewPasswordConfirmation);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user