chore: init project
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using System.Security.Claims;
|
||||
using Asp.Versioning;
|
||||
using InboxIntel.Api.Auth;
|
||||
using InboxIntel.Application;
|
||||
using InboxIntel.Application.Abstractions;
|
||||
using InboxIntel.Infrastructure;
|
||||
using InboxIntel.Infrastructure.Configuration;
|
||||
using InboxIntel.Infrastructure.Persistence;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.Google;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Serilog;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Structured logging (Serilog). Note: token values are never logged.
|
||||
builder.Host.UseSerilog((ctx, cfg) => cfg
|
||||
.ReadFrom.Configuration(ctx.Configuration)
|
||||
.Enrich.FromLogContext()
|
||||
.WriteTo.Console());
|
||||
|
||||
// Persist Data Protection keys so encrypted refresh tokens survive restarts.
|
||||
builder.Services.AddDataProtection()
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(builder.Configuration["DataProtection:KeyPath"] ?? "/keys"))
|
||||
.SetApplicationName("InboxIntel");
|
||||
|
||||
builder.Services.AddApplication();
|
||||
builder.Services.AddInfrastructure(builder.Configuration);
|
||||
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddScoped<ICurrentUser, CurrentUser>();
|
||||
|
||||
// Authentication: cookie session established via Google OAuth2 (only login method).
|
||||
var google = builder.Configuration.GetSection(GoogleOAuthOptions.SectionName).Get<GoogleOAuthOptions>() ?? new();
|
||||
builder.Services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie(options =>
|
||||
{
|
||||
options.Cookie.HttpOnly = true;
|
||||
options.Cookie.SameSite = SameSiteMode.Lax;
|
||||
options.ExpireTimeSpan = TimeSpan.FromDays(7);
|
||||
})
|
||||
.AddGoogle(options =>
|
||||
{
|
||||
options.ClientId = google.ClientId;
|
||||
options.ClientSecret = google.ClientSecret;
|
||||
options.AccessType = "offline"; // request a refresh token
|
||||
options.SaveTokens = true;
|
||||
foreach (var scope in google.Scopes) options.Scope.Add(scope);
|
||||
options.Events.OnCreatingTicket = GoogleAuthEvents.OnCreatingTicketAsync;
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
|
||||
builder.Services.AddApiVersioning(o =>
|
||||
{
|
||||
o.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
o.AssumeDefaultVersionWhenUnspecified = true;
|
||||
o.ReportApiVersions = true;
|
||||
o.ApiVersionReader = new UrlSegmentApiVersionReader();
|
||||
}).AddApiExplorer(o => { o.GroupNameFormat = "'v'VVV"; o.SubstituteApiVersionInUrl = true; });
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
builder.Services.AddCors(o => o.AddPolicy("frontend", p => p
|
||||
.WithOrigins(builder.Configuration.GetSection("Cors:Origins").Get<string[]>() ?? new[] { "http://localhost:5173" })
|
||||
.AllowAnyHeader().AllowAnyMethod().AllowCredentials()));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Apply migrations on startup so `docker-compose up` yields a ready schema.
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
if (db.Database.IsRelational() && app.Configuration.GetValue("Database:AutoMigrate", true))
|
||||
await db.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseSerilogRequestLogging();
|
||||
app.UseCors("frontend");
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
|
||||
public partial class Program { }
|
||||
Reference in New Issue
Block a user