using System.Net;
using System.Text;
using FozFc.Api.Application.Auth;
using FozFc.Api.Application.Progress;
using FozFc.Api.Application.Seeding;
using FozFc.Api.Application.Zerozero;
using FozFc.Api.Configuration;
using FozFc.Api.Infrastructure.Mongo;
using FozFc.Api.Infrastructure.Security;
using FozFc.Api.Infrastructure.Storage;
using FozFc.Api.Infrastructure.Zerozero;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
namespace FozFc.Api.Api;
/// Composition root: registers all services, authentication and CORS.
public static class DependencyInjection
{
public static IServiceCollection AddFozFcServices(this IServiceCollection services, AppOptions options)
{
services.AddSingleton(options);
// Infrastructure
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddHttpClient();
services.AddSingleton();
services.AddSingleton();
// Application
services.AddSingleton();
services.AddSingleton();
services.AddTransient();
// ZeroZero football feeds (scrapes zerozero.pt; replaces the Cloudflare worker)
services.AddMemoryCache();
services.AddHttpClient("zerozero", client => client.Timeout = TimeSpan.FromSeconds(20))
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.All,
AllowAutoRedirect = true,
});
services.AddSingleton();
services.AddSingleton();
return services;
}
public static IServiceCollection AddFozFcAuth(this IServiceCollection services, AppOptions options)
{
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(options.JwtSecret));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwt =>
{
jwt.RequireHttpsMetadata = false;
jwt.MapInboundClaims = false; // keep raw "uid"/"role" claim names
jwt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = AppOptions.JwtIssuer,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ClockSkew = TimeSpan.FromMinutes(1),
NameClaimType = JwtClaims.Uid,
RoleClaimType = JwtClaims.Role,
};
});
services.AddAuthorization();
return services;
}
public static IServiceCollection AddFozFcCors(this IServiceCollection services, AppOptions options)
{
services.AddCors(cors => cors.AddDefaultPolicy(policy =>
policy.WithOrigins(options.CorsOrigins)
.AllowAnyHeader()
.AllowAnyMethod()));
return services;
}
}