Убрать неиспользуемые using по код-стайлу
Прогон dotnet format (IDE0005) по 4 решениям: удалены лишние using, оставшиеся после миграции namespace (676 файлов).
This commit is contained in:
@@ -1,81 +1,74 @@
|
||||
using Deal.Api.Configuration;
|
||||
using Deal.Api.Extensions;
|
||||
using Deal.Api.Models;
|
||||
using Deal.Api.Services;
|
||||
using Deal.Modules.Tenants.Application.Abstractions;
|
||||
using Deal.Modules.Tenants.Application.Extensions;
|
||||
using Deal.Modules.Tenants.Application.Models;
|
||||
using Deal.Modules.Tenants.Application.Registrars;
|
||||
using Deal.Modules.Tenants.Application.Services;
|
||||
using Deal.SharedKernel.Tenants.Abstractions;
|
||||
using Deal.SharedKernel.Tenants.Models;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Deal.Api.Dtos;
|
||||
// Имя конфигурационного типа совпадает с Microsoft.AspNetCore.Http.CookieOptions — фиксируем алиасом.
|
||||
using CookieOptions = Deal.Api.Configuration.CookieOptions;
|
||||
|
||||
namespace Deal.Api.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// Middleware сессии: читает httpOnly-куку, разрешает сессию через AuthService и наполняет
|
||||
/// <c>HttpContext.Items["CurrentUser"]</c> + tenant-контекст запроса (ITenantContext).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Middleware НЕ отвечает 401 сама (pass-through): эндпоинты, требующие авторизации, проверяют
|
||||
/// пользователя и выставляют 401. Нет куки или сессия невалидна — запрос идёт дальше без
|
||||
/// пользователя. Tenant-контекст сбрасывается в finally после обработки запроса.
|
||||
/// <para>
|
||||
/// AuthService — scoped, поэтому на запрос создаётся собственный scope через RequestServices.
|
||||
/// Экземпляр middleware — singleton (стандартный паттерн UseMiddleware), опции читаются через
|
||||
/// IOptionsMonitor, чтобы подхватывать изменения конфигурации.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class SessionMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IOptionsMonitor<CookieOptions> _cookieOptions;
|
||||
private readonly ITenantContext _tenantContext;
|
||||
|
||||
public SessionMiddleware(
|
||||
RequestDelegate next,
|
||||
IOptionsMonitor<CookieOptions> cookieOptions,
|
||||
ITenantContext tenantContext)
|
||||
{
|
||||
_next = next;
|
||||
_cookieOptions = cookieOptions;
|
||||
_tenantContext = tenantContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обрабатывает запрос: разрешает сессию по куке и наполняет контекст.
|
||||
/// </summary>
|
||||
/// <param name="context">Контекст запроса.</param>
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cookieName = _cookieOptions.CurrentValue.Name;
|
||||
if (context.Request.Cookies.TryGetValue(cookieName, out var rawToken)
|
||||
&& !string.IsNullOrWhiteSpace(rawToken))
|
||||
{
|
||||
// AuthService scoped: создаём scope на запрос через RequestServices.
|
||||
await using var scope = context.RequestServices.CreateAsyncScope();
|
||||
var authService = scope.ServiceProvider.GetRequiredService<AuthService>();
|
||||
var user = await authService.ResolveSessionAsync(rawToken, context.RequestAborted);
|
||||
if (user is not null)
|
||||
{
|
||||
context.SetCurrentUser(new CurrentUser(user.Id, user.Login, user.TenantId, user.Status));
|
||||
// Схема тенанта именуется tenant_<id>, где id — Guid в формате "N" (см. TenantService).
|
||||
_tenantContext.SetTenant(new TenantId(user.TenantId.ToString("N")));
|
||||
}
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Контекст AsyncLocal не должен переживать запрос.
|
||||
_tenantContext.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Deal.Api.Extensions;
|
||||
using Deal.Api.Models;
|
||||
using Deal.Modules.Tenants.Application.Services;
|
||||
using Deal.SharedKernel.Tenants.Abstractions;
|
||||
using Deal.SharedKernel.Tenants.Models;
|
||||
using Microsoft.Extensions.Options;
|
||||
// Имя конфигурационного типа совпадает с Microsoft.AspNetCore.Http.CookieOptions — фиксируем алиасом.
|
||||
using CookieOptions = Deal.Api.Configuration.CookieOptions;
|
||||
|
||||
namespace Deal.Api.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// Middleware сессии: читает httpOnly-куку, разрешает сессию через AuthService и наполняет
|
||||
/// <c>HttpContext.Items["CurrentUser"]</c> + tenant-контекст запроса (ITenantContext).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Middleware НЕ отвечает 401 сама (pass-through): эндпоинты, требующие авторизации, проверяют
|
||||
/// пользователя и выставляют 401. Нет куки или сессия невалидна — запрос идёт дальше без
|
||||
/// пользователя. Tenant-контекст сбрасывается в finally после обработки запроса.
|
||||
/// <para>
|
||||
/// AuthService — scoped, поэтому на запрос создаётся собственный scope через RequestServices.
|
||||
/// Экземпляр middleware — singleton (стандартный паттерн UseMiddleware), опции читаются через
|
||||
/// IOptionsMonitor, чтобы подхватывать изменения конфигурации.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class SessionMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IOptionsMonitor<CookieOptions> _cookieOptions;
|
||||
private readonly ITenantContext _tenantContext;
|
||||
|
||||
public SessionMiddleware(
|
||||
RequestDelegate next,
|
||||
IOptionsMonitor<CookieOptions> cookieOptions,
|
||||
ITenantContext tenantContext)
|
||||
{
|
||||
_next = next;
|
||||
_cookieOptions = cookieOptions;
|
||||
_tenantContext = tenantContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обрабатывает запрос: разрешает сессию по куке и наполняет контекст.
|
||||
/// </summary>
|
||||
/// <param name="context">Контекст запроса.</param>
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cookieName = _cookieOptions.CurrentValue.Name;
|
||||
if (context.Request.Cookies.TryGetValue(cookieName, out var rawToken)
|
||||
&& !string.IsNullOrWhiteSpace(rawToken))
|
||||
{
|
||||
// AuthService scoped: создаём scope на запрос через RequestServices.
|
||||
await using var scope = context.RequestServices.CreateAsyncScope();
|
||||
var authService = scope.ServiceProvider.GetRequiredService<AuthService>();
|
||||
var user = await authService.ResolveSessionAsync(rawToken, context.RequestAborted);
|
||||
if (user is not null)
|
||||
{
|
||||
context.SetCurrentUser(new CurrentUser(user.Id, user.Login, user.TenantId, user.Status));
|
||||
// Схема тенанта именуется tenant_<id>, где id — Guid в формате "N" (см. TenantService).
|
||||
_tenantContext.SetTenant(new TenantId(user.TenantId.ToString("N")));
|
||||
}
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Контекст AsyncLocal не должен переживать запрос.
|
||||
_tenantContext.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user