Произошла непредвиденная ошибка
@@ -69,6 +65,8 @@
{
currentUrl = NavigationManager.ToBaseRelativePath(e.Location);
+ NotificationService.Messages.Clear();
+
StateHasChanged();
}
}
diff --git a/Hcs.WebApp/Components/Pages/Account/Register.razor b/Hcs.WebApp/Components/Pages/Account/Register.razor
index 50020ff..dd03f9d 100644
--- a/Hcs.WebApp/Components/Pages/Account/Register.razor
+++ b/Hcs.WebApp/Components/Pages/Account/Register.razor
@@ -1,21 +1,13 @@
@page "/account/register"
-@using Microsoft.AspNetCore.Identity
-@using Hcs.WebApp.Data
-@using Hcs.WebApp.Identity
-
-@inject IUserStore
UserStore
-@inject UserManager UserManager
@inject NotificationService NotificationService
-@inject SignInManager SignInManager
-@inject IdentityRedirectManager RedirectManager
Регистрация аккаунта
-
+
- Регистрация
+ Регистрация
@@ -42,7 +34,7 @@
-
+
@@ -63,28 +55,28 @@
[SupplyParameterFromForm]
InputModel Input { get; set; } = new();
+ [SupplyParameterFromQuery]
+ string? Errors { get; set; }
+
[SupplyParameterFromQuery]
string? ReturnUrl { get; set; }
- async Task OnSubmit(InputModel mode)
+ protected override void OnAfterRender(bool firstRender)
{
- var user = Activator.CreateInstance();
- await UserStore.SetUserNameAsync(user, Input.UserName, CancellationToken.None);
+ base.OnAfterRender(firstRender);
- var result = await UserManager.CreateAsync(user, Input.Password);
- if (!result.Succeeded)
+ if (firstRender)
{
- NotificationService.Notify(new NotificationMessage()
+ if (!string.IsNullOrEmpty(Errors))
{
- Severity = NotificationSeverity.Error,
- Summary = "Ошибка",
- Detail = string.Join(", ", result.Errors.Select(error => error.Description))
- });
- return;
+ NotificationService.Notify(new NotificationMessage()
+ {
+ Severity = NotificationSeverity.Error,
+ Summary = "Ошибка",
+ Detail = Errors,
+ Duration = -1d
+ });
+ }
}
-
- await SignInManager.SignInAsync(user, isPersistent: false);
-
- RedirectManager.RedirectTo(ReturnUrl);
}
}
diff --git a/Hcs.WebApp/Components/Pages/Test/Export.razor b/Hcs.WebApp/Components/Pages/Test/Export.razor
index 33ed8b0..2f4019e 100644
--- a/Hcs.WebApp/Components/Pages/Test/Export.razor
+++ b/Hcs.WebApp/Components/Pages/Test/Export.razor
@@ -1,12 +1,12 @@
@page "/test/export"
-@using Microsoft.AspNetCore.Authorization
@using Hcs.Broker
@using Hcs.Broker.Logger
@using Hcs.Broker.MessageCapturer
@using Hcs.Service.Async.Nsi
@using Hcs.WebApp.Config
@using Hcs.WebApp.Utils
+@using Microsoft.AspNetCore.Authorization
@implements IDisposable
diff --git a/Hcs.WebApp/Components/_Imports.razor b/Hcs.WebApp/Components/_Imports.razor
index a09ea1b..9a15bfd 100644
--- a/Hcs.WebApp/Components/_Imports.razor
+++ b/Hcs.WebApp/Components/_Imports.razor
@@ -1,5 +1,8 @@
@using System.Net.Http
@using System.Net.Http.Json
+@using Hcs.WebApp
+@using Hcs.WebApp.Components
+@using Hcs.WebApp.Components.Shared
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@@ -8,8 +11,5 @@
@using Microsoft.JSInterop
@using Radzen
@using Radzen.Blazor
-@using Hcs.WebApp
-@using Hcs.WebApp.Components
-@using Hcs.WebApp.Components.Shared
@using static Microsoft.AspNetCore.Components.Web.RenderMode
diff --git a/Hcs.WebApp/Controllers/IdentityController.cs b/Hcs.WebApp/Controllers/IdentityController.cs
new file mode 100644
index 0000000..25f1ca1
--- /dev/null
+++ b/Hcs.WebApp/Controllers/IdentityController.cs
@@ -0,0 +1,55 @@
+using Hcs.WebApp.Data;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Mvc;
+using Radzen;
+
+namespace Hcs.WebApp.Controllers
+{
+ [Route("identity/[action]")]
+ public class IdentityController(
+ IUserStore userStore,
+ UserManager userManager,
+ SignInManager signInManager) : Controller
+ {
+ private readonly IUserStore userStore = userStore;
+ private readonly UserManager userManager = userManager;
+ private readonly SignInManager signInManager = signInManager;
+
+ [HttpPost]
+ public async Task Register(string userName, string password, string returnUrl)
+ {
+ var user = Activator.CreateInstance();
+ await userStore.SetUserNameAsync(user, userName, CancellationToken.None);
+
+ var result = await userManager.CreateAsync(user, password);
+ if (!result.Succeeded)
+ {
+ var errors = string.Join(", ", result.Errors.Select(error => error.Description));
+ if (!string.IsNullOrEmpty(returnUrl))
+ {
+ return Redirect($"/account/register?errors={errors}&returnUrl={Uri.EscapeDataString(returnUrl)}");
+ }
+ else
+ {
+ return Redirect($"/account/register?errors={errors}");
+ }
+ }
+
+ await signInManager.SignInAsync(user, isPersistent: false);
+
+ if (string.IsNullOrEmpty(returnUrl))
+ {
+ Redirect("/");
+ }
+
+ return Redirect(returnUrl);
+ }
+
+ public async Task Logout()
+ {
+ await signInManager.SignOutAsync();
+
+ return Redirect("/");
+ }
+ }
+}
diff --git a/Hcs.WebApp/Data/AppIdentityDbContext.cs b/Hcs.WebApp/Data/AppIdentityDbContext.cs
index 3e760cd..391264d 100644
--- a/Hcs.WebApp/Data/AppIdentityDbContext.cs
+++ b/Hcs.WebApp/Data/AppIdentityDbContext.cs
@@ -3,5 +3,5 @@ using Microsoft.EntityFrameworkCore;
namespace Hcs.WebApp.Data
{
- internal class AppIdentityDbContext(DbContextOptions options) : IdentityDbContext(options) { }
+ public class AppIdentityDbContext(DbContextOptions options) : IdentityDbContext(options) { }
}
diff --git a/Hcs.WebApp/Data/AppRole.cs b/Hcs.WebApp/Data/AppRole.cs
new file mode 100644
index 0000000..dab2600
--- /dev/null
+++ b/Hcs.WebApp/Data/AppRole.cs
@@ -0,0 +1,6 @@
+using Microsoft.AspNetCore.Identity;
+
+namespace Hcs.WebApp.Data
+{
+ public class AppRole : IdentityRole { }
+}
diff --git a/Hcs.WebApp/Data/AppUser.cs b/Hcs.WebApp/Data/AppUser.cs
index 21b6d93..1abbf81 100644
--- a/Hcs.WebApp/Data/AppUser.cs
+++ b/Hcs.WebApp/Data/AppUser.cs
@@ -2,5 +2,5 @@
namespace Hcs.WebApp.Data
{
- internal class AppUser : IdentityUser { }
+ public class AppUser : IdentityUser { }
}
diff --git a/Hcs.WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs b/Hcs.WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs
index 8cb9094..052ba4a 100644
--- a/Hcs.WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs
+++ b/Hcs.WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs
@@ -4,7 +4,7 @@
namespace Hcs.WebApp.Data.Migrations
{
///
- internal partial class CreateIdentitySchema : Migration
+ public partial class CreateIdentitySchema : Migration
{
///
protected override void Up(MigrationBuilder migrationBuilder)
diff --git a/Hcs.WebApp/Data/Migrations/AppIdentityDbContextModelSnapshot.cs b/Hcs.WebApp/Data/Migrations/AppIdentityDbContextModelSnapshot.cs
index 2fa491b..a63d47d 100644
--- a/Hcs.WebApp/Data/Migrations/AppIdentityDbContextModelSnapshot.cs
+++ b/Hcs.WebApp/Data/Migrations/AppIdentityDbContextModelSnapshot.cs
@@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
namespace Hcs.WebApp.Data.Migrations
{
[DbContext(typeof(AppIdentityDbContext))]
- internal class AppIdentityDbContextModelSnapshot : ModelSnapshot
+ public class AppIdentityDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
diff --git a/Hcs.WebApp/Hcs.WebApp.csproj b/Hcs.WebApp/Hcs.WebApp.csproj
index 65cd85e..c063d08 100644
--- a/Hcs.WebApp/Hcs.WebApp.csproj
+++ b/Hcs.WebApp/Hcs.WebApp.csproj
@@ -8,6 +8,7 @@
+
diff --git a/Hcs.WebApp/Identity/IdentityComponentsEndpointRouteBuilderExtensions.cs b/Hcs.WebApp/Identity/IdentityComponentsEndpointRouteBuilderExtensions.cs
deleted file mode 100644
index 58cc656..0000000
--- a/Hcs.WebApp/Identity/IdentityComponentsEndpointRouteBuilderExtensions.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Hcs.WebApp.Data;
-using Microsoft.AspNetCore.Identity;
-using Microsoft.AspNetCore.Mvc;
-using System.Security.Claims;
-
-namespace Hcs.WebApp.Identity
-{
- internal static class IdentityComponentsEndpointRouteBuilderExtensions
- {
- public static IEndpointConventionBuilder MapAdditionalIdentityEndpoints(this IEndpointRouteBuilder endpoints)
- {
- ArgumentNullException.ThrowIfNull(endpoints);
-
- var accountGroup = endpoints.MapGroup("/account");
- accountGroup.MapPost("/logout", async (
- ClaimsPrincipal user,
- SignInManager signInManager,
- [FromForm] string returnUrl) =>
- {
- await signInManager.SignOutAsync();
- return TypedResults.LocalRedirect($"~/{returnUrl}");
- });
-
- return accountGroup;
- }
- }
-}
diff --git a/Hcs.WebApp/Identity/IdentityRedirectManager.cs b/Hcs.WebApp/Identity/IdentityRedirectManager.cs
deleted file mode 100644
index ef2bb53..0000000
--- a/Hcs.WebApp/Identity/IdentityRedirectManager.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using Microsoft.AspNetCore.Components;
-using System.Diagnostics.CodeAnalysis;
-
-namespace Hcs.WebApp.Identity
-{
- internal sealed class IdentityRedirectManager(NavigationManager navigationManager)
- {
- public const string STATUS_COOKIE_NAME = "Identity.StatusMessage";
-
- private static readonly CookieBuilder statusCookieBuilder = new()
- {
- SameSite = SameSiteMode.Strict,
- HttpOnly = true,
- IsEssential = true,
- MaxAge = TimeSpan.FromSeconds(5),
- };
-
- private string CurrentPath => navigationManager.ToAbsoluteUri(navigationManager.Uri).GetLeftPart(UriPartial.Path);
-
- [DoesNotReturn]
- public void RedirectTo(string? uri)
- {
- uri ??= "";
-
- if (!Uri.IsWellFormedUriString(uri, UriKind.Relative))
- {
- uri = navigationManager.ToBaseRelativePath(uri);
- }
-
- navigationManager.NavigateTo(uri);
-
- throw new InvalidOperationException($"{nameof(IdentityRedirectManager)} может быть использован только при статичном рендеринге");
- }
-
- [DoesNotReturn]
- public void RedirectTo(string uri, Dictionary queryParameters)
- {
- var uriWithoutQuery = navigationManager.ToAbsoluteUri(uri).GetLeftPart(UriPartial.Path);
- var newUri = navigationManager.GetUriWithQueryParameters(uriWithoutQuery, queryParameters);
- RedirectTo(newUri);
- }
-
- [DoesNotReturn]
- public void RedirectToWithStatus(string uri, string message, HttpContext context)
- {
- context.Response.Cookies.Append(STATUS_COOKIE_NAME, message, statusCookieBuilder.Build(context));
- RedirectTo(uri);
- }
-
- [DoesNotReturn]
- public void RedirectToCurrentPage()
- {
- RedirectTo(CurrentPath);
- }
-
- [DoesNotReturn]
- public void RedirectToCurrentPageWithStatus(string message, HttpContext context)
- {
- RedirectToWithStatus(CurrentPath, message, context);
- }
- }
-}
diff --git a/Hcs.WebApp/Identity/IdentityRevalidatingAuthenticationStateProvider.cs b/Hcs.WebApp/Identity/IdentityRevalidatingAuthenticationStateProvider.cs
deleted file mode 100644
index dd98fe2..0000000
--- a/Hcs.WebApp/Identity/IdentityRevalidatingAuthenticationStateProvider.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Hcs.WebApp.Data;
-using Microsoft.AspNetCore.Components.Authorization;
-using Microsoft.AspNetCore.Components.Server;
-using Microsoft.AspNetCore.Identity;
-using Microsoft.Extensions.Options;
-using System.Security.Claims;
-
-namespace Hcs.WebApp.Identity
-{
- internal sealed class IdentityRevalidatingAuthenticationStateProvider(
- ILoggerFactory loggerFactory,
- IServiceScopeFactory scopeFactory,
- IOptions options) : RevalidatingServerAuthenticationStateProvider(loggerFactory)
- {
- protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);
-
- protected override async Task ValidateAuthenticationStateAsync(
- AuthenticationState authenticationState, CancellationToken cancellationToken)
- {
- await using var scope = scopeFactory.CreateAsyncScope();
-
- var userManager = scope.ServiceProvider.GetRequiredService>();
- return await ValidateSecurityStampAsync(userManager, authenticationState.User);
- }
-
- private async Task ValidateSecurityStampAsync(UserManager userManager, ClaimsPrincipal principal)
- {
- var user = await userManager.GetUserAsync(principal);
- if (user is null)
- {
- return false;
- }
- else if (!userManager.SupportsUserSecurityStamp)
- {
- return true;
- }
- else
- {
- var principalStamp = principal.FindFirstValue(options.Value.ClaimsIdentity.SecurityStampClaimType);
- var userStamp = await userManager.GetSecurityStampAsync(user);
- return principalStamp == userStamp;
- }
- }
- }
-}
diff --git a/Hcs.WebApp/Identity/IdentityUserAccessor.cs b/Hcs.WebApp/Identity/IdentityUserAccessor.cs
deleted file mode 100644
index 0446880..0000000
--- a/Hcs.WebApp/Identity/IdentityUserAccessor.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Hcs.WebApp.Data;
-using Microsoft.AspNetCore.Identity;
-
-namespace Hcs.WebApp.Identity
-{
- internal sealed class IdentityUserAccessor(UserManager userManager, IdentityRedirectManager redirectManager)
- {
- public async Task GetRequiredUserAsync(HttpContext context)
- {
- var user = await userManager.GetUserAsync(context.User);
- if (user is null)
- {
- redirectManager.RedirectToWithStatus("account/invalid_user", $"Ошибка: Не удалось загрузить пользователя с идентификатором '{userManager.GetUserId(context.User)}'", context);
- }
- return user;
- }
- }
-}
diff --git a/Hcs.WebApp/Program.cs b/Hcs.WebApp/Program.cs
index ee6889a..78de197 100644
--- a/Hcs.WebApp/Program.cs
+++ b/Hcs.WebApp/Program.cs
@@ -1,7 +1,5 @@
using Hcs.WebApp.Components;
using Hcs.WebApp.Data;
-using Hcs.WebApp.Identity;
-using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Radzen;
@@ -12,52 +10,49 @@ builder.Services
.AddRazorComponents()
.AddInteractiveServerComponents();
+builder.Services.AddControllers();
builder.Services.AddRadzenComponents();
-builder.Services.AddCascadingAuthenticationState();
-builder.Services.AddScoped();
-builder.Services.AddScoped();
-builder.Services.AddScoped();
-
-builder.Services
- .AddAuthentication(options =>
- {
- options.DefaultScheme = IdentityConstants.ApplicationScheme;
- options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
- })
- .AddIdentityCookies();
+builder.Services.AddHttpClient("Hcs.WebApp").AddHeaderPropagation(x => x.Headers.Add("Cookie"));
+builder.Services.AddHeaderPropagation(x => x.Headers.Add("Cookie"));
+builder.Services.AddAuthentication();
+builder.Services.AddAuthorization();
var connectionString = builder.Configuration.GetConnectionString("IdentityConnection") ?? throw new InvalidOperationException(" 'IdentityConnection'");
builder.Services.AddDbContext(options => options.UseSqlServer(connectionString));
-builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services
- .AddIdentityCore()
+ .AddIdentity(options =>
+ {
+ options.Password.RequiredLength = 6;
+ options.Password.RequireNonAlphanumeric = false;
+ options.Password.RequireDigit = false;
+ options.Password.RequireLowercase = false;
+ options.Password.RequireUppercase = false;
+ options.Password.RequiredUniqueChars = 1;
+ })
.AddEntityFrameworkStores()
- .AddSignInManager()
.AddDefaultTokenProviders();
var app = builder.Build();
-if (app.Environment.IsDevelopment())
-{
- app.UseMigrationsEndPoint();
-}
-else
+if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error", createScopeForErrors: true);
app.UseHsts();
}
app.UseHttpsRedirection();
-
app.UseStaticFiles();
+app.UseHeaderPropagation();
+app.UseRouting();
app.UseAntiforgery();
+app.UseAuthentication();
+app.UseAuthorization();
+app.MapControllers();
app
.MapRazorComponents()
.AddInteractiveServerRenderMode();
-app.MapAdditionalIdentityEndpoints();
-
app.Run();