diff --git a/WatchIt.Common/WatchIt.Common.Model/Accounts/AccountEmailRequest.cs b/WatchIt.Common/WatchIt.Common.Model/Accounts/AccountEmailRequest.cs new file mode 100644 index 0000000..bdf5bab --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Accounts/AccountEmailRequest.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace WatchIt.Common.Model.Accounts; + +public class AccountEmailRequest +{ + #region PROPERTIES + + [JsonPropertyName("new_email")] + public string NewEmail { get; set; } + + [JsonPropertyName("password")] + public string Password { get; set; } + + #endregion + + + + #region PUBLIC METHODS + + public void UpdateAccount(Database.Model.Account.Account account) + { + account.Email = NewEmail; + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Accounts/AccountPasswordRequest.cs b/WatchIt.Common/WatchIt.Common.Model/Accounts/AccountPasswordRequest.cs new file mode 100644 index 0000000..e0048c1 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Accounts/AccountPasswordRequest.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; + +namespace WatchIt.Common.Model.Accounts; + +public class AccountPasswordRequest +{ + #region PROPERTIES + + [JsonPropertyName("old_password")] + public string OldPassword { get; set; } + + [JsonPropertyName("new_password")] + public string NewPassword { get; set; } + + [JsonPropertyName("new_password_confirmation")] + public string NewPasswordConfirmation { get; set; } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs index c24a5ec..f7f5db4 100644 --- a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs @@ -15,9 +15,9 @@ public class Account public short? GenderId { get; set; } public Guid? ProfilePictureId { get; set; } public Guid? BackgroundPictureId { get; set; } - public required byte[] Password { get; set; } - public required string LeftSalt { get; set; } - public required string RightSalt { get; set; } + public byte[] Password { get; set; } + public string LeftSalt { get; set; } + public string RightSalt { get; set; } public bool IsAdmin { get; set; } = false; public DateTime CreationDate { get; set; } public DateTime LastActive { get; set; } diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs index 1b93fe9..56ea67a 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs @@ -114,6 +114,20 @@ public class AccountsController(IAccountsControllerService accountsControllerSer [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task 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 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 PatchAccountPassword([FromBody]AccountPasswordRequest data) => await accountsControllerService.PatchAccountPassword(data); + #endregion [HttpGet("{id}/movies")] diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs index 67d41c1..cb6a052 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs @@ -37,18 +37,13 @@ public class AccountsControllerService( public async Task 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 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 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 } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs index 481603e..0728d3e 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs @@ -22,6 +22,8 @@ public interface IAccountsControllerService Task GetAccountInfo(long id); Task PutAccountProfileInfo(AccountProfileInfoRequest data); Task PatchAccountUsername(AccountUsernameRequest data); + Task PatchAccountEmail(AccountEmailRequest data); + Task PatchAccountPassword(AccountPasswordRequest data); Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query); Task GetAccountRatedSeries(long id, SeriesRatedQueryParameters query); Task GetAccountRatedPersons(long id, PersonRatedQueryParameters query); diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Accounts/AccountEmailRequestValidator.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Accounts/AccountEmailRequestValidator.cs new file mode 100644 index 0000000..6bc7e63 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Accounts/AccountEmailRequestValidator.cs @@ -0,0 +1,15 @@ +using FluentValidation; +using WatchIt.Common.Model.Accounts; +using WatchIt.Database; + +namespace WatchIt.WebAPI.Validators.Accounts; + +public class AccountEmailRequestValidator : AbstractValidator +{ + public AccountEmailRequestValidator(DatabaseContext database) + { + RuleFor(x => x.NewEmail).EmailAddress() + .CannotBeIn(database.Accounts, x => x.Email) + .WithMessage("Email was already used"); + } +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Accounts/AccountPasswordRequestValidator.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Accounts/AccountPasswordRequestValidator.cs new file mode 100644 index 0000000..ffa2096 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Accounts/AccountPasswordRequestValidator.cs @@ -0,0 +1,17 @@ +using FluentValidation; +using WatchIt.Common.Model.Accounts; +using WatchIt.Database; + +namespace WatchIt.WebAPI.Validators.Accounts; + +public class AccountPasswordRequestValidator : AbstractValidator +{ + 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); + } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs index d73728e..49e0344 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs @@ -191,6 +191,36 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig .ExecuteAction(); } + public async Task PatchAccountEmail(AccountEmailRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.PatchAccountEmail); + HttpRequest request = new HttpRequest(HttpMethodType.Patch, url) + { + Body = data, + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor400BadRequest(badRequestAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .ExecuteAction(); + } + + public async Task PatchAccountPassword(AccountPasswordRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.PatchAccountPassword); + HttpRequest request = new HttpRequest(HttpMethodType.Patch, url) + { + Body = data, + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor400BadRequest(badRequestAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .ExecuteAction(); + } + public async Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null) { string url = GetUrl(EndpointsConfiguration.Accounts.GetAccountRatedMovies, id); diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs index 4a86d8f..84b48f5 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs @@ -21,6 +21,8 @@ public interface IAccountsClientService Task GetAccountInfo(long id, Action? successAction = null, Action? notFoundAction = null); Task PutAccountProfileInfo(AccountProfileInfoRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); Task PatchAccountUsername(AccountUsernameRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); + Task PatchAccountEmail(AccountEmailRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); + Task PatchAccountPassword(AccountPasswordRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null); Task GetAccountRatedSeries(long id, SeriesRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null); Task GetAccountRatedPersons(long id, PersonRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null); diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs index 04e8c7f..fae7f58 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs @@ -16,6 +16,8 @@ public class Accounts public string GetAccountInfo { get; set; } public string PutAccountProfileInfo { get; set; } public string PatchAccountUsername { get; set; } + public string PatchAccountEmail { get; set; } + public string PatchAccountPassword { get; set; } public string GetAccountRatedMovies { get; set; } public string GetAccountRatedSeries { get; set; } public string GetAccountRatedPersons { get; set; } diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewEmailPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewEmailPanelComponent.razor new file mode 100644 index 0000000..612abe7 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewEmailPanelComponent.razor @@ -0,0 +1,46 @@ +
+
+

Change email

+ @if (_data is not null) + { + + +
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ @if (!string.IsNullOrWhiteSpace(_error)) + { + @(_error) + } + else if (_saved) + { + New email saved! + } +
+
+ +
+
+
+
+ } + else + { + + } +
+
\ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewEmailPanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewEmailPanelComponent.razor.cs new file mode 100644 index 0000000..77043e6 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewEmailPanelComponent.razor.cs @@ -0,0 +1,83 @@ +using Microsoft.AspNetCore.Components; +using WatchIt.Common.Model.Accounts; +using WatchIt.Website.Services.Client.Accounts; + +namespace WatchIt.Website.Components.Pages.UserEditPage.Panels; + +public partial class NewEmailPanelComponent : ComponentBase +{ + #region SERVICES + + [Inject] private IAccountsClientService AccountsClientService { get; set; } = default!; + [Inject] private NavigationManager NavigationManager { get; set; } = default!; + + #endregion + + + + #region PARAMETERS + + [Parameter] public required AccountResponse AccountData { get; set; } + + #endregion + + + + #region FIELDS + + private AccountEmailRequest? _data; + private string? _error; + private bool _saving; + private bool _saved; + + #endregion + + + + #region PRIVATE METHODS + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + _data = new AccountEmailRequest + { + NewEmail = AccountData.Email, + }; + StateHasChanged(); + } + } + + private async Task Save() + { + void Success() + { + _saved = true; + _saving = false; + _data = new AccountEmailRequest + { + NewEmail = _data!.NewEmail + }; + NavigationManager.Refresh(true); + } + + void BadRequest(IDictionary errors) + { + _error = errors.SelectMany(x => x.Value).FirstOrDefault() ?? "Unknown error"; + _saving = false; + } + + void Unauthorized() + { + _error = "Incorrect password"; + _saving = false; + } + + _saving = true; + _saved = false; + _error = null; + await AccountsClientService.PatchAccountEmail(_data!, Success, BadRequest, Unauthorized); + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewPasswordPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewPasswordPanelComponent.razor new file mode 100644 index 0000000..1a869ac --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewPasswordPanelComponent.razor @@ -0,0 +1,45 @@ +
+
+

Change password

+ + +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ @if (!string.IsNullOrWhiteSpace(_error)) + { + @(_error) + } + else if (_saved) + { + New email saved! + } +
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewPasswordPanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewPasswordPanelComponent.razor.cs new file mode 100644 index 0000000..7655c8c --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewPasswordPanelComponent.razor.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Components; +using WatchIt.Common.Model.Accounts; +using WatchIt.Website.Services.Client.Accounts; + +namespace WatchIt.Website.Components.Pages.UserEditPage.Panels; + +public partial class NewPasswordPanelComponent : ComponentBase +{ + #region SERVICES + + [Inject] private IAccountsClientService AccountsClientService { get; set; } = default!; + [Inject] private NavigationManager NavigationManager { get; set; } = default!; + + #endregion + + + + #region FIELDS + + private AccountPasswordRequest _data = new AccountPasswordRequest(); + private string? _error; + private bool _saving; + private bool _saved; + + #endregion + + + + #region PRIVATE METHODS + + private async Task Save() + { + void Success() + { + _saved = true; + _saving = false; + _data = new AccountPasswordRequest(); + NavigationManager.Refresh(true); + } + + void BadRequest(IDictionary errors) + { + _error = errors.SelectMany(x => x.Value).FirstOrDefault() ?? "Unknown error"; + _saving = false; + } + + void Unauthorized() + { + _error = "Incorrect password"; + _saving = false; + } + + _saving = true; + _saved = false; + _error = null; + await AccountsClientService.PatchAccountPassword(_data, Success, BadRequest, Unauthorized); + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewUsernamePanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewUsernamePanelComponent.razor.cs index 0a797fd..39eeb7f 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewUsernamePanelComponent.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/NewUsernamePanelComponent.razor.cs @@ -9,7 +9,6 @@ public partial class NewUsernamePanelComponent : ComponentBase { #region SERVICES - [Inject] private IAuthenticationService AuthenticationService { get; set; } = default!; [Inject] private IAccountsClientService AccountsClientService { get; set; } = default!; [Inject] private NavigationManager NavigationManager { get; set; } = default!; @@ -19,7 +18,7 @@ public partial class NewUsernamePanelComponent : ComponentBase #region PARAMETERS - [Parameter] public required long Id { get; set; } + [Parameter] public required AccountResponse AccountData { get; set; } #endregion @@ -42,21 +41,11 @@ public partial class NewUsernamePanelComponent : ComponentBase { if (firstRender) { - User? user = await AuthenticationService.GetUserAsync(); - - if (user is null) + _data = new AccountUsernameRequest { - return; - } - - await AccountsClientService.GetAccountInfo(user.Id, data => - { - _data = new AccountUsernameRequest - { - NewUsername = data.Username - }; - StateHasChanged(); - }); + NewUsername = AccountData.Username, + }; + StateHasChanged(); } } diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor index 8f9869a..b5a326d 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor @@ -23,7 +23,7 @@ @foreach (GenderResponse gender in _genders) { - + } diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor.cs index 59806dd..7407687 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/ProfileEditFormPanelComponent.razor.cs @@ -20,7 +20,7 @@ public partial class ProfileEditFormPanelComponent : ComponentBase #region PARAMETERS - [Parameter] public long Id { get; set; } + [Parameter] public required AccountResponse AccountData { get; set; } [Parameter] public string Class { get; set; } = string.Empty; #endregion @@ -47,11 +47,8 @@ public partial class ProfileEditFormPanelComponent : ComponentBase { if (firstRender) { - await Task.WhenAll( - [ - GendersClientService.GetAllGenders(successAction: data => _genders = data), - AccountsClientService.GetAccountInfo(Id, data => _accountProfileInfo = new AccountProfileInfoRequest(data)) - ]); + _accountProfileInfo = new AccountProfileInfoRequest(AccountData); + await GendersClientService.GetAllGenders(successAction: data => _genders = data); _loaded = true; StateHasChanged(); diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor index 2fd8305..f9a9c48 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor @@ -1,8 +1,8 @@
- +
-

@(_username ?? "Loading...")

+

@(AccountData.Username)

User settings
diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor.cs index 83f7d8e..7700867 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserEditPage/Panels/UserEditPageHeaderPanelComponent.razor.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Components; +using WatchIt.Common.Model.Accounts; using WatchIt.Website.Components.Common.Subcomponents; using WatchIt.Website.Services.Authentication; using WatchIt.Website.Services.Client.Accounts; @@ -18,7 +19,7 @@ public partial class UserEditPageHeaderPanelComponent : ComponentBase #region PARAMETERS - [Parameter] public required User User { get; set; } + [Parameter] public required AccountResponse AccountData { get; set; } #endregion @@ -27,7 +28,6 @@ public partial class UserEditPageHeaderPanelComponent : ComponentBase #region FIELDS private AccountPictureComponent _accountPicture = default!; - private string? _username; #endregion @@ -38,22 +38,4 @@ public partial class UserEditPageHeaderPanelComponent : ComponentBase public async Task ReloadPicture() => await _accountPicture.Reload(); #endregion - - - - #region PRIVATE METHODS - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender) - { - await AccountsClientService.GetAccountInfo(User.Id, data => - { - _username = data.Username; - StateHasChanged(); - }); - } - } - - #endregion } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor b/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor index 77dadc7..1ef2c1b 100644 --- a/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor +++ b/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor @@ -9,7 +9,7 @@ @{ StringBuilder sb = new StringBuilder(" - WatchIt"); - if (_user is null) sb.Insert(0, "Loading..."); + if (_accountData is null) sb.Insert(0, "Loading..."); else sb.Insert(0, "User settings"); @(sb.ToString()) @@ -18,11 +18,11 @@
- @if (_user is not null) + @if (_accountData is not null) {
- +
@@ -45,7 +45,7 @@
-
-
-
@@ -70,7 +70,9 @@
- + + +
diff --git a/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor.cs b/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor.cs index 8e4c5ea..4b29a60 100644 --- a/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Pages/UserEditPage.razor.cs @@ -1,6 +1,7 @@ using System.Net; using Microsoft.AspNetCore.Components; using WatchIt.Common.Model; +using WatchIt.Common.Model.Accounts; using WatchIt.Common.Model.Photos; using WatchIt.Website.Components.Pages.UserEditPage.Panels; using WatchIt.Website.Layout; @@ -31,7 +32,7 @@ public partial class UserEditPage : ComponentBase #region FIELDS - private User? _user; + private AccountResponse? _accountData; private UserEditPageHeaderPanelComponent _header = default!; @@ -47,15 +48,19 @@ public partial class UserEditPage : ComponentBase { Layout.BackgroundPhoto = null; - _user = await AuthenticationService.GetUserAsync(); - if (_user is null) + User? user = await AuthenticationService.GetUserAsync(); + if (user is null) { NavigationManager.NavigateTo($"/auth?redirect_to={WebUtility.UrlEncode("/user/edit")}"); return; } StateHasChanged(); - await AccountsClientService.GetAccountProfileBackground(_user.Id, data => Layout.BackgroundPhoto = data); + await Task.WhenAll( + [ + AccountsClientService.GetAccountInfo(user.Id, data => _accountData = data), + AccountsClientService.GetAccountProfileBackground(user.Id, data => Layout.BackgroundPhoto = data) + ]); StateHasChanged(); } } diff --git a/WatchIt.Website/WatchIt.Website/appsettings.json b/WatchIt.Website/WatchIt.Website/appsettings.json index a4eb5eb..943633b 100644 --- a/WatchIt.Website/WatchIt.Website/appsettings.json +++ b/WatchIt.Website/WatchIt.Website/appsettings.json @@ -30,6 +30,8 @@ "GetAccountInfo": "/{0}/info", "PutAccountProfileInfo": "/profile_info", "PatchAccountUsername": "/username", + "PatchAccountEmail": "/email", + "PatchAccountPassword": "/password", "GetAccountRatedMovies": "/{0}/movies", "GetAccountRatedSeries": "/{0}/series", "GetAccountRatedPersons": "/{0}/persons"