Files
jsmr/JSMR.Api/Startup/ServiceCollectionExtensions.cs
Brian Bicknell ab3524ea20
Some checks failed
ci / build-test (push) Has been cancelled
ci / publish-image (push) Has been cancelled
Added docker-compose. Updated startups for API and Web layer.
2026-02-24 00:25:03 -05:00

130 lines
4.4 KiB
C#

using JSMR.Application.DI;
using JSMR.Infrastructure.Data;
using JSMR.Infrastructure.DI;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JSMR.Api.Startup;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddAppServices(this IServiceCollection services, IConfigurationManager configuration)
{
services
.AddMemoryCache()
.AddApplication()
.AddInfrastructure();
string connectionString = configuration.GetConnectionString("AppDb")
?? throw new InvalidOperationException("Missing ConnectionStrings:AppDb");
services.AddDbContextFactory<AppDbContext>(opt =>
opt.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
.EnableSensitiveDataLogging(false));
services.AddControllers();
return services;
}
public static IServiceCollection AddAppJson(this IServiceCollection services)
{
services.Configure<JsonOptions>(options =>
{
options.SerializerOptions.PropertyNameCaseInsensitive = true;
options.SerializerOptions.Converters.Add(
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
});
return services;
}
public static IServiceCollection AddAppOpenApi(this IServiceCollection services)
{
services.AddOpenApi();
return services;
}
public static IServiceCollection AddAppAuthentication(this IServiceCollection services, IHostEnvironment environment)
{
services.AddAuthorization();
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "vw_auth";
options.Cookie.HttpOnly = true;
//options.Cookie.SameSite = SameSiteMode.None;
//options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy =
environment.IsDevelopment()
? CookieSecurePolicy.SameAsRequest
: CookieSecurePolicy.Always;
options.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = ctx =>
{
ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
},
OnRedirectToAccessDenied = ctx =>
{
ctx.Response.StatusCode = StatusCodes.Status403Forbidden;
return Task.CompletedTask;
}
};
});
return services;
}
public static IServiceCollection AddAppCors(this IServiceCollection services, IConfigurationManager configuration)
{
string[] origins = configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? [];
services.AddCors(options =>
{
options.AddPolicy("ui", policyBuilder =>
{
if (origins.Length == 0)
{
// In container/prod you often don't need CORS at all (same-origin),
// but if it *is* needed and not configured, fail closed rather than crash.
// Do not call WithOrigins().
return;
}
policyBuilder.WithOrigins(origins)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
return services;
}
//public static IServiceCollection AddAppLogging(this IServiceCollection services, IHostApplicationBuilder builder)
//{
// var config = builder.Configuration;
// var env = builder.Environment;
// Log.Logger = new LoggerConfiguration()
// .ReadFrom.Configuration(config)
// .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
// .Enrich.WithProperty("Service", "JSMR.Api")
// .Enrich.WithProperty("Environment", env.EnvironmentName)
// .CreateLogger();
// return services;
//}
}