From 01e11a66b977586262151d45b38875210fd277d4 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Sun, 12 Mar 2023 19:40:45 +0100 Subject: [PATCH 01/11] Create basic register form --- .../Pages/Member/PasswordReset.razor | 4 +- .../Pages/Member/Register.razor | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/iRLeagueManager.Web/Pages/Member/Register.razor diff --git a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor index 39178a59..d99287b9 100644 --- a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor +++ b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor @@ -55,7 +55,7 @@ private bool Success { get; set; } - private StatusResultValidator ResultValidator { get; set; } = default!; + private StatusResultValidator? ResultValidator { get; set; } public record SetPassword { @@ -86,7 +86,7 @@ var result = await request; if (result.Success == false) { - ResultValidator.ValidateResult(result.ToStatusResult()); + ResultValidator?.ValidateResult(result.ToStatusResult()); return; } Success = true; diff --git a/src/iRLeagueManager.Web/Pages/Member/Register.razor b/src/iRLeagueManager.Web/Pages/Member/Register.razor new file mode 100644 index 00000000..9263872f --- /dev/null +++ b/src/iRLeagueManager.Web/Pages/Member/Register.razor @@ -0,0 +1,44 @@ +@page "/member/Register" +@using iRLeagueApiCore.Common.Models.Users; + +
+
+
+ +
+
+ + +
+ + + +
+
+ + + +
+
+ + + +
+
+ + +
+
+
+
+
+ +@code { + private StatusResultValidator? ResultValidator { get; set; } + + private RegisterModel Model { get; } = new(); + + private bool PrivacyPolicyAgreeed { get; set; } = false; +} From ef880fc3c7d90f27b4d5790e6c7dc3f80dde3807 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Sat, 18 Mar 2023 20:16:14 +0100 Subject: [PATCH 02/11] Add complete form validation --- .../Pages/Member/Register.razor | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/iRLeagueManager.Web/Pages/Member/Register.razor b/src/iRLeagueManager.Web/Pages/Member/Register.razor index 9263872f..d435a220 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Register.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Register.razor @@ -1,5 +1,5 @@ @page "/member/Register" -@using iRLeagueApiCore.Common.Models.Users; +@using System.ComponentModel.DataAnnotations;
@@ -8,7 +8,8 @@
- + +
@@ -17,18 +18,35 @@
- +
-
- +
+ + + +
+
+ + +
+
+ + + +
+
+ +
@@ -38,7 +56,29 @@ @code { private StatusResultValidator? ResultValidator { get; set; } - private RegisterModel Model { get; } = new(); + private class RegisterModel : iRLeagueApiCore.Common.Models.Users.RegisterModel + { + [Required] + [MinLength(4)] + [RegularExpression("^[a-zA-Z0-9_-]{4,}$", ErrorMessage = "Username can only contain following characters: \"a-zA-Z0-9_-\"")] + public new string Username { get => base.Username; set => base.Username = value; } + + [Required] + [RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])?(?=.*[#$^+=!*()@%&]).{8,255}$", ErrorMessage = @"Password must be at leas 8 characters long, contain upper and lowercase letters and at least one special character (#$^+=!*()@%&)")] + public new string Password { get => base.Password; set => base.Password = value; } + + [Required(ErrorMessage = "Password confirmation is required")] + [Compare(nameof(Password), ErrorMessage = "Confirmed passsword does not match")] + public string PasswordConfirm { get; set; } = string.Empty; + + [Required] + [Range(typeof(bool), "true", "true", ErrorMessage = "Please accept the privacy policy")] + public bool PrivacyPolicyAgreeed { get; set; } = false; + + [Required] + [Range(typeof(bool), "true", "true", ErrorMessage = "Please accept the terms and conditions")] + public bool TermsConditionsAgreed { get; set; } = false; + } - private bool PrivacyPolicyAgreeed { get; set; } = false; + private RegisterModel Model { get; set; } = new(); } From 18e9c03360732d7b2aa28b6e1dfd944486b6ffac Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Mon, 27 Mar 2023 21:21:11 +0200 Subject: [PATCH 03/11] Add pages for email confirmation --- .../Pages/Member/ConfirmEmail.razor | 17 ++++ .../Pages/Member/Login.razor | 19 ++++- .../Pages/Member/PasswordReset.razor | 1 + .../Pages/Member/ResendConfirmation.razor | 82 +++++++++++++++++++ .../Shared/StatusResultValidator.cs | 10 ++- src/iRLeagueManager.Web/appsettings.json | 4 +- .../iRLeagueManager.Web.csproj | 7 +- 7 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor create mode 100644 src/iRLeagueManager.Web/Pages/Member/ResendConfirmation.razor diff --git a/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor b/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor new file mode 100644 index 00000000..3a247841 --- /dev/null +++ b/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor @@ -0,0 +1,17 @@ +@page "/member/{UserId}/confirm/{ConfirmationToken}" + +@code { + [Parameter] + public string UserId { get; set; } = default!; + [Parameter] + public string ConfirmationToken { get; set; } = default!; + + protected override void OnParametersSet() + { + base.OnParametersSet(); + BlazorParameterNullException.ThrowIfNull(this, UserId); + BlazorParameterNullException.ThrowIfNull(this, ConfirmationToken); + } + + +} diff --git a/src/iRLeagueManager.Web/Pages/Member/Login.razor b/src/iRLeagueManager.Web/Pages/Member/Login.razor index 1e42645b..bfc91826 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Login.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Login.razor @@ -2,6 +2,7 @@ @using System.ComponentModel.DataAnnotations @using iRLeagueApiCore.Client @using iRLeagueApiCore.Client.Http +@using iRLeagueApiCore.Common.Responses; @using iRLeagueManager.Web.Extensions @inject IConfiguration configuration @inject ITokenStore tokenStore @@ -26,7 +27,12 @@
- +
diff --git a/src/iRLeagueManager.Web/Pages/Member/ResendConfirmation.razor b/src/iRLeagueManager.Web/Pages/Member/ResendConfirmation.razor new file mode 100644 index 00000000..cade0f92 --- /dev/null +++ b/src/iRLeagueManager.Web/Pages/Member/ResendConfirmation.razor @@ -0,0 +1,82 @@ +@page "/member/resend-confirmation" +@inject LeagueApiService ApiService +@inject NavigationManager NavigationManager +@using System.ComponentModel.DataAnnotations; +@using iRLeagueApiCore.Client.Endpoints; + +
+ @if (Success) + { +
+

An email with a confirmation link has been send to the given email address. Please make sure to check your spam folder if you cannot find any mail from us.

+

If you continue having problems with this step please contact simon@iRLeagueManager.net

+
+ } + else + { +
+
+ +
+
+ + + +
+ + + +
+ +
+
+
+ } +
+ +@code { + private sealed class ConfirmationContext + { + [Required] + [EmailAddress] + public string Email { get; set; } = string.Empty; + } + + private StatusResultValidator? ResultValidator { get; set; } + + private bool Loading { get; set; } = false; + + private bool Success { get; set; } = false; + + private ConfirmationContext Context { get; } = new(); + + private async Task Submit() + { + try + { + Loading = true; + var linkTemplate = $$"""{{NavigationManager.BaseUri}}member/{userId}/confirm/{token}"""; + var result = await ApiService.Client + .Users() + .ResendConfirmation() + .AddQueryParameter(x => x.Add("linkTemplate", linkTemplate)) + .Post(Context.Email); + if (result.Success == false) + { + ResultValidator?.ValidateResult(result.ToStatusResult()); + return; + } + Success = true; + } + finally + { + Loading = false; + } + } +} diff --git a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs index ddfd1b3a..c182da4a 100644 --- a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs +++ b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs @@ -46,7 +46,7 @@ public void ValidateResult(StatusResult result) switch (result.Status) { case StatusResult.Unauthorized: - AddUnauthorizedValidationMessages(); + AddUnauthorizedValidationMessages(result); break; case StatusResult.BadRequest: AddBadRequestValidationMessages(result); @@ -73,8 +73,14 @@ private void DisplayErrorMessage(StatusResult result) } } - private void AddUnauthorizedValidationMessages() + private void AddUnauthorizedValidationMessages(StatusResult result) { + if (result.Message == "MailConfirm") + { + ErrorMessage = "Email confirmation is missing"; + return; + } + var usernameField = CurrentEditContext.Field("Username"); var passwordField = CurrentEditContext.Field("Password"); messageStore.Add(usernameField, ""); diff --git a/src/iRLeagueManager.Web/appsettings.json b/src/iRLeagueManager.Web/appsettings.json index bc04f2c2..8813a99e 100644 --- a/src/iRLeagueManager.Web/appsettings.json +++ b/src/iRLeagueManager.Web/appsettings.json @@ -9,8 +9,8 @@ } }, "AllowedHosts": "*", - //"APIServer": "http://localhost:5000", - "APIServer": "https://irleaguemanager.net/api/", + "APIServer": "http://localhost:5000", + //"APIServer": "https://irleaguemanager.net/api/", "DefaultUser": "testuser", "DefaultPassword": "TestPass123!" } diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index 8de15574..9e9ba5d8 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -2,11 +2,12 @@ net6.0 - 0.5.1 + 0.6.0-dev.1 enable enable aspnet-iRLeagueManager.Web-2B05F9DC-55A3-49D1-BD64-31507000EDF3 Debug;Release; + 11 @@ -130,8 +131,8 @@ - - + + From b0ba609ce795f5f4f6c0a7e43564587ba9f690aa Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Tue, 28 Mar 2023 13:24:11 +0200 Subject: [PATCH 04/11] Finish up registration and confirmation pages --- .../Pages/Member/ConfirmEmail.razor | 53 +++++++ .../Pages/Member/Register.razor | 144 ++++++++++++------ .../iRLeagueManager.Web.csproj | 2 +- 3 files changed, 151 insertions(+), 48 deletions(-) diff --git a/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor b/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor index 3a247841..4a43bc31 100644 --- a/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor +++ b/src/iRLeagueManager.Web/Pages/Member/ConfirmEmail.razor @@ -1,4 +1,29 @@ @page "/member/{UserId}/confirm/{ConfirmationToken}" +@inject LeagueApiService ApiService +@inject NavigationManager NavigationManager + +
+ @if (Success) + { +

+ Your email has been successfully verified. + You can now log into your account with your username and password +

+ + Login + + } + else if (Error) + { +

Oops, something went wrong! Please contact the administrator if you continue having problems.

+ } + else + { +

+ Processing email confirmation ... +

+ } +
@code { [Parameter] @@ -6,6 +31,9 @@ [Parameter] public string ConfirmationToken { get; set; } = default!; + private bool Success { get; set; } = false; + private bool Error { get; set; } = false; + protected override void OnParametersSet() { base.OnParametersSet(); @@ -13,5 +41,30 @@ BlazorParameterNullException.ThrowIfNull(this, ConfirmationToken); } + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (firstRender == false) + { + return; + } + var result = await ApiService.Client + .Users() + .WithId(UserId) + .ConfirmEmail(ConfirmationToken) + .Post(); + if (result.Success) + { + Success = true; + await InvokeAsync(StateHasChanged); + await Task.Delay(3000); + NavigationManager.NavigateTo("/member/login"); + } + else + { + Error = true; + } + await InvokeAsync(StateHasChanged); + } } diff --git a/src/iRLeagueManager.Web/Pages/Member/Register.razor b/src/iRLeagueManager.Web/Pages/Member/Register.razor index d435a220..13e9f9ca 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Register.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Register.razor @@ -1,61 +1,87 @@ @page "/member/Register" +@inject LeagueApiService ApiService +@inject NavigationManager NavigationManager @using System.ComponentModel.DataAnnotations; +@using iRLeagueApiCore.Client.Endpoints;
-
-
- + @if (Success) + { +
+

Thank you for your registration!

+

+ An email with a confirmation link has been send to the given email address. Please make sure to check your spam folder if you cannot find any mail from us.
+ Please click the link in the email to finish up your registration and activate your account. +

-
- - - -
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - -
-
+ } + else + { +
+
+ +
+
+ + + +
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + +
+
+
-
+ }
@code { private StatusResultValidator? ResultValidator { get; set; } + private bool Loading { get; set; } = false; + + private bool Success { get; set; } = false; + private class RegisterModel : iRLeagueApiCore.Common.Models.Users.RegisterModel { [Required] @@ -81,4 +107,28 @@ } private RegisterModel Model { get; set; } = new(); + + private async Task Submit() + { + try + { + Loading = true; + Success = false; + var linkTemplate = $$"""{{NavigationManager.BaseUri}}member/{userId}/confirm/{token}"""; + var result = await ApiService.Client + .Authenticate() + .Register() + .AddQueryParameter(x => x.Add("linkTemplate", linkTemplate)) + .Post(Model); + if (result.Success) + { + Success = true; + } + ResultValidator?.ValidateResult(result.ToStatusResult()); + } + finally + { + Loading = false; + } + } } diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index 9e9ba5d8..9d4a1318 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -131,7 +131,7 @@ - + From 1d28457d67ce8626936f385b5f25ced0565d28ab Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 30 Mar 2023 13:00:47 +0200 Subject: [PATCH 05/11] Add signup link to login page --- src/iRLeagueManager.Web/Pages/Member/Login.razor | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/iRLeagueManager.Web/Pages/Member/Login.razor b/src/iRLeagueManager.Web/Pages/Member/Login.razor index bfc91826..8910c598 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Login.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Login.razor @@ -40,7 +40,15 @@ Login - Forgot password + +
+ Not a member yet? +
+
From 1520e6676110d5d308c628c2de2c1666c8d19276 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 30 Mar 2023 13:08:37 +0200 Subject: [PATCH 06/11] Add sign up link in dropdown and fix login/logout return url --- src/iRLeagueManager.Web/Shared/Header.razor | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/iRLeagueManager.Web/Shared/Header.razor b/src/iRLeagueManager.Web/Shared/Header.razor index cca95e89..be60e9d1 100644 --- a/src/iRLeagueManager.Web/Shared/Header.razor +++ b/src/iRLeagueManager.Web/Shared/Header.razor @@ -108,10 +108,11 @@ }
  • -
  • Logout
  • +
  • NavigateTo($"/member/logout?returnUrl={GetReturnUrl()}"))>Logout
  • -
  • Login
  • +
  • NavigateTo($"/member/login?returnUrl={GetReturnUrl()}"))>Login
  • +
  • Sign Up
  • From 555f72de6636934879e9915872ac6b6c7f49d386 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 30 Mar 2023 13:23:06 +0200 Subject: [PATCH 07/11] Add firstname, lastname fields --- src/iRLeagueManager.Web/Pages/Member/Register.razor | 12 ++++++++++++ src/iRLeagueManager.Web/iRLeagueManager.Web.csproj | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/iRLeagueManager.Web/Pages/Member/Register.razor b/src/iRLeagueManager.Web/Pages/Member/Register.razor index 13e9f9ca..a2685b59 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Register.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Register.razor @@ -30,6 +30,18 @@ +
    +
    + + + +
    +
    + + + +
    +
    diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index 9d4a1318..368e90d6 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -132,7 +132,7 @@ - + From b77b69965f0ee7fd53c3dad7bb30661e7db4bbaa Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Sat, 1 Apr 2023 22:56:53 +0200 Subject: [PATCH 08/11] Implement display of users according to privacy settings --- .../Components/DisplayUser.razor | 33 +++++++++++++++++++ .../Components/Reviews/ReviewCard.razor | 1 + .../Components/Reviews/ReviewComment.razor | 10 +++++- .../Components/Settings/SearchUserModal.razor | 4 +-- src/iRLeagueManager.Web/Pages/Reviews.razor | 3 ++ .../Pages/Settings/UserSettings.razor | 11 ++----- .../ViewModels/ReviewsPageViewModel.cs | 28 ++++++++++++++++ 7 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 src/iRLeagueManager.Web/Components/DisplayUser.razor diff --git a/src/iRLeagueManager.Web/Components/DisplayUser.razor b/src/iRLeagueManager.Web/Components/DisplayUser.razor new file mode 100644 index 00000000..47b6f795 --- /dev/null +++ b/src/iRLeagueManager.Web/Components/DisplayUser.razor @@ -0,0 +1,33 @@ +@using iRLeagueApiCore.Common.Models.Users; + +
    + @if (User is null || (string.IsNullOrEmpty(User.Firstname) && string.IsNullOrEmpty(User.Firstname))) + { + + } + else + { + + @if (ShowUserName) + { + + } + } +
    + +@code { + [Parameter] + public string FallbackName { get; set; } = string.Empty; + [Parameter] + public UserModel? User { get; set; } + [Parameter] + public bool ShowUserName { get; set; } = true; + + protected override void OnParametersSet() + { + if (string.IsNullOrEmpty(FallbackName) && User is not null) + { + FallbackName = User.UserName; + } + } +} diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor index 25e3f752..f6f6a45d 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor @@ -4,6 +4,7 @@ @using Blazored.Typeahead @using iRLeagueApiCore.Common.Models @using iRLeagueApiCore.Common.Models.Reviews +@using iRLeagueApiCore.Common.Models.Users; @using iRLeagueManager.Web.ViewModels @inject NavigationManager NavigationManager diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor index ab8aa187..8a6a1911 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor @@ -1,11 +1,12 @@ @inherits MvvmComponentBase @using iRLeagueApiCore.Common.Models @using iRLeagueApiCore.Common.Models.Reviews +@using iRLeagueApiCore.Common.Models.Users; @using iRLeagueManager.Web.ViewModels
    -
    @Bind(Comment, x => x.AuthorName)
    +
    @Bind(Comment, x=> x.Text)
    @@ -36,6 +37,8 @@ public IModalService ModalService { get; set; } = default!; [CascadingParameter] public IEnumerable InvolvedMembers { get; set; } = Array.Empty(); + [CascadingParameter] + public IEnumerable LeagueUsers { get; set; } = Array.Empty(); [Parameter, EditorRequired] public ReviewCommentViewModel Comment { get; set; } = default!; [CascadingParameter] @@ -101,4 +104,9 @@ await OnStateHasChanged.InvokeAsync(); } } + + private UserModel? GetUser(string userId) + { + return LeagueUsers.FirstOrDefault(x => x.UserId == userId); + } } diff --git a/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor b/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor index 4124e050..3cad8af2 100644 --- a/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor +++ b/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor @@ -10,10 +10,10 @@ Debounce=500 placeholder="Type Name ..."> - @user?.UserName + - @user.UserName (@user.Firstname @user.Lastname) + + @switch (SelectedTabIndex) { case 0: @@ -124,6 +125,7 @@ break; } +
    @code { @@ -178,6 +180,7 @@ { return; } + await ReviewsVm.LoadUsers(); SelectedTabIndex = NavigationManager.QueryParameter(tabIndexParam); SelectedReviewId = NavigationManager.QueryParameter(reviewIdParam); } diff --git a/src/iRLeagueManager.Web/Pages/Settings/UserSettings.razor b/src/iRLeagueManager.Web/Pages/Settings/UserSettings.razor index 044e4506..74b9de40 100644 --- a/src/iRLeagueManager.Web/Pages/Settings/UserSettings.razor +++ b/src/iRLeagueManager.Web/Pages/Settings/UserSettings.razor @@ -30,14 +30,9 @@ @foreach(var user in @Bind(Users, x => x.LeagueUsers)) { - @if (string.IsNullOrWhiteSpace(user.FirstName) && string.IsNullOrWhiteSpace(user.LastName)) - { - @user.UserName - } - else - { - @user.FirstName @user.LastName - } + + + @foreach(var role in LeagueRoles.RolesAvailable) { diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs index cec8173b..952f48ed 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs @@ -1,5 +1,6 @@ using iRLeagueApiCore.Common.Enums; using iRLeagueApiCore.Common.Models; +using iRLeagueApiCore.Common.Models.Users; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; @@ -30,6 +31,9 @@ public ReviewsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiSe private IEnumerable eventMembers = Array.Empty(); public IEnumerable EventMembers { get => eventMembers; set => Set(ref eventMembers, value); } + private ObservableCollection leagueUsers = new(); + public ObservableCollection LeagueUsers { get => leagueUsers; set => Set(ref leagueUsers, value); } + public async Task LoadFromEventAsync(long eventId, CancellationToken cancellationToken = default) { if (ApiService.CurrentLeague == null) @@ -101,6 +105,30 @@ public async Task LoadFromEventAsync(long eventId, CancellationToken cancellatio } } + public async Task LoadUsers(CancellationToken cancellationToken = default) + { + if (CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = true; + var result = await CurrentLeague.Users() + .Get(cancellationToken); + if (result.Success && result.Content is not null) + { + LeagueUsers = new(result.Content); + } + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } + public async Task FileProtest(long sessionId, PostProtestModel protest, CancellationToken cancellationToken = default) { if (ApiService.CurrentLeague is null) From 2657426158333fb0f2c033232c6a6ff9ef560bb1 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Sun, 2 Apr 2023 00:44:21 +0200 Subject: [PATCH 09/11] Add profile page --- .../Components/DisplayUser.razor | 2 +- .../Pages/Member/PasswordReset.razor | 2 +- .../Pages/Member/Profile.razor | 90 +++++++++++++++++++ .../Pages/Member/RequestPasswordReset.razor | 2 +- src/iRLeagueManager.Web/Program.cs | 6 ++ src/iRLeagueManager.Web/Services.cs | 1 + src/iRLeagueManager.Web/Shared/Header.razor | 2 +- .../Shared/ProfileHandler.cs | 33 +++++++ .../Shared/ProfileOwnerRequirement.cs | 10 +++ .../ViewModels/LeagueViewModelBase.cs | 1 + .../ViewModels/UserViewModel.cs | 77 ++++++++++++++++ .../iRLeagueManager.Web.csproj | 4 +- src/iRLeagueManager.Web/wwwroot/css/site.css | 4 + 13 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/iRLeagueManager.Web/Pages/Member/Profile.razor create mode 100644 src/iRLeagueManager.Web/Shared/ProfileHandler.cs create mode 100644 src/iRLeagueManager.Web/Shared/ProfileOwnerRequirement.cs create mode 100644 src/iRLeagueManager.Web/ViewModels/UserViewModel.cs diff --git a/src/iRLeagueManager.Web/Components/DisplayUser.razor b/src/iRLeagueManager.Web/Components/DisplayUser.razor index 47b6f795..1cbcf5a4 100644 --- a/src/iRLeagueManager.Web/Components/DisplayUser.razor +++ b/src/iRLeagueManager.Web/Components/DisplayUser.razor @@ -7,7 +7,7 @@ } else { - + @if (ShowUserName) { diff --git a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor index f8c940e3..89805379 100644 --- a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor +++ b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor @@ -82,7 +82,7 @@ Loading = true; var token = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(ResetToken)); var requestUrl = $"Authenticate/SetPassword/{UserId}"; - var request = ApiService.Client.CustomEndpoint(requestUrl) + var request = ApiService.Client.CustomEndpoint(requestUrl) .Post(new { PasswordToken = token, NewPassword = model.NewPassword}); var result = await request; if (result.Success == false) diff --git a/src/iRLeagueManager.Web/Pages/Member/Profile.razor b/src/iRLeagueManager.Web/Pages/Member/Profile.razor new file mode 100644 index 00000000..997012a4 --- /dev/null +++ b/src/iRLeagueManager.Web/Pages/Member/Profile.razor @@ -0,0 +1,90 @@ +@page "/member/{UserId}/profile" +@inject UserViewModel User; +@using iRLeagueApiCore.Common.Models.Users; + +
    +
    +
    + +
    +
    + + + +
    + +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + +
    +
    + + + +
    + @if (User.HasChanged) + { +
    + + +
    + } +
    +
    +
    +
    +
    +
    +
    + +@code { + [Parameter] + public string UserId { get; set; } = default!; + + private StatusResultValidator? ResultValidator { get; set; } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (firstRender == false) + { + return; + } + await User.LoadUser(UserId); + await InvokeAsync(StateHasChanged); + } + + private async Task SaveChanges() + { + var result = await User.SaveChangesAsync(); + if (result.IsSuccess == false) + { + ResultValidator?.ValidateResult(result); + } + } +} diff --git a/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor b/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor index 0781e5cb..ccffb069 100644 --- a/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor +++ b/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor @@ -70,7 +70,7 @@ Loading = true; model.LinkUriTemplate = GenerateLinkUrlTemplate(); var requestUrl = $"Authenticate/ResetPassword"; - var request = ApiService.Client.CustomEndpoint(requestUrl) + var request = ApiService.Client.CustomEndpoint(requestUrl) .Post(model); var result = await request; if (result.Success == false) diff --git a/src/iRLeagueManager.Web/Program.cs b/src/iRLeagueManager.Web/Program.cs index 4ffb7213..4ec14cf5 100644 --- a/src/iRLeagueManager.Web/Program.cs +++ b/src/iRLeagueManager.Web/Program.cs @@ -12,6 +12,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Reflection; +using Microsoft.AspNetCore.Authorization; var builder = WebApplication.CreateBuilder(args); @@ -46,6 +47,11 @@ builder.Services.AddScoped(); builder.Services.AddTrackList(); builder.Services.AddViewModels(); +builder.Services.AddSingleton(); +builder.Services.AddAuthorization(config => +{ + config.AddPolicy(ProfileOwnerRequirement.Policy, policy => policy.AddRequirements(new ProfileOwnerRequirement())); +}); builder.Services.AddBlazoredModal(); builder.Services.AddLocalization(); diff --git a/src/iRLeagueManager.Web/Services.cs b/src/iRLeagueManager.Web/Services.cs index 18fce473..d3575219 100644 --- a/src/iRLeagueManager.Web/Services.cs +++ b/src/iRLeagueManager.Web/Services.cs @@ -31,6 +31,7 @@ public static IServiceCollection AddViewModels(this IServiceCollection services) services.TryAddTransient(); services.TryAddTransient(); services.TryAddTransient(); + services.TryAddTransient(); services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); diff --git a/src/iRLeagueManager.Web/Shared/Header.razor b/src/iRLeagueManager.Web/Shared/Header.razor index be60e9d1..5b44e762 100644 --- a/src/iRLeagueManager.Web/Shared/Header.razor +++ b/src/iRLeagueManager.Web/Shared/Header.razor @@ -101,7 +101,7 @@ From f0a09a3d9c35e618ea21ee19fd9a99966574ec63 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Sun, 2 Apr 2023 01:07:48 +0200 Subject: [PATCH 11/11] bump version to 0.6.0 update packages --- src/iRLeagueManager.Web/iRLeagueManager.Web.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index ce1da068..dd0b5dd2 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -2,7 +2,7 @@ net6.0 - 0.6.0-dev.1 + 0.6.0 enable enable aspnet-iRLeagueManager.Web-2B05F9DC-55A3-49D1-BD64-31507000EDF3 @@ -131,8 +131,8 @@ - - + +