using FileShare_API.Authentication; using FileShare_API.Services; using FileShare_EFCore.Database; using FileShare_Services.Core; using FileShare_Services.Endpoints; using FileShare_Services.Services; using FileShare_Services.Services.AuthService; using FileShare_Services.Services.FileLibrary; using FileShare_Services.Services.QrCode; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; namespace FileShare_API.Configuration { /// /// API 项目服务配置扩展类,负责注册数据库、鉴权、业务服务和统一端点。 /// public static class ServicesConfiguration { /// /// 注册统一端点及其依赖的服务(含数据库)。 /// 所有业务端点定义在 FileShare-Services/Endpoints/AppEndpoints.cs。 /// public static IServiceCollection AddUnifiedApiServices(this IServiceCollection services, IConfiguration configuration) { // ---- 数据库 ---- // 从 appsettings.json 读取 DatabaseConfiguration 节 // 注册默认数据库提供程序(SQLite / MySQL / PostgreSQL / SqlServer) DatabaseProviderRegistry.RegisterDefaults(); var databaseConfig = configuration .GetSection(nameof(DatabaseConfiguration)) .Get() ?? DatabaseConfiguration.ForSQLite("app.db"); // 注册 AppDataContext(共享数据上下文) services.AddAppDatabase(databaseConfig); // ---- 业务服务 ---- services.AddScoped(); var thumbnailOptions = configuration .GetSection(nameof(ThumbnailStorageOptions)) .Get() ?? new ThumbnailStorageOptions(); services.AddSingleton(thumbnailOptions); services.AddSingleton(sp => new VideoThumbnailService(sp.GetRequiredService())); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.Configure(configuration.GetSection(nameof(FileLibraryScanOptions))); services.AddHostedService(); services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data-protection-keys"))); // ---- API 鉴权 ---- var jwtSection = configuration.GetSection("Jwt"); services.Configure(jwtSection); var jwtOptions = jwtSection.Get() ?? new JwtOptions(); services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtOptions.Issuer, ValidAudience = jwtOptions.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SigningKey)), ClockSkew = TimeSpan.FromMinutes(1), }; }); services.AddAuthorization(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // ---- 统一端点 ---- var endpointBuilder = new ServiceEndpointBuilder(); AppEndpoints.Configure(endpointBuilder); AuthEndpoints.ConfigureApi(endpointBuilder); var endpoints = endpointBuilder.Build(); services.AddSingleton(endpoints); return services; } } }