Upgraded the last forms to the new mooncore version

This commit is contained in:
Marcel Baumgartner
2024-07-05 20:09:45 +02:00
parent 3f0ade7fb2
commit e53a1bad0e
5 changed files with 140 additions and 98 deletions

View File

@@ -1,9 +0,0 @@
using System.ComponentModel;
namespace Moonlight.Core.Models.Forms;
public class ChangeCookiesForm
{
[Description("This specifies if you would like to personalize your experience with optional cookies.")]
public bool UseOptionalCookies { get; set; } = false;
}

View File

@@ -6,6 +6,7 @@
@using MoonCore.Exceptions @using MoonCore.Exceptions
@inject IdentityService IdentityService @inject IdentityService IdentityService
@inject AlertService AlertService
@inject IAuthenticationProvider AuthenticationProvider @inject IAuthenticationProvider AuthenticationProvider
@if (IdentityService.CurrentUser.Totp) @if (IdentityService.CurrentUser.Totp)
@@ -61,15 +62,15 @@ else
</div> </div>
</div> </div>
</div> </div>
<SmartForm Model="CodeForm" OnValidSubmit="VerifyAndEnable"> <div>
<input @bind="CodeForm.Code" type="number" class="form-control form-control-lg form-control-solid text-center my-8" placeholder="Enter authentication code" name="code"> <input @bind="CodeForm.Code" type="number" class="form-control form-control-lg form-control-solid text-center my-8" placeholder="Enter authentication code" name="code">
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<button type="submit" class="btn btn-primary"> <WButton OnClick="VerifyAndEnable" CssClasses="btn btn-primary">
Continue Continue
<i class="bx bx-sm bx-right-arrow-alt"></i> <i class="bx bx-sm bx-right-arrow-alt"></i>
</button> </WButton>
</div>
</div> </div>
</SmartForm>
</div> </div>
} }
else else
@@ -170,7 +171,10 @@ else
var correctCode = totp.ComputeTotp(); var correctCode = totp.ComputeTotp();
if (CodeForm.Code != correctCode) if (CodeForm.Code != correctCode)
throw new DisplayException("Invalid code entered. Please try again"); {
await AlertService.Danger("Invalid code entered. Please try again");
return;
}
// Enable two factor auth for user // Enable two factor auth for user
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.CurrentUser, Key); await AuthenticationProvider.SetTwoFactorSecret(IdentityService.CurrentUser, Key);

View File

