diff --git a/IntegryControlPanel/IntegryControlPanel.Client/Layout/AuthLayout.razor b/IntegryControlPanel/IntegryControlPanel.Client/Layout/AuthLayout.razor new file mode 100644 index 0000000..98ee0bb --- /dev/null +++ b/IntegryControlPanel/IntegryControlPanel.Client/Layout/AuthLayout.razor @@ -0,0 +1,99 @@ +@inherits LayoutComponentBase + + + + + + + + + @* + Integry Control Panel + + *@ + + + + @Body + + + + +
+ An unhandled error has occurred. + Reload + ?? +
+ +@code { + MudTheme MyCustomTheme = new MudTheme() + { + PaletteLight = new PaletteLight() + { + Primary = "#4CAF50", // Verde Material (puoi usare anche #43A047 o #2E7D32 per più scuro) + Secondary = "#00BFA5", // Verde acqua moderno + Tertiary = "#8BC34A", // Verde lime di supporto + Background = "#FDFDFD", + Surface = "#FFFFFF", + AppbarBackground = "#FFFFFF", + AppbarText = "#212121", + DrawerBackground = "#F9F9F9", + DrawerText = "#212121", + DrawerIcon = "#4CAF50", + TextPrimary = "#212121", + TextSecondary = "#616161", + ActionDefault = "#4CAF50", + ActionDisabled = "#BDBDBD", + Divider = "#E0E0E0", + LinesDefault = "#E0E0E0", + TableLines = "#E0E0E0" + }, + Typography = new Typography() + { + Default = new DefaultTypography() + { + FontFamily = ["Montserrat", "Roboto", "Helvetica", "Arial", "sans-serif"], + FontSize = ".95rem", + FontWeight = "400", + LineHeight = "1.5" + }, + H6 = new H6Typography() + { + FontSize = "1.1rem", + FontWeight = "500", + LetterSpacing = ".0156em" + }, + Button = new ButtonTypography() + { + TextTransform = "none", + FontWeight = "500" + } + }, + LayoutProperties = new LayoutProperties() + { + DefaultBorderRadius = "16px" // Flat ma leggermente smussato (stile Material You) + }, + Shadows = new Shadow() + { + + Elevation = + [ + + "none", // 0 + "0px 1px 2px rgba(0,0,0,0.05)", // 1 + "0px 2px 4px rgba(0,0,0,0.08)", // 2 + "0px 4px 8px rgba(0,0,0,0.1)", // 3 + "0px 8px 16px rgba(0,0,0,0.12)",// 4 + "0px 12px 24px rgba(0,0,0,0.14)",// 5 + // dal 6 al 24 puoi riciclare o tenere "none" + "none","none","none","none","none", + "none","none","none","none","none", + "none","none","none","none","none", + "none","none","none","none","none" + ] + } + }; +} \ No newline at end of file diff --git a/IntegryControlPanel/IntegryControlPanel.Client/Layout/MainLayout.razor b/IntegryControlPanel/IntegryControlPanel.Client/Layout/MainLayout.razor index 3e9bc61..aadf2ab 100644 --- a/IntegryControlPanel/IntegryControlPanel.Client/Layout/MainLayout.razor +++ b/IntegryControlPanel/IntegryControlPanel.Client/Layout/MainLayout.razor @@ -1,16 +1,16 @@ @inherits LayoutComponentBase - - - - + + + + - + Integry Control Panel - + @@ -18,10 +18,10 @@ - + - + @Body @@ -37,6 +37,74 @@ @code { private bool _drawerOpen = true; -} + MudTheme MyCustomTheme = new MudTheme() + { + PaletteLight = new PaletteLight() + { + Primary = "#4CAF50", // Verde Material (puoi usare anche #43A047 o #2E7D32 per più scuro) + Secondary = "#00BFA5", // Verde acqua moderno + Tertiary = "#8BC34A", // Verde lime di supporto + Background = "#FDFDFD", + Surface = "#FFFFFF", + AppbarBackground = "#FFFFFF", + AppbarText = "#212121", + DrawerBackground = "#F9F9F9", + DrawerText = "#212121", + DrawerIcon = "#4CAF50", + TextPrimary = "#212121", + TextSecondary = "#616161", + ActionDefault = "#4CAF50", + ActionDisabled = "#BDBDBD", + Divider = "#E0E0E0", + LinesDefault = "#E0E0E0", + TableLines = "#E0E0E0" + }, + Typography = new Typography() + { + Default = new DefaultTypography() + { + FontFamily = ["Roboto", "Helvetica", "Arial", "sans-serif"], + FontSize = ".95rem", + FontWeight = "400", + LineHeight = "1.5" + }, + H6 = new H6Typography() + { + FontSize = "1.1rem", + FontWeight = "500", + LetterSpacing = ".0156em" + }, + Button = new ButtonTypography() + { + TextTransform = "none", + FontWeight = "500" + } + }, + LayoutProperties = new LayoutProperties() + { + DefaultBorderRadius = "12px" // Flat ma leggermente smussato (stile Material You) + }, + Shadows = new Shadow() + { + + Elevation = + [ + + "none", // 0 + "0px 1px 2px rgba(0,0,0,0.05)", // 1 + "0px 2px 4px rgba(0,0,0,0.08)", // 2 + "0px 4px 8px rgba(0,0,0,0.1)", // 3 + "0px 8px 16px rgba(0,0,0,0.12)",// 4 + "0px 12px 24px rgba(0,0,0,0.14)",// 5 + // dal 6 al 24 puoi riciclare o tenere "none" + "none","none","none","none","none", + "none","none","none","none","none", + "none","none","none","none","none", + "none","none","none","none","none" + ] + } + }; + +} \ No newline at end of file diff --git a/IntegryControlPanel/IntegryControlPanel.Client/Layout/NavMenu.razor b/IntegryControlPanel/IntegryControlPanel.Client/Layout/NavMenu.razor index 1137a67..efa7e3a 100644 --- a/IntegryControlPanel/IntegryControlPanel.Client/Layout/NavMenu.razor +++ b/IntegryControlPanel/IntegryControlPanel.Client/Layout/NavMenu.razor @@ -6,31 +6,19 @@ Dashboard - - - Server - Client - Servizi - - - Counter - Weather - Auth Required - - - - Profilo (@context.User.Identity?.Name) - - Logout - - + + + Server + Client + Servizi + + + + Logout + - - Login - Register - @@ -54,5 +42,5 @@ { NavigationManager.LocationChanged -= OnLocationChanged; } -} +} \ No newline at end of file diff --git a/IntegryControlPanel/IntegryControlPanel.Client/Pages/Dashboard.razor b/IntegryControlPanel/IntegryControlPanel.Client/Pages/Dashboard.razor index 5c3cc8e..3e0203b 100644 --- a/IntegryControlPanel/IntegryControlPanel.Client/Pages/Dashboard.razor +++ b/IntegryControlPanel/IntegryControlPanel.Client/Pages/Dashboard.razor @@ -8,13 +8,13 @@ Dashboard - + @* Benvenuto, @context.User.Identity?.Name! - + *@ @@ -129,35 +129,7 @@ - - - - - - Informazioni Sistema - - - - -
- - Versione: 1.0.0 - -
-
- - Database: Connesso - -
-
- - LDAP: Connesso - -
-
-
-
-
+
diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityComponentsEndpointRouteBuilderExtensions.cs b/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityComponentsEndpointRouteBuilderExtensions.cs index b9c0ddf..e1a19dd 100644 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityComponentsEndpointRouteBuilderExtensions.cs +++ b/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityComponentsEndpointRouteBuilderExtensions.cs @@ -17,107 +17,30 @@ namespace Microsoft.AspNetCore.Routing // These endpoints are required by the Identity Razor components defined in the /Components/Account/Pages directory of this project. public static IEndpointConventionBuilder MapAdditionalIdentityEndpoints(this IEndpointRouteBuilder endpoints) { - ArgumentNullException.ThrowIfNull(endpoints); + ArgumentNullException.ThrowIfNull(endpoints); - var accountGroup = endpoints.MapGroup("/Account"); + var accountGroup = endpoints.MapGroup("/Account"); - accountGroup.MapPost("/PerformExternalLogin", ( - HttpContext context, - [FromServices] SignInManager signInManager, - [FromForm] string provider, - [FromForm] string returnUrl) => - { - IEnumerable> query = [ - new("ReturnUrl", returnUrl), - new("Action", ExternalLogin.LoginCallbackAction)]; + accountGroup.MapPost("/Logout", async ( + ClaimsPrincipal user, + [FromServices] SignInManager signInManager, + [FromForm] string returnUrl) => + { + await signInManager.SignOutAsync(); + return TypedResults.LocalRedirect($"~/{returnUrl}"); + }); - var redirectUrl = UriHelper.BuildRelative( - context.Request.PathBase, - "/Account/ExternalLogin", - QueryString.Create(query)); + // Add GET endpoint for logout to handle navigation from WebAssembly client + accountGroup.MapGet("/Logout", async ( + ClaimsPrincipal user, + [FromServices] SignInManager signInManager, + [FromQuery] string? returnUrl) => + { + await signInManager.SignOutAsync(); + return TypedResults.LocalRedirect($"~/{returnUrl ?? "Account/Login"}"); + }); - var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); - return TypedResults.Challenge(properties, [provider]); - }); - - accountGroup.MapPost("/Logout", async ( - ClaimsPrincipal user, - [FromServices] SignInManager signInManager, - [FromForm] string returnUrl) => - { - await signInManager.SignOutAsync(); - return TypedResults.LocalRedirect($"~/{returnUrl}"); - }); - - // Add GET endpoint for logout to handle navigation from WebAssembly client - accountGroup.MapGet("/Logout", async ( - ClaimsPrincipal user, - [FromServices] SignInManager signInManager, - [FromQuery] string? returnUrl) => - { - await signInManager.SignOutAsync(); - return TypedResults.LocalRedirect($"~/{returnUrl ?? "Account/Login"}"); - }); - - var manageGroup = accountGroup.MapGroup("/Manage").RequireAuthorization(); - - manageGroup.MapPost("/LinkExternalLogin", async ( - HttpContext context, - [FromServices] SignInManager signInManager, - [FromForm] string provider) => - { - // Clear the existing external cookie to ensure a clean login process - await context.SignOutAsync(IdentityConstants.ExternalScheme); - - var redirectUrl = UriHelper.BuildRelative( - context.Request.PathBase, - "/Account/Manage/ExternalLogins", - QueryString.Create("Action", ExternalLogins.LinkLoginCallbackAction)); - - var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, signInManager.UserManager.GetUserId(context.User)); - return TypedResults.Challenge(properties, [provider]); - }); - - var loggerFactory = endpoints.ServiceProvider.GetRequiredService(); - var downloadLogger = loggerFactory.CreateLogger("DownloadPersonalData"); - - manageGroup.MapPost("/DownloadPersonalData", async ( - HttpContext context, - [FromServices] UserManager userManager, - [FromServices] AuthenticationStateProvider authenticationStateProvider) => - { - var user = await userManager.GetUserAsync(context.User); - if (user is null) - { - return Results.NotFound($"Unable to load user with ID '{userManager.GetUserId(context.User)}'."); - } - - var userId = await userManager.GetUserIdAsync(user); - downloadLogger.LogInformation("User with ID '{UserId}' asked for their personal data.", userId); - - // Only include personal data for download - var personalData = new Dictionary(); - var personalDataProps = typeof(ApplicationUser).GetProperties().Where( - prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute))); - foreach (var p in personalDataProps) - { - personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null"); - } - - var logins = await userManager.GetLoginsAsync(user); - foreach (var l in logins) - { - personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey); - } - - personalData.Add("Authenticator Key", (await userManager.GetAuthenticatorKeyAsync(user))!); - var fileBytes = JsonSerializer.SerializeToUtf8Bytes(personalData); - - context.Response.Headers.TryAdd("Content-Disposition", "attachment; filename=PersonalData.json"); - return TypedResults.File(fileBytes, contentType: "application/json", fileDownloadName: "PersonalData.json"); - }); - - return accountGroup; - } + return accountGroup; + } } } diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityNoOpEmailSender.cs b/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityNoOpEmailSender.cs deleted file mode 100644 index 51f48b1..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/IdentityNoOpEmailSender.cs +++ /dev/null @@ -1,21 +0,0 @@ -using IntegryControlPanel.Data; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI.Services; - -namespace IntegryControlPanel.Components.Account -{ - // Remove the "else if (EmailSender is IdentityNoOpEmailSender)" block from RegisterConfirmation.razor after updating with a real implementation. - internal sealed class IdentityNoOpEmailSender : IEmailSender - { - private readonly IEmailSender emailSender = new NoOpEmailSender(); - - public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink) => - emailSender.SendEmailAsync(email, "Confirm your email", $"Please confirm your account by clicking here."); - - public Task SendPasswordResetLinkAsync(ApplicationUser user, string email, string resetLink) => - emailSender.SendEmailAsync(email, "Reset your password", $"Please reset your password by clicking here."); - - public Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode) => - emailSender.SendEmailAsync(email, "Reset your password", $"Please reset your password using the following code: {resetCode}"); - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/AccessDenied.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/AccessDenied.razor index db67a6f..13ac9ea 100644 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/AccessDenied.razor +++ b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/AccessDenied.razor @@ -1,5 +1,15 @@ @page "/Account/AccessDenied" +@layout IntegryControlPanel.Client.Layout.AuthLayout -Access denied +Accesso negato -You do not have access to this resource. + + Accesso negato + Non hai i permessi necessari per accedere a questa risorsa. + + + + + Torna alla home + + diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ConfirmEmail.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ConfirmEmail.razor deleted file mode 100644 index dcfe8f3..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ConfirmEmail.razor +++ /dev/null @@ -1,48 +0,0 @@ -@page "/Account/ConfirmEmail" - -@using System.Text -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IdentityRedirectManager RedirectManager - -Confirm email - -

Confirm email

- - -@code { - private string? statusMessage; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromQuery] - private string? UserId { get; set; } - - [SupplyParameterFromQuery] - private string? Code { get; set; } - - protected override async Task OnInitializedAsync() - { - if (UserId is null || Code is null) - { - RedirectManager.RedirectTo(""); - } - - var user = await UserManager.FindByIdAsync(UserId); - if (user is null) - { - HttpContext.Response.StatusCode = StatusCodes.Status404NotFound; - statusMessage = $"Error loading user with ID {UserId}"; - } - else - { - var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(Code)); - var result = await UserManager.ConfirmEmailAsync(user, code); - statusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; - } - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ConfirmEmailChange.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ConfirmEmailChange.razor deleted file mode 100644 index 3b76728..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ConfirmEmailChange.razor +++ /dev/null @@ -1,68 +0,0 @@ -@page "/Account/ConfirmEmailChange" - -@using System.Text -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityRedirectManager RedirectManager - -Confirm email change - -

Confirm email change

- - - -@code { - private string? message; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromQuery] - private string? UserId { get; set; } - - [SupplyParameterFromQuery] - private string? Email { get; set; } - - [SupplyParameterFromQuery] - private string? Code { get; set; } - - protected override async Task OnInitializedAsync() - { - if (UserId is null || Email is null || Code is null) - { - RedirectManager.RedirectToWithStatus( - "Account/Login", "Error: Invalid email change confirmation link.", HttpContext); - } - - var user = await UserManager.FindByIdAsync(UserId); - if (user is null) - { - message = "Unable to find user with Id '{userId}'"; - return; - } - - var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(Code)); - var result = await UserManager.ChangeEmailAsync(user, Email, code); - if (!result.Succeeded) - { - message = "Error changing email."; - return; - } - - // In our UI email and user name are one and the same, so when we update the email - // we need to update the user name. - var setUserNameResult = await UserManager.SetUserNameAsync(user, Email); - if (!setUserNameResult.Succeeded) - { - message = "Error changing user name."; - return; - } - - await SignInManager.RefreshSignInAsync(user); - message = "Thank you for confirming your email change."; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ExternalLogin.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ExternalLogin.razor deleted file mode 100644 index cdcba73..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ExternalLogin.razor +++ /dev/null @@ -1,205 +0,0 @@ -@page "/Account/ExternalLogin" - -@using System.ComponentModel.DataAnnotations -@using System.Security.Claims -@using System.Text -@using System.Text.Encodings.Web -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject SignInManager SignInManager -@inject UserManager UserManager -@inject IUserStore UserStore -@inject IEmailSender EmailSender -@inject NavigationManager NavigationManager -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Register - - -

Register

-

Associate your @ProviderDisplayName account.

- - -
- You've successfully authenticated with @ProviderDisplayName. - Please enter an email address for this site below and click the Register button to finish - logging in. -
- -
-
- - - -
- - - -
- -
-
-
- -@code { - public const string LoginCallbackAction = "LoginCallback"; - - private string? message; - private ExternalLoginInfo? externalLoginInfo; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - [SupplyParameterFromQuery] - private string? RemoteError { get; set; } - - [SupplyParameterFromQuery] - private string? ReturnUrl { get; set; } - - [SupplyParameterFromQuery] - private string? Action { get; set; } - - private string? ProviderDisplayName => externalLoginInfo?.ProviderDisplayName; - - protected override async Task OnInitializedAsync() - { - if (RemoteError is not null) - { - RedirectManager.RedirectToWithStatus("Account/Login", $"Error from external provider: {RemoteError}", HttpContext); - } - - var info = await SignInManager.GetExternalLoginInfoAsync(); - if (info is null) - { - RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext); - } - - externalLoginInfo = info; - - if (HttpMethods.IsGet(HttpContext.Request.Method)) - { - if (Action == LoginCallbackAction) - { - await OnLoginCallbackAsync(); - return; - } - - // We should only reach this page via the login callback, so redirect back to - // the login page if we get here some other way. - RedirectManager.RedirectTo("Account/Login"); - } - } - - private async Task OnLoginCallbackAsync() - { - if (externalLoginInfo is null) - { - RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext); - } - - // Sign in the user with this external login provider if the user already has a login. - var result = await SignInManager.ExternalLoginSignInAsync( - externalLoginInfo!.LoginProvider, - externalLoginInfo!.ProviderKey, - isPersistent: false, - bypassTwoFactor: true); - - if (result.Succeeded) - { - Logger.LogInformation( - "{Name} logged in with {LoginProvider} provider.", - externalLoginInfo.Principal.Identity?.Name, - externalLoginInfo.LoginProvider); - RedirectManager.RedirectTo(ReturnUrl); - } - else if (result.IsLockedOut) - { - RedirectManager.RedirectTo("Account/Lockout"); - } - - // If the user does not have an account, then ask the user to create an account. - if (externalLoginInfo.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) - { - Input.Email = externalLoginInfo.Principal.FindFirstValue(ClaimTypes.Email) ?? ""; - } - } - - private async Task OnValidSubmitAsync() - { - if (externalLoginInfo is null) - { - RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information during confirmation.", HttpContext); - } - - var emailStore = GetEmailStore(); - var user = CreateUser(); - - await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None); - await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None); - - var result = await UserManager.CreateAsync(user); - if (result.Succeeded) - { - result = await UserManager.AddLoginAsync(user, externalLoginInfo); - if (result.Succeeded) - { - Logger.LogInformation("User created an account using {Name} provider.", externalLoginInfo.LoginProvider); - - var userId = await UserManager.GetUserIdAsync(user); - var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - - var callbackUrl = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri, - new Dictionary { ["userId"] = userId, ["code"] = code }); - await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl)); - - // If account confirmation is required, we need to show the link if we don't have a real email sender - if (UserManager.Options.SignIn.RequireConfirmedAccount) - { - RedirectManager.RedirectTo("Account/RegisterConfirmation", new() { ["email"] = Input.Email }); - } - - await SignInManager.SignInAsync(user, isPersistent: false, externalLoginInfo.LoginProvider); - RedirectManager.RedirectTo(ReturnUrl); - } - } - - message = $"Error: {string.Join(",", result.Errors.Select(error => error.Description))}"; - } - - private static ApplicationUser CreateUser() - { - try - { - return Activator.CreateInstance(); - } - catch - { - throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " + - $"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor"); - } - } - - private IUserEmailStore GetEmailStore() - { - if (!UserManager.SupportsUserEmail) - { - throw new NotSupportedException("The default UI requires a user store with email support."); - } - return (IUserEmailStore)UserStore; - } - - private sealed class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ForgotPassword.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ForgotPassword.razor deleted file mode 100644 index 4c5fe48..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ForgotPassword.razor +++ /dev/null @@ -1,68 +0,0 @@ -@page "/Account/ForgotPassword" - -@using System.ComponentModel.DataAnnotations -@using System.Text -@using System.Text.Encodings.Web -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IEmailSender EmailSender -@inject NavigationManager NavigationManager -@inject IdentityRedirectManager RedirectManager - -Forgot your password? - -Forgot your password? -Enter your email. - - - - - - - - - - - Reset password - - - - -@code { - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - private async Task OnValidSubmitAsync() - { - var user = await UserManager.FindByEmailAsync(Input.Email); - if (user is null || !(await UserManager.IsEmailConfirmedAsync(user))) - { - // Don't reveal that the user does not exist or is not confirmed - RedirectManager.RedirectTo("Account/ForgotPasswordConfirmation"); - } - - // For more information on how to enable account confirmation and password reset please - // visit https://go.microsoft.com/fwlink/?LinkID=532713 - var code = await UserManager.GeneratePasswordResetTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ResetPassword").AbsoluteUri, - new Dictionary { ["code"] = code }); - - await EmailSender.SendPasswordResetLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl)); - - RedirectManager.RedirectTo("Account/ForgotPasswordConfirmation"); - } - - private sealed class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ForgotPasswordConfirmation.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ForgotPasswordConfirmation.razor deleted file mode 100644 index 31f70ce..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ForgotPasswordConfirmation.razor +++ /dev/null @@ -1,7 +0,0 @@ -@page "/Account/ForgotPasswordConfirmation" - -Forgot password confirmation - -Forgot password confirmation - -Please check your email to reset your password. diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/InvalidPasswordReset.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/InvalidPasswordReset.razor deleted file mode 100644 index 561b651..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/InvalidPasswordReset.razor +++ /dev/null @@ -1,8 +0,0 @@ -@page "/Account/InvalidPasswordReset" - -Invalid password reset - -

Invalid password reset

-

- The password reset link is invalid. -

diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Lockout.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Lockout.razor deleted file mode 100644 index 017e31d..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Lockout.razor +++ /dev/null @@ -1,8 +0,0 @@ -@page "/Account/Lockout" - -Locked out - -
-

Locked out

- -
diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Login.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Login.razor index 30def34..54599f2 100644 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Login.razor +++ b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Login.razor @@ -1,4 +1,5 @@ @page "/Account/Login" +@layout IntegryControlPanel.Client.Layout.AuthLayout @using System.ComponentModel.DataAnnotations @using Microsoft.AspNetCore.Authentication @@ -10,64 +11,77 @@ @inject NavigationManager NavigationManager @inject IdentityRedirectManager RedirectManager -Log in +@* Log in *@ -Log in + - - - - - + - Use a local account to log in. + - - - - - - - - - Remember me - - - Log in - - - + Accedi al tuo account - - - Forgot your password?
- { ["ReturnUrl"] = ReturnUrl }))">Register as a new user
- Resend email confirmation -
-
-
- - Use another service to log in. + - + + + + + + + + + + + + @* + Ricordami + *@ + + + Accedi + + + + + + + @* *@ + + @* + + Non hai ancora un account? + { ["ReturnUrl"] = ReturnUrl }))" + Color="Color.Primary"> + Registrati qui + + + *@ + + @* Commented out links for now + + + Forgot your password?
+ Resend email confirmation
+*@ +
@code { private string? errorMessage; - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; + [CascadingParameter] private HttpContext HttpContext { get; set; } = default!; - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); + [SupplyParameterFromForm] private InputModel Input { get; set; } = new(); - [SupplyParameterFromQuery] - private string? ReturnUrl { get; set; } + [SupplyParameterFromQuery] private string? ReturnUrl { get; set; } protected override async Task OnInitializedAsync() { @@ -115,7 +129,7 @@ [DataType(DataType.Password)] public string Password { get; set; } = ""; - [Display(Name = "Remember me?")] - public bool RememberMe { get; set; } + [Display(Name = "Remember me?")] public bool RememberMe { get; set; } } -} + +} \ No newline at end of file diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/LoginWith2fa.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/LoginWith2fa.razor deleted file mode 100644 index ad9ee2d..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/LoginWith2fa.razor +++ /dev/null @@ -1,101 +0,0 @@ -@page "/Account/LoginWith2fa" - -@using System.ComponentModel.DataAnnotations -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject SignInManager SignInManager -@inject UserManager UserManager -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Two-factor authentication - -

