Clean architecture solution with: - Domain: Entities (User, CVCheck, CVFlag, CompanyCache) and Enums - Application: Service interfaces, DTOs, and models - Infrastructure: EF Core, Identity, Hangfire, external API clients, services - Web: Blazor Server UI with pages and components Features: - CV upload and parsing (PDF/DOCX) using Claude API - Employment verification against Companies House API - Timeline analysis for gaps and overlaps - Veracity scoring algorithm - Background job processing with Hangfire - Azure Blob Storage for file storage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
109 lines
3.2 KiB
C#
109 lines
3.2 KiB
C#
using Hangfire;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Serilog;
|
|
using TrueCV.Infrastructure;
|
|
using TrueCV.Infrastructure.Data;
|
|
using TrueCV.Infrastructure.Identity;
|
|
using TrueCV.Web;
|
|
using TrueCV.Web.Components;
|
|
|
|
// Configure Serilog
|
|
Log.Logger = new LoggerConfiguration()
|
|
.WriteTo.Console()
|
|
.CreateBootstrapLogger();
|
|
|
|
try
|
|
{
|
|
Log.Information("Starting TrueCV web application");
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Configure Serilog from appsettings
|
|
builder.Host.UseSerilog((context, services, configuration) => configuration
|
|
.ReadFrom.Configuration(context.Configuration)
|
|
.ReadFrom.Services(services)
|
|
.Enrich.FromLogContext());
|
|
|
|
// Add services to the container.
|
|
builder.Services.AddRazorComponents()
|
|
.AddInteractiveServerComponents();
|
|
|
|
// Add Infrastructure services (DbContext, Hangfire, HttpClients, Services)
|
|
builder.Services.AddInfrastructure(builder.Configuration);
|
|
|
|
// Add Identity
|
|
builder.Services.AddIdentity<ApplicationUser, IdentityRole<Guid>>(options =>
|
|
{
|
|
options.Password.RequireDigit = false;
|
|
options.Password.RequireLowercase = false;
|
|
options.Password.RequireUppercase = false;
|
|
options.Password.RequireNonAlphanumeric = false;
|
|
options.Password.RequiredLength = 6;
|
|
options.SignIn.RequireConfirmedAccount = false;
|
|
})
|
|
.AddEntityFrameworkStores<ApplicationDbContext>()
|
|
.AddDefaultTokenProviders();
|
|
|
|
builder.Services.ConfigureApplicationCookie(options =>
|
|
{
|
|
options.LoginPath = "/account/login";
|
|
options.LogoutPath = "/account/logout";
|
|
options.AccessDeniedPath = "/account/login";
|
|
});
|
|
|
|
// Add Cascading Authentication State
|
|
builder.Services.AddCascadingAuthenticationState();
|
|
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<ApplicationUser>>();
|
|
|
|
var app = builder.Build();
|
|
|
|
// Configure the HTTP request pipeline.
|
|
if (!app.Environment.IsDevelopment())
|
|
{
|
|
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
|
app.UseHsts();
|
|
}
|
|
|
|
app.UseHttpsRedirection();
|
|
|
|
app.UseStaticFiles();
|
|
app.UseAntiforgery();
|
|
|
|
// Add Serilog request logging
|
|
app.UseSerilogRequestLogging();
|
|
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
|
|
// Add Hangfire Dashboard (only in development)
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.UseHangfireDashboard("/hangfire", new DashboardOptions
|
|
{
|
|
Authorization = [] // Allow anonymous access in development
|
|
});
|
|
}
|
|
|
|
// Logout endpoint
|
|
app.MapPost("/account/logout", async (SignInManager<ApplicationUser> signInManager) =>
|
|
{
|
|
await signInManager.SignOutAsync();
|
|
return Results.Redirect("/");
|
|
}).RequireAuthorization();
|
|
|
|
app.MapRazorComponents<App>()
|
|
.AddInteractiveServerRenderMode();
|
|
|
|
app.Run();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Fatal(ex, "Application terminated unexpectedly");
|
|
}
|
|
finally
|
|
{
|
|
Log.CloseAndFlush();
|
|
}
|