133 lines
5.9 KiB
C#
133 lines
5.9 KiB
C#
using System.Text;
|
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using TeleWave.Application.Broadcast.Bumpers;
|
|
using TeleWave.Application.Broadcast.Scheduling;
|
|
using TeleWave.Application.Common.Interfaces;
|
|
using TeleWave.Application.Streaming;
|
|
using TeleWave.Domain.Broadcast.Scheduling;
|
|
using TeleWave.Infrastructure.Broadcast;
|
|
using TeleWave.Infrastructure.Identity;
|
|
using TeleWave.Infrastructure.Media;
|
|
using TeleWave.Infrastructure.Persistence;
|
|
using TeleWave.Infrastructure.Settings;
|
|
using TeleWave.Infrastructure.Streaming;
|
|
|
|
namespace TeleWave.Infrastructure;
|
|
|
|
/// <summary>
|
|
/// Регистрация сервисов инфраструктуры: EF Core (PostgreSQL), Identity/JWT-аутентификация.
|
|
/// </summary>
|
|
public static class DependencyInjection
|
|
{
|
|
public static IServiceCollection AddInfrastructure(
|
|
this IServiceCollection services,
|
|
IConfiguration configuration
|
|
)
|
|
{
|
|
services.AddDbContext<AppDbContext>(options =>
|
|
options.UseNpgsql(
|
|
configuration["ConnectionStrings:Default"]
|
|
?? throw new InvalidOperationException(
|
|
"Строка подключения 'ConnectionStrings:Default' не сконфигурирована."
|
|
)
|
|
)
|
|
);
|
|
services.AddScoped<IAppDbContext>(sp => sp.GetRequiredService<AppDbContext>());
|
|
|
|
services
|
|
.AddIdentityCore<AppUser>(options =>
|
|
{
|
|
options.User.RequireUniqueEmail = false;
|
|
options.Password.RequiredLength = 8;
|
|
options.Password.RequireDigit = true;
|
|
options.Password.RequireUppercase = true;
|
|
options.Password.RequireNonAlphanumeric = false;
|
|
options.Lockout.MaxFailedAccessAttempts = 5;
|
|
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
|
|
options.Lockout.AllowedForNewUsers = true;
|
|
})
|
|
.AddRoles<AppRole>()
|
|
.AddEntityFrameworkStores<AppDbContext>()
|
|
.AddSignInManager()
|
|
.AddDefaultTokenProviders();
|
|
|
|
services.Configure<JwtOptions>(configuration.GetSection(JwtOptions.SectionName));
|
|
services.Configure<AdminSeedOptions>(
|
|
configuration.GetSection(AdminSeedOptions.SectionName)
|
|
);
|
|
|
|
var jwtOptions =
|
|
configuration.GetSection(JwtOptions.SectionName).Get<JwtOptions>()
|
|
?? throw new InvalidOperationException("Секция конфигурации 'Jwt' не задана.");
|
|
|
|
services
|
|
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
.AddJwtBearer(options =>
|
|
{
|
|
options.TokenValidationParameters = new TokenValidationParameters
|
|
{
|
|
ValidateIssuer = true,
|
|
ValidIssuer = jwtOptions.Issuer,
|
|
ValidateAudience = true,
|
|
ValidAudience = jwtOptions.Audience,
|
|
ValidateIssuerSigningKey = true,
|
|
IssuerSigningKey = new SymmetricSecurityKey(
|
|
Encoding.UTF8.GetBytes(jwtOptions.SigningKey)
|
|
),
|
|
ValidateLifetime = true,
|
|
ClockSkew = TimeSpan.FromSeconds(30),
|
|
};
|
|
});
|
|
|
|
services.AddAuthorization();
|
|
|
|
services.AddScoped<IIdentityService, IdentityService>();
|
|
services.AddScoped<IJwtTokenService, JwtTokenService>();
|
|
services.AddScoped<IRefreshTokenService, RefreshTokenService>();
|
|
services.AddScoped<IRoleService, RoleService>();
|
|
services.AddScoped<ICurrentUser, CurrentUser>();
|
|
services.AddScoped<ISiteSettings, SiteSettings>();
|
|
services.AddScoped<DbInitializer>();
|
|
|
|
AddMedia(services, configuration);
|
|
AddBroadcast(services, configuration);
|
|
|
|
return services;
|
|
}
|
|
|
|
/// <summary>Планировщик расписания: генератор, источник случайности и фоновый сервис горизонта.</summary>
|
|
private static void AddBroadcast(IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
services.Configure<SchedulerOptions>(configuration.GetSection(SchedulerOptions.SectionName));
|
|
services.Configure<StreamingOptions>(configuration.GetSection(StreamingOptions.SectionName));
|
|
services.Configure<BumperOptions>(configuration.GetSection(BumperOptions.SectionName));
|
|
|
|
services.AddSingleton<IRandomSource, SystemRandomSource>();
|
|
services.AddSingleton<StreamTokenService>();
|
|
services.AddSingleton<IBumperRenderer, FfmpegBumperRenderer>();
|
|
services.AddScoped<ScheduleGenerator>();
|
|
services.AddHostedService<SchedulingBackgroundService>();
|
|
}
|
|
|
|
/// <summary>Хранилище медиа, обработка ffmpeg, очередь и фоновые сервисы (очередь + inbox-сканер).</summary>
|
|
private static void AddMedia(IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
services.Configure<StorageOptions>(configuration.GetSection(StorageOptions.SectionName));
|
|
services.Configure<MediaOptions>(configuration.GetSection(MediaOptions.SectionName));
|
|
|
|
services.AddSingleton<MediaPathResolver>();
|
|
services.AddSingleton<IMediaStorage, FileSystemMediaStorage>();
|
|
services.AddSingleton<IBumperTemplateStorage, BumperTemplateStorage>();
|
|
services.AddSingleton<IMediaProcessor, FfmpegMediaProcessor>();
|
|
services.AddSingleton<IMediaProcessingQueue, MediaProcessingQueue>();
|
|
|
|
services.AddHostedService<MediaProcessingBackgroundService>();
|
|
services.AddHostedService<InboxScannerBackgroundService>();
|
|
}
|
|
}
|