Two-factor authentication

- - -

Your login is protected with an authenticator app. Enter your authenticator code below.

-
-
- - - - - -
- - - -
-
- -
-
- -
-
-
-
-

- Don't have access to your authenticator device? You can - log in with a recovery code. -

- -@code { - private string? message; - private ApplicationUser user = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - [SupplyParameterFromQuery] - private string? ReturnUrl { get; set; } - - [SupplyParameterFromQuery] - private bool RememberMe { get; set; } - - protected override async Task OnInitializedAsync() - { - // Ensure the user has gone through the username & password screen first - user = await SignInManager.GetTwoFactorAuthenticationUserAsync() ?? - throw new InvalidOperationException("Unable to load two-factor authentication user."); - } - - private async Task OnValidSubmitAsync() - { - var authenticatorCode = Input.TwoFactorCode!.Replace(" ", string.Empty).Replace("-", string.Empty); - var result = await SignInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, RememberMe, Input.RememberMachine); - var userId = await UserManager.GetUserIdAsync(user); - - if (result.Succeeded) - { - Logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", userId); - RedirectManager.RedirectTo(ReturnUrl); - } - else if (result.IsLockedOut) - { - Logger.LogWarning("User with ID '{UserId}' account locked out.", userId); - RedirectManager.RedirectTo("Account/Lockout"); - } - else - { - Logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", userId); - message = "Error: Invalid authenticator code."; - } - } - - private sealed class InputModel - { - [Required] - [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Text)] - [Display(Name = "Authenticator code")] - public string? TwoFactorCode { get; set; } - - [Display(Name = "Remember this machine")] - public bool RememberMachine { get; set; } - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/LoginWithRecoveryCode.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/LoginWithRecoveryCode.razor deleted file mode 100644 index 51fff5f..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/LoginWithRecoveryCode.razor +++ /dev/null @@ -1,85 +0,0 @@ -@page "/Account/LoginWithRecoveryCode" - -@using System.ComponentModel.DataAnnotations -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject SignInManager SignInManager -@inject UserManager UserManager -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Recovery code verification - -

Recovery code verification

- - -

- You have requested to log in with a recovery code. This login will not be remembered until you provide - an authenticator app code at log in or disable 2FA and log in again. -

-
-
- - - -
- - - -
- -
-
-
- -@code { - private string? message; - private ApplicationUser user = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - [SupplyParameterFromQuery] - private string? ReturnUrl { get; set; } - - protected override async Task OnInitializedAsync() - { - // Ensure the user has gone through the username & password screen first - user = await SignInManager.GetTwoFactorAuthenticationUserAsync() ?? - throw new InvalidOperationException("Unable to load two-factor authentication user."); - } - - private async Task OnValidSubmitAsync() - { - var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty); - - var result = await SignInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); - - var userId = await UserManager.GetUserIdAsync(user); - - if (result.Succeeded) - { - Logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", userId); - RedirectManager.RedirectTo(ReturnUrl); - } - else if (result.IsLockedOut) - { - Logger.LogWarning("User account locked out."); - RedirectManager.RedirectTo("Account/Lockout"); - } - else - { - Logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", userId); - message = "Error: Invalid recovery code entered."; - } - } - - private sealed class InputModel - { - [Required] - [DataType(DataType.Text)] - [Display(Name = "Recovery Code")] - public string RecoveryCode { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ChangePassword.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ChangePassword.razor deleted file mode 100644 index 05e2f95..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ChangePassword.razor +++ /dev/null @@ -1,98 +0,0 @@ -@page "/Account/Manage/ChangePassword" - -@using System.ComponentModel.DataAnnotations -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Change password - -Change password - - - - - - - - - - - - - - - - - - Update password - - - - -@code { - private string? message; - private ApplicationUser user = default!; - private bool hasPassword; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - hasPassword = await UserManager.HasPasswordAsync(user); - if (!hasPassword) - { - RedirectManager.RedirectTo("Account/Manage/SetPassword"); - } - } - - private async Task OnValidSubmitAsync() - { - var changePasswordResult = await UserManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword); - if (!changePasswordResult.Succeeded) - { - message = $"Error: {string.Join(",", changePasswordResult.Errors.Select(error => error.Description))}"; - return; - } - - await SignInManager.RefreshSignInAsync(user); - Logger.LogInformation("User changed their password successfully."); - - RedirectManager.RedirectToCurrentPageWithStatus("Your password has been changed", HttpContext); - } - - private sealed class InputModel - { - [Required] - [DataType(DataType.Password)] - [Display(Name = "Current password")] - public string OldPassword { get; set; } = ""; - - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string NewPassword { get; set; } = ""; - - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/DeletePersonalData.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/DeletePersonalData.razor deleted file mode 100644 index b506639..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/DeletePersonalData.razor +++ /dev/null @@ -1,86 +0,0 @@ -@page "/Account/Manage/DeletePersonalData" - -@using System.ComponentModel.DataAnnotations -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Delete Personal Data - -Delete personal data - - - - - Deleting this data will permanently remove your account, and this cannot be recovered. - - - - - - - @if (requirePassword) - { - - - - } - - Delete data and close my account - - - - -@code { - private string? message; - private ApplicationUser user = default!; - private bool requirePassword; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - protected override async Task OnInitializedAsync() - { - Input ??= new(); - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - requirePassword = await UserManager.HasPasswordAsync(user); - } - - private async Task OnValidSubmitAsync() - { - if (requirePassword && !await UserManager.CheckPasswordAsync(user, Input.Password)) - { - message = "Error: Incorrect password."; - return; - } - - var result = await UserManager.DeleteAsync(user); - if (!result.Succeeded) - { - throw new InvalidOperationException("Unexpected error occurred deleting user."); - } - - await SignInManager.SignOutAsync(); - - var userId = await UserManager.GetUserIdAsync(user); - Logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId); - - RedirectManager.RedirectToCurrentPage(); - } - - private sealed class InputModel - { - [DataType(DataType.Password)] - public string Password { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/Disable2fa.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/Disable2fa.razor deleted file mode 100644 index d515f06..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/Disable2fa.razor +++ /dev/null @@ -1,64 +0,0 @@ -@page "/Account/Manage/Disable2fa" - -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Disable two-factor authentication (2FA) - - -

Disable two-factor authentication (2FA)

- - - -
-
- - - -
- -@code { - private ApplicationUser user = default!; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - - if (HttpMethods.IsGet(HttpContext.Request.Method) && !await UserManager.GetTwoFactorEnabledAsync(user)) - { - throw new InvalidOperationException("Cannot disable 2FA for user as it's not currently enabled."); - } - } - - private async Task OnSubmitAsync() - { - var disable2faResult = await UserManager.SetTwoFactorEnabledAsync(user, false); - if (!disable2faResult.Succeeded) - { - throw new InvalidOperationException("Unexpected error occurred disabling 2FA."); - } - - var userId = await UserManager.GetUserIdAsync(user); - Logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", userId); - RedirectManager.RedirectToWithStatus( - "Account/Manage/TwoFactorAuthentication", - "2fa has been disabled. You can reenable 2fa when you setup an authenticator app", - HttpContext); - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/Email.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/Email.razor deleted file mode 100644 index 23823dd..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/Email.razor +++ /dev/null @@ -1,122 +0,0 @@ -@page "/Account/Manage/Email" - -@using System.ComponentModel.DataAnnotations -@using System.Text -@using System.Text.Encodings.Web -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IEmailSender EmailSender -@inject IdentityUserAccessor UserAccessor -@inject NavigationManager NavigationManager - -Manage email - -Manage email - - - -
- - - - - - - - @if (isEmailConfirmed) - { - - - - } - else - { - - - - - Send verification email - - } - - - - - - - Change email - - - - -@code { - private string? message; - private ApplicationUser user = default!; - private string? email; - private bool isEmailConfirmed; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm(FormName = "change-email")] - private InputModel Input { get; set; } = new(); - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - email = await UserManager.GetEmailAsync(user); - isEmailConfirmed = await UserManager.IsEmailConfirmedAsync(user); - - Input.NewEmail ??= email; - } - - private async Task OnValidSubmitAsync() - { - if (Input.NewEmail is null || Input.NewEmail == email) - { - message = "Your email is unchanged."; - return; - } - - var userId = await UserManager.GetUserIdAsync(user); - var code = await UserManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ConfirmEmailChange").AbsoluteUri, - new Dictionary { ["userId"] = userId, ["email"] = Input.NewEmail, ["code"] = code }); - - await EmailSender.SendConfirmationLinkAsync(user, Input.NewEmail, HtmlEncoder.Default.Encode(callbackUrl)); - - message = "Confirmation link to change email sent. Please check your email."; - } - - private async Task OnSendEmailVerificationAsync() - { - if (email is null) - { - return; - } - - var userId = await UserManager.GetUserIdAsync(user); - var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri, - new Dictionary { ["userId"] = userId, ["code"] = code }); - - await EmailSender.SendConfirmationLinkAsync(user, email, HtmlEncoder.Default.Encode(callbackUrl)); - - message = "Verification email sent. Please check your email."; - } - - private sealed class InputModel - { - [Required] - [EmailAddress] - [Display(Name = "New email")] - public string? NewEmail { get; set; } - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/EnableAuthenticator.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/EnableAuthenticator.razor deleted file mode 100644 index 2a7c9d0..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/EnableAuthenticator.razor +++ /dev/null @@ -1,178 +0,0 @@ -@page "/Account/Manage/EnableAuthenticator" - -@using System.ComponentModel.DataAnnotations -@using System.Globalization -@using System.Text -@using System.Text.Encodings.Web -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IdentityUserAccessor UserAccessor -@inject UrlEncoder UrlEncoder -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Configure authenticator app - -@if (recoveryCodes is not null) -{ - -} -else -{ - Configure authenticator app - - - - To use an authenticator app go through the following steps: - -
    -
  1. - - Download a two-factor authenticator app like Microsoft Authenticator for - Android and - iOS or - Google Authenticator for - Android and - iOS. - -
  2. -
  3. - - Scan the QR Code or enter this key into your two factor authenticator app. Spaces and casing do not matter: - - - @sharedKey - - - Learn how to enable QR code generation. - - -
    -
  4. -
  5. - - Once you have scanned the QR code or input the key above, your two factor authentication app will provide you - with a unique code. Enter the code in the confirmation box below. - - - - - - - - - - Verify - - - -
  6. -
-} - -@code { - private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6"; - - private string? message; - private ApplicationUser user = default!; - private string? sharedKey; - private string? authenticatorUri; - private IEnumerable? recoveryCodes; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - - await LoadSharedKeyAndQrCodeUriAsync(user); - } - - private async Task OnValidSubmitAsync() - { - // Strip spaces and hyphens - var verificationCode = Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty); - - var is2faTokenValid = await UserManager.VerifyTwoFactorTokenAsync( - user, UserManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); - - if (!is2faTokenValid) - { - message = "Error: Verification code is invalid."; - return; - } - - await UserManager.SetTwoFactorEnabledAsync(user, true); - var userId = await UserManager.GetUserIdAsync(user); - Logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId); - - message = "Your authenticator app has been verified."; - - if (await UserManager.CountRecoveryCodesAsync(user) == 0) - { - recoveryCodes = await UserManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); - } - else - { - RedirectManager.RedirectToWithStatus("Account/Manage/TwoFactorAuthentication", message, HttpContext); - } - } - - private async ValueTask LoadSharedKeyAndQrCodeUriAsync(ApplicationUser user) - { - // Load the authenticator key & QR code URI to display on the form - var unformattedKey = await UserManager.GetAuthenticatorKeyAsync(user); - if (string.IsNullOrEmpty(unformattedKey)) - { - await UserManager.ResetAuthenticatorKeyAsync(user); - unformattedKey = await UserManager.GetAuthenticatorKeyAsync(user); - } - - sharedKey = FormatKey(unformattedKey!); - - var email = await UserManager.GetEmailAsync(user); - authenticatorUri = GenerateQrCodeUri(email!, unformattedKey!); - } - - private string FormatKey(string unformattedKey) - { - var result = new StringBuilder(); - int currentPosition = 0; - while (currentPosition + 4 < unformattedKey.Length) - { - result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' '); - currentPosition += 4; - } - if (currentPosition < unformattedKey.Length) - { - result.Append(unformattedKey.AsSpan(currentPosition)); - } - - return result.ToString().ToLowerInvariant(); - } - - private string GenerateQrCodeUri(string email, string unformattedKey) - { - return string.Format( - CultureInfo.InvariantCulture, - AuthenticatorUriFormat, - UrlEncoder.Encode("Microsoft.AspNetCore.Identity.UI"), - UrlEncoder.Encode(email), - unformattedKey); - } - - private sealed class InputModel - { - [Required] - [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Text)] - [Display(Name = "Verification Code")] - public string Code { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ExternalLogins.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ExternalLogins.razor deleted file mode 100644 index eb8cc63..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ExternalLogins.razor +++ /dev/null @@ -1,140 +0,0 @@ -@page "/Account/Manage/ExternalLogins" - -@using Microsoft.AspNetCore.Authentication -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityUserAccessor UserAccessor -@inject IUserStore UserStore -@inject IdentityRedirectManager RedirectManager - -Manage your external logins - - -@if (currentLogins?.Count > 0) -{ -

Registered Logins

- - - @foreach (var login in currentLogins) - { - - - - - } - -
@login.ProviderDisplayName - @if (showRemoveButton) - { -
- -
- - - -
- - } - else - { - @:   - } -
-} -@if (otherLogins?.Count > 0) -{ -

Add another service to log in.

- -
- -
-

- @foreach (var provider in otherLogins) - { - - } -

-
- -} - -@code { - public const string LinkLoginCallbackAction = "LinkLoginCallback"; - - private ApplicationUser user = default!; - private IList? currentLogins; - private IList? otherLogins; - private bool showRemoveButton; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm] - private string? LoginProvider { get; set; } - - [SupplyParameterFromForm] - private string? ProviderKey { get; set; } - - [SupplyParameterFromQuery] - private string? Action { get; set; } - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - currentLogins = await UserManager.GetLoginsAsync(user); - otherLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()) - .Where(auth => currentLogins.All(ul => auth.Name != ul.LoginProvider)) - .ToList(); - - string? passwordHash = null; - if (UserStore is IUserPasswordStore userPasswordStore) - { - passwordHash = await userPasswordStore.GetPasswordHashAsync(user, HttpContext.RequestAborted); - } - - showRemoveButton = passwordHash is not null || currentLogins.Count > 1; - - if (HttpMethods.IsGet(HttpContext.Request.Method) && Action == LinkLoginCallbackAction) - { - await OnGetLinkLoginCallbackAsync(); - } - } - - private async Task OnSubmitAsync() - { - var result = await UserManager.RemoveLoginAsync(user, LoginProvider!, ProviderKey!); - if (!result.Succeeded) - { - RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not removed.", HttpContext); - } - - await SignInManager.RefreshSignInAsync(user); - RedirectManager.RedirectToCurrentPageWithStatus("The external login was removed.", HttpContext); - } - - private async Task OnGetLinkLoginCallbackAsync() - { - var userId = await UserManager.GetUserIdAsync(user); - var info = await SignInManager.GetExternalLoginInfoAsync(userId); - if (info is null) - { - RedirectManager.RedirectToCurrentPageWithStatus("Error: Could not load external login info.", HttpContext); - } - - var result = await UserManager.AddLoginAsync(user, info); - if (!result.Succeeded) - { - RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not added. External logins can only be associated with one account.", HttpContext); - } - - // Clear the existing external cookie to ensure a clean login process - await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - - RedirectManager.RedirectToCurrentPageWithStatus("The external login was added.", HttpContext); - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/GenerateRecoveryCodes.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/GenerateRecoveryCodes.razor deleted file mode 100644 index 89ba031..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/GenerateRecoveryCodes.razor +++ /dev/null @@ -1,68 +0,0 @@ -@page "/Account/Manage/GenerateRecoveryCodes" - -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Generate two-factor authentication (2FA) recovery codes - -@if (recoveryCodes is not null) -{ - -} -else -{ -

Generate two-factor authentication (2FA) recovery codes

- -
-
- - - -
-} - -@code { - private string? message; - private ApplicationUser user = default!; - private IEnumerable? recoveryCodes; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - - var isTwoFactorEnabled = await UserManager.GetTwoFactorEnabledAsync(user); - if (!isTwoFactorEnabled) - { - throw new InvalidOperationException("Cannot generate recovery codes for user because they do not have 2FA enabled."); - } - } - - private async Task OnSubmitAsync() - { - var userId = await UserManager.GetUserIdAsync(user); - recoveryCodes = await UserManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); - message = "You have generated new recovery codes."; - - Logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ResetAuthenticator.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ResetAuthenticator.razor deleted file mode 100644 index bc8eb7e..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/ResetAuthenticator.razor +++ /dev/null @@ -1,52 +0,0 @@ -@page "/Account/Manage/ResetAuthenticator" - -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager -@inject ILogger Logger - -Reset authenticator key - -Reset authenticator key - - - - - If you reset your authenticator key your authenticator app will not work until you reconfigure it. - - - - This process disables 2FA until you verify your authenticator app. - If you do not complete your authenticator app configuration you may lose access to your account. - - -
- - - Reset authenticator key - - -@code { - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - private async Task OnSubmitAsync() - { - var user = await UserAccessor.GetRequiredUserAsync(HttpContext); - await UserManager.SetTwoFactorEnabledAsync(user, false); - await UserManager.ResetAuthenticatorKeyAsync(user); - var userId = await UserManager.GetUserIdAsync(user); - Logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", userId); - - await SignInManager.RefreshSignInAsync(user); - - RedirectManager.RedirectToWithStatus( - "Account/Manage/EnableAuthenticator", - "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key.", - HttpContext); - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/SetPassword.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/SetPassword.razor deleted file mode 100644 index 5453106..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/SetPassword.razor +++ /dev/null @@ -1,87 +0,0 @@ -@page "/Account/Manage/SetPassword" - -@using System.ComponentModel.DataAnnotations -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager - -Set password - -

Set your password

- -

- You do not have a local username/password for this site. Add a local - account so you can log in without an external login. -

-
-
- - - -
- - - -
-
- - - -
- -
-
-
- -@code { - private string? message; - private ApplicationUser user = default!; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - protected override async Task OnInitializedAsync() - { - user = await UserAccessor.GetRequiredUserAsync(HttpContext); - - var hasPassword = await UserManager.HasPasswordAsync(user); - if (hasPassword) - { - RedirectManager.RedirectTo("Account/Manage/ChangePassword"); - } - } - - private async Task OnValidSubmitAsync() - { - var addPasswordResult = await UserManager.AddPasswordAsync(user, Input.NewPassword!); - if (!addPasswordResult.Succeeded) - { - message = $"Error: {string.Join(",", addPasswordResult.Errors.Select(error => error.Description))}"; - return; - } - - await SignInManager.RefreshSignInAsync(user); - RedirectManager.RedirectToCurrentPageWithStatus("Your password has been set.", HttpContext); - } - - private sealed class InputModel - { - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string? NewPassword { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string? ConfirmPassword { get; set; } - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/TwoFactorAuthentication.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/TwoFactorAuthentication.razor deleted file mode 100644 index 8351ca3..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Manage/TwoFactorAuthentication.razor +++ /dev/null @@ -1,110 +0,0 @@ -@page "/Account/Manage/TwoFactorAuthentication" - -@using Microsoft.AspNetCore.Http.Features -@using Microsoft.AspNetCore.Identity -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject SignInManager SignInManager -@inject IdentityUserAccessor UserAccessor -@inject IdentityRedirectManager RedirectManager - -Two-factor authentication (2FA) - -Two-factor authentication (2FA) - - - -@if (canTrack) -{ - if (is2faEnabled) - { - if (recoveryCodesLeft == 0) - { - You have no recovery codes left. - - - You must generate a new set of recovery codes - before you can log in with a recovery code. - - } - else if (recoveryCodesLeft == 1) - { - You have 1 recovery code left. - - - You can generate a new set of recovery codes. - - } - else if (recoveryCodesLeft <= 3) - { - You have @recoveryCodesLeft recovery codes left. - - - You should generate a new set of recovery codes. - - } - - if (isMachineRemembered) - { -
- - - Forget this browser - - } - - Disable 2FA
- Reset recovery codes - } - - Authenticator app - - @if (!hasAuthenticator) - { - Add authenticator app
- } - else - { - Set up authenticator app
- Reset authenticator app - } -} -else -{ - Privacy and cookie policy have not been accepted. - - - You must accept the policy before you can enable two factor authentication. - -} - -@code { - private bool canTrack; - private bool hasAuthenticator; - private int recoveryCodesLeft; - private bool is2faEnabled; - private bool isMachineRemembered; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - protected override async Task OnInitializedAsync() - { - var user = await UserAccessor.GetRequiredUserAsync(HttpContext); - canTrack = HttpContext.Features.Get()?.CanTrack ?? true; - hasAuthenticator = await UserManager.GetAuthenticatorKeyAsync(user) is not null; - is2faEnabled = await UserManager.GetTwoFactorEnabledAsync(user); - isMachineRemembered = await SignInManager.IsTwoFactorClientRememberedAsync(user); - recoveryCodesLeft = await UserManager.CountRecoveryCodesAsync(user); - } - - private async Task OnSubmitForgetBrowserAsync() - { - await SignInManager.ForgetTwoFactorClientAsync(); - - RedirectManager.RedirectToCurrentPageWithStatus( - "The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code.", - HttpContext); - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Register.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Register.razor deleted file mode 100644 index 4e6a001..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/Register.razor +++ /dev/null @@ -1,146 +0,0 @@ -@page "/Account/Register" - -@using System.ComponentModel.DataAnnotations -@using System.Text -@using System.Text.Encodings.Web -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IUserStore UserStore -@inject SignInManager SignInManager -@inject IEmailSender EmailSender -@inject ILogger Logger -@inject NavigationManager NavigationManager -@inject IdentityRedirectManager RedirectManager - -Register - -Register - - - - - - - - Create a new account. - - - - - - - - - - - - - Register - - - - - - Use another service to register. - - - - -@code { - private IEnumerable? identityErrors; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - [SupplyParameterFromQuery] - private string? ReturnUrl { get; set; } - - private string? Message => identityErrors is null ? null : $"Error: {string.Join(", ", identityErrors.Select(error => error.Description))}"; - - public async Task RegisterUser(EditContext editContext) - { - var user = CreateUser(); - - await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None); - var emailStore = GetEmailStore(); - await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None); - var result = await UserManager.CreateAsync(user, Input.Password); - - if (!result.Succeeded) - { - identityErrors = result.Errors; - return; - } - - Logger.LogInformation("User created a new account with password."); - - var userId = await UserManager.GetUserIdAsync(user); - var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri, - new Dictionary { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl }); - - await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl)); - - if (UserManager.Options.SignIn.RequireConfirmedAccount) - { - RedirectManager.RedirectTo( - "Account/RegisterConfirmation", - new() { ["email"] = Input.Email, ["returnUrl"] = ReturnUrl }); - } - - await SignInManager.SignInAsync(user, isPersistent: false); - RedirectManager.RedirectTo(ReturnUrl); - } - - private static ApplicationUser CreateUser() - { - try - { - return Activator.CreateInstance(); - } - catch - { - throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " + - $"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor."); - } - } - - private IUserEmailStore GetEmailStore() - { - if (!UserManager.SupportsUserEmail) - { - throw new NotSupportedException("The default UI requires a user store with email support."); - } - return (IUserEmailStore)UserStore; - } - - private sealed class InputModel - { - [Required] - [EmailAddress] - [Display(Name = "Email")] - public string Email { get; set; } = ""; - - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Password")] - public string Password { get; set; } = ""; - - [DataType(DataType.Password)] - [Display(Name = "Confirm password")] - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/RegisterConfirmation.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/RegisterConfirmation.razor deleted file mode 100644 index dde3906..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/RegisterConfirmation.razor +++ /dev/null @@ -1,68 +0,0 @@ -@page "/Account/RegisterConfirmation" - -@using System.Text -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IEmailSender EmailSender -@inject NavigationManager NavigationManager -@inject IdentityRedirectManager RedirectManager - -Register confirmation - -

Register confirmation

- - - -@if (emailConfirmationLink is not null) -{ -

- This app does not currently have a real email sender registered, see these docs for how to configure a real email sender. - Normally this would be emailed: Click here to confirm your account -

-} -else -{ -

Please check your email to confirm your account.

-} - -@code { - private string? emailConfirmationLink; - private string? statusMessage; - - [CascadingParameter] - private HttpContext HttpContext { get; set; } = default!; - - [SupplyParameterFromQuery] - private string? Email { get; set; } - - [SupplyParameterFromQuery] - private string? ReturnUrl { get; set; } - - protected override async Task OnInitializedAsync() - { - if (Email is null) - { - RedirectManager.RedirectTo(""); - } - - var user = await UserManager.FindByEmailAsync(Email); - if (user is null) - { - HttpContext.Response.StatusCode = StatusCodes.Status404NotFound; - statusMessage = "Error finding user for unspecified email"; - } - else if (EmailSender is IdentityNoOpEmailSender) - { - // Once you add a real email sender, you should remove this code that lets you confirm the account - var userId = await UserManager.GetUserIdAsync(user); - var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - emailConfirmationLink = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri, - new Dictionary { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl }); - } - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResendEmailConfirmation.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResendEmailConfirmation.razor deleted file mode 100644 index cd48367..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResendEmailConfirmation.razor +++ /dev/null @@ -1,70 +0,0 @@ -@page "/Account/ResendEmailConfirmation" - -@using System.ComponentModel.DataAnnotations -@using System.Text -@using System.Text.Encodings.Web -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject UserManager UserManager -@inject IEmailSender EmailSender -@inject NavigationManager NavigationManager -@inject IdentityRedirectManager RedirectManager - -Resend email confirmation - -Resend email confirmation - -Enter your email. - - - - - - - - - - - - Resend - - - - -@code { - private string? message; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - private async Task OnValidSubmitAsync() - { - var user = await UserManager.FindByEmailAsync(Input.Email!); - if (user is null) - { - message = "Verification email sent. Please check your email."; - return; - } - - var userId = await UserManager.GetUserIdAsync(user); - var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = NavigationManager.GetUriWithQueryParameters( - NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri, - new Dictionary { ["userId"] = userId, ["code"] = code }); - await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl)); - - message = "Verification email sent. Please check your email."; - } - - private sealed class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResetPassword.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResetPassword.razor deleted file mode 100644 index cf353b1..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResetPassword.razor +++ /dev/null @@ -1,103 +0,0 @@ -@page "/Account/ResetPassword" - -@using System.ComponentModel.DataAnnotations -@using System.Text -@using Microsoft.AspNetCore.Identity -@using Microsoft.AspNetCore.WebUtilities -@using IntegryControlPanel.Data - -@inject IdentityRedirectManager RedirectManager -@inject UserManager UserManager - -Reset password - -

Reset password

-

Reset your password.

- -
-
- - - - - - -
- - - -
-
- - - -
-
- - - -
- -
-
-
- -@code { - private IEnumerable? identityErrors; - - [SupplyParameterFromForm] - private InputModel Input { get; set; } = new(); - - [SupplyParameterFromQuery] - private string? Code { get; set; } - - private string? Message => identityErrors is null ? null : $"Error: {string.Join(", ", identityErrors.Select(error => error.Description))}"; - - protected override void OnInitialized() - { - if (Code is null) - { - RedirectManager.RedirectTo("Account/InvalidPasswordReset"); - } - - Input.Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(Code)); - } - - private async Task OnValidSubmitAsync() - { - var user = await UserManager.FindByEmailAsync(Input.Email); - if (user is null) - { - // Don't reveal that the user does not exist - RedirectManager.RedirectTo("Account/ResetPasswordConfirmation"); - } - - var result = await UserManager.ResetPasswordAsync(user, Input.Code, Input.Password); - if (result.Succeeded) - { - RedirectManager.RedirectTo("Account/ResetPasswordConfirmation"); - } - - identityErrors = result.Errors; - } - - private sealed class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } = ""; - - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - public string Password { get; set; } = ""; - - [DataType(DataType.Password)] - [Display(Name = "Confirm password")] - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } = ""; - - [Required] - public string Code { get; set; } = ""; - } -} diff --git a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResetPasswordConfirmation.razor b/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResetPasswordConfirmation.razor deleted file mode 100644 index 2554ddb..0000000 --- a/IntegryControlPanel/IntegryControlPanel/Components/Account/Pages/ResetPasswordConfirmation.razor +++ /dev/null @@ -1,7 +0,0 @@ -@page "/Account/ResetPasswordConfirmation" -Reset password confirmation - -

Reset password confirmation

-

- Your password has been reset. Please click here to log in. -

diff --git a/IntegryControlPanel/IntegryControlPanel/Components/App.razor b/IntegryControlPanel/IntegryControlPanel/Components/App.razor index a4ec36a..571bc27 100644 --- a/IntegryControlPanel/IntegryControlPanel/Components/App.razor +++ b/IntegryControlPanel/IntegryControlPanel/Components/App.razor @@ -5,7 +5,7 @@ - + diff --git a/IntegryControlPanel/IntegryControlPanel/Program.cs b/IntegryControlPanel/IntegryControlPanel/Program.cs index f6eb3f2..c6673a3 100644 --- a/IntegryControlPanel/IntegryControlPanel/Program.cs +++ b/IntegryControlPanel/IntegryControlPanel/Program.cs @@ -71,8 +71,6 @@ builder.Services.AddScoped(); // Registra il servizio per gestire il database esistente builder.Services.AddScoped(); -builder.Services.AddSingleton, IdentityNoOpEmailSender>(); - var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/IntegryControlPanel/IntegryControlPanel/wwwroot/images/background.png b/IntegryControlPanel/IntegryControlPanel/wwwroot/images/background.png new file mode 100644 index 0000000..209a2c8 Binary files /dev/null and b/IntegryControlPanel/IntegryControlPanel/wwwroot/images/background.png differ