using Books.Api; using Books.Api.Authorization; using Books.Api.GraphQL; using GraphQL; using GraphQL.Server.Ui.Altair; using Hangfire; // Enable legacy timestamp behavior for Npgsql 6.0+ // This allows DateTimeOffset with non-UTC offsets to be written to timestamptz columns AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); var builder = WebApplication.CreateBuilder(args); // Configure EventFlow, Hangfire, GraphQL and all services Startup.ConfigureServices(builder.Services, builder.Configuration, builder.Environment); var app = builder.Build(); // Configure the HTTP request pipeline if (app.Environment.IsDevelopment()) { app.UseHangfireDashboard(); } app.UseHttpsRedirection(); // CORS must come before auth app.UseCors(); // Authentication & Authorization app.UseAuthentication(); app.UseAuthorization(); // Company context middleware - extracts X-Company-Id header and validates user access app.UseCompanyContext(); // Require authentication for the GraphQL endpoint app.UseWhen( context => context.Request.Path.StartsWithSegments("/graphql"), appBuilder => appBuilder.Use(async (context, next) => { if (context.User.Identity?.IsAuthenticated != true) { context.Response.StatusCode = 401; context.Response.ContentType = "application/json"; await context.Response.WriteAsync("{\"errors\":[{\"message\":\"Authentication required\"}]}"); return; } await next(); }) ); // Map controllers (for AuthController) app.MapControllers(); // GraphQL endpoint app.UseGraphQL("/graphql"); // GraphQL UI (development only) - use external tools like Altair, Insomnia, or GraphiQL if (app.Environment.IsDevelopment()) { app.UseGraphQLAltair("/graphql/ui"); } app.Run();