@@ -1,8 +1,10 @@
@page "/account" @page "/account"
@using System.ComponentModel.DataAnnotations
@using Moonlight.Core.Services @using Moonlight.Core.Services
@using Moonlight.Core.Models.Forms @using Moonlight.Core.Models.Forms
@using Mappy.Net @using Mappy.Net
@using Moonlight.Core.Database.Entities
@using Moonlight.Core.Models.Abstractions @using Moonlight.Core.Models.Abstractions
@using Moonlight.Core.UI.Components.Navigations @using Moonlight.Core.UI.Components.Navigations
@@ -22,9 +24,7 @@
<AccountNavigation Index="0"/> <AccountNavigation Index="0"/>
<LazyLoader Load="Load"> <div class="row g-5">
<div class="row g-5">
<div class="col-md-3 col-12"> <div class="col-md-3 col-12">
<div class="card card-body h-100"> <div class="card card-body h-100">
<div class="d-flex flex-column justify-content-center"> <div class="d-flex flex-column justify-content-center">
@@ -42,33 +42,55 @@
</div> </div>
<div class="col-md-9 col-12"> <div class="col-md-9 col-12">
<div class="card"> <div class="card">
<SmartForm Model="Form" OnValidSubmit="Update">
<div class="card-body"> <div class="card-body">
<AutoForm TForm="UpdateAccountForm" Columns="12" Model="Form"/> <FastForm @ref="Form" Model="User" OnConfigure="OnConfigure" />
</div> </div>
<div class="card-footer d-flex justify-content-end"> <div class="card-footer d-flex justify-content-end">
<button type="submit" class="btn btn-primary">Save changes</button> <WButton OnClick="SaveChanges" CssClasses="btn btn-primary">Save changes</WButton>
</div>
</SmartForm>
</div> </div>
</div> </div>
</div> </div>
</LazyLoader> </div>
@code @code
{ {
private UpdateAccountForm Form = new(); private User User;
private FastForm<User> Form;
private Task Load(LazyLoader _) protected override void OnInitialized()
{ {
Form = Mapper.Map<UpdateAccountForm>(IdentityService.CurrentUser); // Create a copy of the user
User = Mapper.Map<User>(IdentityService.CurrentUser);
return Task.CompletedTask;
} }
private async Task Update() private void OnConfigure(FastFormConfiguration<User> configuration)
{ {
await AuthenticationProvider.ChangeDetails(IdentityService.CurrentUser, Form.Email, Form.Username); configuration.AddProperty(x => x.Username)
.WithComponent<StringComponent>(component =>
{
component.ColumnsMd = 12;
})
.WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^[a-z][a-z0-9]*$", "Usernames can only contain lowercase characters and numbers and should not start with a number"))
.WithValidation(x => x.Length >= 6 ? ValidationResult.Success : new("The username is too short"))
.WithValidation(x => x.Length <= 20 ? ValidationResult.Success : new("The username cannot be longer than 20 characters"));
configuration.AddProperty(x => x.Email)
.WithComponent<StringComponent>(component =>
{
component.ColumnsMd = 12;
component.Type = "email";
})
.WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^.+@.+$", "You need to provide a valid email address"));
}
private async Task SaveChanges()
{
if(!await Form.Submit())
return;
await AuthenticationProvider.ChangeDetails(IdentityService.CurrentUser, User.Email, User.Username);
await ToastService.Success("Successfully updated details"); await ToastService.Success("Successfully updated details");
// This will trigger a re-render as well as an update of the model // This will trigger a re-render as well as an update of the model

View File

@@ -1,5 +1,6 @@
@page "/account/security" @page "/account/security"
@using System.ComponentModel.DataAnnotations
@using Moonlight.Core.Services @using Moonlight.Core.Services
@using Moonlight.Core.UI.Components.Navigations @using Moonlight.Core.UI.Components.Navigations
@using Moonlight.Core.Models.Forms @using Moonlight.Core.Models.Forms
@@ -23,20 +24,15 @@
<AccountNavigation Index="1"/> <AccountNavigation Index="1"/>
<LazyLoader Load="Load"> <div class="row g-5">
<div class="row g-5">
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card"> <div class="card">
<SmartForm Model="PasswordForm" OnValidSubmit="OnValidSubmitPassword">
<div class="card-body"> <div class="card-body">
<div class="row"> <FastForm @ref="PasswordForm" Model="PasswordModel" OnConfigure="OnConfigurePasswordForm" />
<AutoForm Model="PasswordForm" Columns="12" />
</div>
</div> </div>
<div class="card-footer d-flex justify-content-end"> <div class="card-footer d-flex justify-content-end">
<button class="btn btn-primary" type="submit">Save changes</button> <WButton OnClick="ChangePassword" CssClasses="btn btn-primary">Save changes</WButton>
</div> </div>
</SmartForm>
</div> </div>
</div> </div>
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
@@ -48,49 +44,77 @@
</div> </div>
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card h-100"> <div class="card h-100">
<SmartForm Model="CookiesForm" OnValidSubmit="OnValidSubmitCookie">
<div class="card-body"> <div class="card-body">
<h3>Cookies</h3> <h3>Cookies</h3>
<div> <p class="my-2 text-muted fs-5">
This specifies if you would like to personalize your experience with optional cookies.
<AutoForm Model="CookiesForm"/> </p>
</div> <div class="form-check form-switch">
</div> @if (CookieConsent)
<div class="card-footer d-flex justify-content-end"> {
<button class="btn btn-primary" type="submit">Save changes</button> <input @onclick="() => SetCookieConsent(false)" class="form-check-input" type="checkbox" role="switch" checked="checked">
</div> }
</SmartForm> else
{
<input @onclick="() => SetCookieConsent(true)" class="form-check-input" type="checkbox" role="switch">
}
</div> </div>
</div> </div>
</div> </div>
</LazyLoader> </div>
</div>
@code @code
{ {
private readonly ChangePasswordForm PasswordForm = new(); private ChangePasswordForm PasswordModel = new();
private FastForm<ChangePasswordForm> PasswordForm;
private ChangeCookiesForm CookiesForm = new(); private bool CookieConsent;
private async Task Load(LazyLoader lazyLoader) protected override async Task OnInitializedAsync()
{ {
CookiesForm.UseOptionalCookies = await IdentityService.HasFlag("CookieConsent"); CookieConsent = await IdentityService.HasFlag("CookieConsent");
} }
private async Task OnValidSubmitPassword() private async Task SetCookieConsent(bool flag)
{ {
if (PasswordForm.Password != PasswordForm.RepeatedPassword) await IdentityService.SetFlag("CookieConsent", flag);
await ToastService.Success("Successfully changed cookie preferences");
await InvokeAsync(StateHasChanged);
}
private void OnConfigurePasswordForm(FastFormConfiguration<ChangePasswordForm> configuration)
{
configuration.AddProperty(x => x.Password)
.WithComponent<StringComponent>(component =>
{
component.ColumnsMd = 6;
component.Type = "password";
})
.WithValidation(FastFormValidators.Required)
.WithValidation(x => x.Length >= 8 ? ValidationResult.Success : new("The password must be at least 8 characters long"))
.WithValidation(x => x.Length <= 256 ? ValidationResult.Success : new("The password must not be longer than 256 characters"));
configuration.AddProperty(x => x.RepeatedPassword)
.WithComponent<StringComponent>(component =>
{
component.ColumnsMd = 6;
component.Type = "password";
});
}
private async Task ChangePassword()
{
if(!await PasswordForm.Submit())
return;
if (PasswordModel.Password != PasswordModel.RepeatedPassword)
throw new DisplayException("The passwords do not match"); throw new DisplayException("The passwords do not match");
await AuthenticationProvider.ChangePassword(IdentityService.CurrentUser, PasswordForm.Password); await AuthenticationProvider.ChangePassword(IdentityService.CurrentUser, PasswordModel.Password);
await ToastService.Success("Successfully changed password"); await ToastService.Success("Successfully changed password");
await IdentityService.Authenticate(true); await IdentityService.Authenticate(true);
} }
private async Task OnValidSubmitCookie()
{
await IdentityService.SetFlag("CookieConsent", CookiesForm.UseOptionalCookies);
await InvokeAsync(StateHasChanged);
}
} }

View File

@@ -217,6 +217,7 @@
component.SearchFunc = x => $"{x.IpAddress}:{x.Port}"; component.SearchFunc = x => $"{x.IpAddress}:{x.Port}";
component.DisplayFunc = x => $"{x.IpAddress}:{x.Port}"; component.DisplayFunc = x => $"{x.IpAddress}:{x.Port}";
component.ItemsCallback = () =>GetAllocation(server); component.ItemsCallback = () =>GetAllocation(server);
component.ColumnsMd = 6;
}) })
.WithPage("Network"); .WithPage("Network");
} }