using System.Globalization; using System.Text.Json; using System.Threading.RateLimiting; using DysonNetwork.Pass.Account; using DysonNetwork.Pass.Auth; using DysonNetwork.Pass.Auth.OidcProvider.Options; using DysonNetwork.Pass.Auth.OidcProvider.Services; using DysonNetwork.Pass.Auth.OpenId; using DysonNetwork.Pass.Localization; using DysonNetwork.Pass.Permission; using DysonNetwork.Shared.Cache; using DysonNetwork.Shared.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.RateLimiting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using NodaTime; using NodaTime.Serialization.SystemTextJson; using StackExchange.Redis; namespace DysonNetwork.Pass.Startup; public static class ServiceCollectionExtensions { public static IServiceCollection AddAppServices(this IServiceCollection services, IConfiguration configuration) { services.AddLocalization(options => options.ResourcesPath = "Resources"); services.AddDbContext(); services.AddSingleton(_ => { var connection = configuration.GetConnectionString("FastRetrieve")!; return ConnectionMultiplexer.Connect(connection); }); services.AddSingleton(SystemClock.Instance); services.AddHttpContextAccessor(); services.AddSingleton(); services.AddHttpClient(); // Register MagicOnion services services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // Register OIDC services services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.SnakeCaseLower; options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); }).AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource)); }); services.AddRazorPages(); services.Configure(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("zh-Hans"), }; options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); return services; } public static IServiceCollection AddAppRateLimiting(this IServiceCollection services) { services.AddRateLimiter(o => o.AddFixedWindowLimiter(policyName: "fixed", opts => { opts.Window = TimeSpan.FromMinutes(1); opts.PermitLimit = 120; opts.QueueLimit = 2; opts.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; })); return services; } public static IServiceCollection AddAppAuthentication(this IServiceCollection services) { services.AddCors(); services.AddAuthorization(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = AuthConstants.SchemeName; options.DefaultChallengeScheme = AuthConstants.SchemeName; }) .AddScheme(AuthConstants.SchemeName, _ => { }); return services; } public static IServiceCollection AddAppSwagger(this IServiceCollection services) { services.AddEndpointsApiExplorer(); services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "Solar Network API", Description = "An open-source social network", TermsOfService = new Uri("https://solsynth.dev/terms"), License = new OpenApiLicense { Name = "APGLv3", Url = new Uri("https://www.gnu.org/licenses/agpl-3.0.html") } }); options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Please enter a valid token", Name = "Authorization", Type = SecuritySchemeType.Http, BearerFormat = "JWT", Scheme = "Bearer" }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, [] } }); }); services.AddOpenApi(); return services; } public static IServiceCollection AddAppBusinessServices(this IServiceCollection services, IConfiguration configuration) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.Configure(configuration.GetSection("OidcProvider")); services.AddScoped(); return services; } }