/
afanasevn
/
RedisLab
Обзор
Документация
Войти
/
afanasevn
/
RedisLab
Код
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/RedisLab.Infrastructure/DependencyInjection.cs
111 строк
5 KB
IBS\NAfanasev
Update solution commit
24 июн 2026, 19:46
24 июн 2026, 19:46
40761b1
Код
Авторство
О чём код?
using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using RedisLab.Application.Abstractions; using RedisLab.Infrastructure.Activity; using RedisLab.Infrastructure.Auth; using RedisLab.Infrastructure.Dashboard; using RedisLab.Infrastructure.Hosting; using RedisLab.Infrastructure.Leaderboard; using RedisLab.Infrastructure.Notifications; using RedisLab.Infrastructure.Persistence; using RedisLab.Infrastructure.Redis; using RedisLab.Infrastructure.Reminders; using RedisLab.Infrastructure.Tasks; using StackExchange.Redis; namespace RedisLab.Infrastructure; /// <summary> /// Регистрация сервисов Infrastructure-слоя в DI-контейнере. /// </summary> public static class DependencyInjection { /// <summary> /// Подключает PostgreSQL, Redis, JWT и application services. /// </summary> public static IServiceCollection AddInfrastructure( this IServiceCollection services, IConfiguration configuration) { services.Configure<JwtSettings>(configuration.GetSection(JwtSettings.SectionName)); var connectionString = configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("ConnectionStrings:DefaultConnection не задан"); services.AddDbContext<AppDbContext>(options => options.UseNpgsql(connectionString)); var redisConnection = configuration.GetConnectionString("Redis") ?? throw new InvalidOperationException("ConnectionStrings:Redis не задан"); // IConnectionMultiplexer — один на приложение: переиспользует TCP-соединения к Redis. services.AddSingleton<IConnectionMultiplexer>(_ => ConnectionMultiplexer.Connect(redisConnection)); services.AddSingleton<InstanceIdentity>(); services.AddSingleton<IDistributedLockService, DistributedLockService>(); services.AddHostedService<TaskReminderHostedService>(); services.AddHostedService<LeaderboardRebuildHostedService>(); services.AddHostedService<NotificationStreamConsumerHostedService>(); services.AddSingleton<IProcessedNotificationStore, ProcessedNotificationStore>(); services.AddScoped<IAuthService, AuthService>(); services.AddScoped<DashboardService>(); services.AddScoped<IDashboardService>(sp => sp.GetRequiredService<DashboardService>()); services.AddScoped<IDashboardKpiCacheInvalidator>(sp => sp.GetRequiredService<DashboardService>()); services.AddScoped<TaskCardCache>(); services.AddScoped<ITaskCardCacheInvalidator>(sp => sp.GetRequiredService<TaskCardCache>()); services.AddScoped<ILoginRateLimiter, LoginRateLimiter>(); services.AddScoped<IRedisDebugService, RedisDebugService>(); services.AddScoped<IActivityFeedService, ActivityFeedService>(); services.AddScoped<INotificationStreamPublisher, NotificationStreamPublisher>(); services.AddScoped<ILeaderboardService, LeaderboardService>(); services.AddScoped<ITaskService, TaskService>(); var jwt = configuration.GetSection(JwtSettings.SectionName).Get<JwtSettings>() ?? throw new InvalidOperationException("Секция Jwt не задана"); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // Сохраняем короткие JWT-имена claim (sub, role), иначе Me не найдёт user id. options.MapInboundClaims = false; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwt.Issuer, ValidAudience = jwt.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.Key)), }; // SignalR передаёт JWT через query access_token при WebSocket negotiate. options.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs")) { context.Token = accessToken; } return Task.CompletedTask; }, }; }); services.AddAuthorization(); return services; } }