/
azarayaos
/
OrderHub
Обзор
Документация
Войти
/
azarayaos
/
OrderHub
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
dev
OrderHub.Tests/TestServerHelper.cs
207 строк
8 KB
Azaray AOS
Добавлена APiпо авторизации и тесты для него. Так же пдготовлен файл CICD
01 июл 2026, 21:04
01 июл 2026, 21:04
9ff1e4b
Код
Авторство
О чём код?
using System.IdentityModel.Tokens.Jwt; using System.Net.Http.Headers; using System.Net.Http.Json; using System.Security.Claims; using System.Text; using System.Text.Json; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.TestHost; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.IdentityModel.Tokens; using NSubstitute; using OrderHub.ApiService.Endpoints; using OrderHub.Core.Interfaces; using OrderHub.Infrastructure.Data; using OrderHub.Infrastructure.Repositories; namespace OrderHub.Tests; /// <summary> /// Вспомогательный класс для создания TestServer с настроенной JWT-аутентификацией. /// </summary> public static class TestServerHelper { private const string JwtKey = "TestKey_ForUnitTests_MustBeAtLeast32Chars!"; private const string JwtIssuer = "OrderHub.Tests"; private const string JwtAudience = "OrderHub.Tests"; /// <summary> /// Создаёт TestServer с InMemory БД, JWT-аутентификацией и замоканным EventPublisher. /// </summary> /// <returns>Хост TestServer и HTTP-клиент.</returns> public static (IHost Host, HttpClient Client) CreateTestServer() { var orderDbName = Guid.NewGuid().ToString(); var authDbName = Guid.NewGuid().ToString(); var builder = new HostBuilder() .ConfigureAppConfiguration(config => { config.AddInMemoryCollection(new Dictionary<string, string?> { ["Jwt:Key"] = JwtKey, ["Jwt:Issuer"] = JwtIssuer, ["Jwt:Audience"] = JwtAudience }); }) .ConfigureWebHost(webHost => { webHost.UseTestServer(); webHost.Configure(app => { app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapAuthEndpoints(); endpoints.MapOrderEndpoints(); endpoints.MapStatusEndpoints(); endpoints.MapAdminEndpoints(); endpoints.MapHealthEndpoints(); }); }); webHost.ConfigureServices(services => { services.AddRouting(); services.AddDbContext<OrderDbContext>(options => options.UseInMemoryDatabase(orderDbName)); services.AddDbContext<AuthDbContext>(options => options.UseInMemoryDatabase(authDbName)); services.AddIdentity<OrderHubUser, IdentityRole>(options => { options.Password.RequireDigit = true; options.Password.RequiredLength = 8; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = true; options.Password.RequireLowercase = true; options.User.RequireUniqueEmail = true; }) .AddEntityFrameworkStores<AuthDbContext>() .AddDefaultTokenProviders(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = JwtIssuer, ValidAudience = JwtAudience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtKey)) }; }); services.AddAuthorizationBuilder() .AddPolicy("AdminOnly", policy => policy.RequireRole("Admin")); services.AddScoped<IOrderRepository, OrderRepository>(); var mockPublisher = Substitute.For<IEventPublisher>(); services.AddSingleton(mockPublisher); }); }); var host = builder.Start(); var server = host.GetTestServer(); return (host, server.CreateClient()); } /// <summary> /// Генерирует JWT-токен для тестов с указанными ролями. /// </summary> /// <param name="userId">Идентификатор пользователя.</param> /// <param name="email">Email пользователя.</param> /// <param name="roles">Список ролей.</param> /// <returns>JWT-токен.</returns> public static string GenerateTestToken(string userId = "test-user-id", string email = "test@test.com", string[]? roles = null) { var claims = new List<Claim> { new(ClaimTypes.NameIdentifier, userId), new(ClaimTypes.Name, email), new(ClaimTypes.Email, email), new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; if (roles is not null) { claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r))); } var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtKey)); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = DateTime.UtcNow.AddHours(1), Issuer = JwtIssuer, Audience = JwtAudience, SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256) }; var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } /// <summary> /// Устанавливает заголовок авторизации Bearer для HTTP-клиента. /// </summary> /// <param name="client">HTTP-клиент.</param> /// <param name="token">JWT-токен.</param> public static void AuthenticateClient(HttpClient client, string token) { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); } /// <summary> /// Регистрирует и входит пользователем через API, возвращает токен. /// </summary> /// <param name="client">HTTP-клиент.</param> /// <param name="email">Email пользователя.</param> /// <param name="password">Пароль пользователя.</param> /// <returns>JWT-токен или null при ошибке.</returns> public static async Task<string?> RegisterAndLoginAsync(HttpClient client, string email, string password) { var registerResponse = await client.PostAsJsonAsync("/api/auth/register", new { Email = email, Password = password }); if (!registerResponse.IsSuccessStatusCode) { return null; } var loginResponse = await client.PostAsJsonAsync("/api/auth/login", new { Email = email, Password = password }); if (!loginResponse.IsSuccessStatusCode) { return null; } var authData = await loginResponse.Content.ReadFromJsonAsync<Dictionary<string, JsonElement>>(); return authData is not null && authData.TryGetValue("token", out var tokenProp) ? tokenProp.GetString() : null; } }