profileShare

rasmusjy / splitapp-backend-microservices

Read-only snapshot

No repository description.

main default branch 501 files Expires Sep 13, 2026, 9:06 AM
Program.cs 3,202 bytes
1 using Asp.Versioning;
2 using Asp.Versioning.ApiExplorer;
3 using Microsoft.Extensions.Options;
4 using SplitApp.Modules.Users.Api.Controllers;
5 using SplitApp.Modules.Users.Infrastructure;
6 using SplitApp.Shared.Contracts.Users;
7 using SplitApp.Shared.Messaging;
8 using SplitApp.Shared.Messaging.Integration.Users;
9 using SplitApp.UsersService.Hosting;
10 using SplitApp.UsersService.Messaging;
11 using Swashbuckle.AspNetCore.SwaggerGen;
12
13 var builder = WebApplication.CreateBuilder(args);
14
15 builder.Services
16 .AddControllers()
17 .AddApplicationPart(typeof(AccountController).Assembly);
18
19 builder.Services.AddApiVersioning(options =>
20 {
21 options.ReportApiVersions = true;
22 options.DefaultApiVersion = new ApiVersion(1, 0);
23 options.AssumeDefaultVersionWhenUnspecified = true;
24 options.ApiVersionReader = new UrlSegmentApiVersionReader();
25 }).AddApiExplorer(options =>
26 {
27 options.GroupNameFormat = "'v'VVV";
28 options.SubstituteApiVersionInUrl = true;
29 });
30
31 builder.Services.AddEndpointsApiExplorer();
32 builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
33 builder.Services.AddSwaggerGen();
34
35 // Users module (Identity + JWT + EF + repos) — reused verbatim from the modular monolith.
36 builder.Services.AddUsersModule(builder.Configuration);
37
38 builder.Services.AddAuthorization();
39
40 // CORS — same wide-open policy as the WebApp, so external SPA frontends (Vite/Vue)
41 // can call /api/v1/identity/* directly without proxy gymnastics. The login response
42 // returns the JWT as JSON; SPAs store it in localStorage and send it on subsequent
43 // requests via `Authorization: Bearer ...`, so cross-subdomain cookie issues don't apply.
44 builder.Services.AddCors(options =>
45 {
46 options.AddPolicy("CorsAllowAll", policy =>
47 {
48 policy
49 .AllowAnyOrigin()
50 .AllowAnyHeader()
51 .AllowAnyMethod()
52 .WithExposedHeaders("X-Version", "X-Version-Created-At");
53 });
54 });
55
56 // Messaging: this process advertises serviceName "users-service" in queue names.
57 builder.Services.AddMessaging(builder.Configuration, serviceName: "users-service");
58 builder.Services.AddIntegrationRequestHandler<GetUserByIdRequest, UserDto?, GetUserByIdRequestHandler>();
59 builder.Services.AddIntegrationRequestHandler<GetUsersByIdsRequest, UserDto[], GetUsersByIdsRequestHandler>();
60
61 builder.Services.AddSingleton<SeededHealthState>();
62
63 var app = builder.Build();
64
65 // Run migrations + seed roles/users. The compose healthcheck polls /health until this flips.
66 app.UseUsersModule();
67 app.Services.GetRequiredService<SeededHealthState>().MarkSeeded();
68
69 if (app.Environment.IsDevelopment())
70 {
71 app.UseDeveloperExceptionPage();
72 }
73
74 app.UseSwagger();
75 app.UseSwaggerUI(options =>
76 {
77 var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
78 foreach (var description in provider.ApiVersionDescriptions)
79 {
80 options.SwaggerEndpoint(
81 $"/swagger/{description.GroupName}/swagger.json",
82 description.GroupName.ToUpperInvariant());
83 }
84 });
85
86 app.UseRouting();
87 app.UseCors("CorsAllowAll");
88 app.UseAuthentication();
89 app.UseAuthorization();
90 app.MapControllers();
91
92 app.Run();
93
94 public partial class Program;
95