-
-
-
-
+
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
-
-
-
-@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)
-
-
-
- This action only disables 2FA.
-
-
- Disabling 2FA does not change the keys used in authenticator apps. If you wish to change the key
- used in an authenticator app you should reset your authenticator keys.
-
-
- Download a two-factor authenticator app like Microsoft Authenticator for
- Android and
- iOS or
- Google Authenticator for
- Android and
- iOS.
-
-
-
-
- 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.
-
-
-
-
-
-
- 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
-
-
-
-
- If you lose your device and don't have the recovery codes you will lose access to your account.
-
-
- Generating new recovery codes does not change the keys used in authenticator apps. If you wish to change the key
- used in an authenticator app you should reset your authenticator keys.
-
-
-
-
-
-}
-
-@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.
-
-
-
-
-@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)
- {
-
- }
-
- 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
-