Sfoglia il codice sorgente

Split application configuration into separate modules

Lukas Angerer 3 anni fa
parent
commit
22c2478477

+ 18 - 0
src/RunnersMeet.Server/ApiControllersModule.cs

@@ -0,0 +1,18 @@
+namespace RunnersMeet.Server;
+
+public class ApiControllersModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+		services.AddControllers().AddJsonOptions(options =>
+		{
+			options.JsonSerializerOptions.Converters.Add(new ObjectIdConverter());
+		});
+		services.Configure<ApiSettings>(config.GetSection(ApiSettings.SectionName));
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+		app.MapControllers();
+	}
+}

+ 18 - 68
src/RunnersMeet.Server/AppServer.cs

@@ -1,89 +1,39 @@
-using Microsoft.AspNetCore.Authentication.JwtBearer;
-using Microsoft.AspNetCore.StaticFiles.Infrastructure;
-using Microsoft.IdentityModel.Tokens;
+using RunnersMeet.Server.Domain;
 using RunnersMeet.Server.Frontend;
-using RunnersMeet.Server.GpxFormat;
 using RunnersMeet.Server.Persistence;
 
 namespace RunnersMeet.Server;
 
 public class AppServer
 {
+	private readonly IList<IAppConfigurationModule> _modules = new List<IAppConfigurationModule>
+	{
+		new AuthenticationModule(),
+		new CorsModule(),
+		new SpaRoutingModule(),
+		new ApiControllersModule(),
+		new SwaggerModule(),
+		new PersistenceModule(),
+		new DomainServicesModule(),
+	};
+
 	public void Start(string[] args)
 	{
 		var builder = WebApplication.CreateBuilder(args);
 
-		ConfigureServices(builder.Services, builder.Configuration);
-		builder.Services.AddControllers().AddJsonOptions(options =>
+		foreach (var appConfigurationModule in _modules)
 		{
-			options.JsonSerializerOptions.Converters.Add(new ObjectIdConverter());
-		});
-		// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
-		builder.Services.AddEndpointsApiExplorer();
-		builder.Services.AddSwaggerGen();
-
-		builder.Services.AddCors(options =>
-		{
-			options.AddDefaultPolicy(policy  =>
-			{
-				policy.WithOrigins("http://localhost:4200", "https://gpx.studio");
-				policy.WithHeaders("Authorization", "Content-Type");
-				policy.AllowAnyMethod();
-				policy.WithExposedHeaders("Content-Disposition");
-			});
-		});
-
-		var authOptions = new AuthOptions();
-		builder.Configuration.GetSection("Auth").Bind(authOptions);
-		builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
-			.AddJwtBearer(options =>
-			{
-				options.Authority = authOptions.Authority;
-				options.TokenValidationParameters = new TokenValidationParameters
-				{
-					ValidIssuer = authOptions.Authority,
-					ValidAudience = authOptions.Audience
-				};
-			});
-
-		builder.Services.AddAuthorization(authorizationOptions =>
-		{
-			foreach (var policyPair in authOptions.PolicyClaims)
-			{
-				authorizationOptions.AddPolicy(policyPair.Key, policyBuilder => policyBuilder.RequireClaim("permissions", policyPair.Value));
-			}
-		});
+			appConfigurationModule.ConfigureServices(builder.Services, builder.Configuration);
+		}
 
 		var app = builder.Build();
+		app.UseHttpsRedirection();
 
-		// Configure the HTTP request pipeline.
-		if (app.Environment.IsDevelopment())
+		foreach (var appConfigurationModule in _modules)
 		{
-			app.UseSwagger();
-			app.UseSwaggerUI();
+			appConfigurationModule.ConfigureApplication(app);
 		}
 
-		app.UseHttpsRedirection();
-		app.UseCors();
-		app.UseAuthorization();
-		app.UseSpaDefaultPageMiddleware();
-		app.UseStaticFiles();
-		app.MapControllers();
-
-
 		app.Run();
 	}
-
-	private void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
-	{
-		services.AddSingleton<IDatabase, Database>();
-		services.AddSingleton<IFileStorage, FileStorage>();
-		services.AddScoped<QueryFactory, QueryFactory>();
-
-		services.AddSingleton<GpxParser>();
-
-		services.Configure<PersistenceOptions>(config.GetSection(PersistenceOptions.SectionName));
-		services.AddTransient<IPersistenceOptions, PersistenceOptionsAccessor>();
-		services.Configure<ApiSettings>(config.GetSection(ApiSettings.SectionName));
-	}
 }

+ 37 - 0
src/RunnersMeet.Server/AuthenticationModule.cs

@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.IdentityModel.Tokens;
+
+namespace RunnersMeet.Server;
+
+public class AuthenticationModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+		var authOptions = new AuthOptions();
+		config.GetSection("Auth").Bind(authOptions);
+		services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+			.AddJwtBearer(options =>
+			{
+				options.Authority = authOptions.Authority;
+				options.TokenValidationParameters = new TokenValidationParameters
+				{
+					ValidIssuer = authOptions.Authority,
+					ValidAudience = authOptions.Audience
+				};
+			});
+
+		services.AddAuthorization(authorizationOptions =>
+		{
+			foreach (var policyPair in authOptions.PolicyClaims)
+			{
+				authorizationOptions.AddPolicy(policyPair.Key,
+					policyBuilder => policyBuilder.RequireClaim("permissions", policyPair.Value));
+			}
+		});
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+		app.UseAuthorization();
+	}
+}

+ 23 - 0
src/RunnersMeet.Server/CorsModule.cs

@@ -0,0 +1,23 @@
+namespace RunnersMeet.Server;
+
+public class CorsModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+		services.AddCors(options =>
+		{
+			options.AddDefaultPolicy(policy =>
+			{
+				policy.WithOrigins("http://localhost:4200", "https://gpx.studio");
+				policy.WithHeaders("Authorization", "Content-Type");
+				policy.AllowAnyMethod();
+				policy.WithExposedHeaders("Content-Disposition");
+			});
+		});
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+		app.UseCors();
+	}
+}

+ 15 - 0
src/RunnersMeet.Server/Domain/DomainServicesModule.cs

@@ -0,0 +1,15 @@
+using RunnersMeet.Server.GpxFormat;
+
+namespace RunnersMeet.Server.Domain;
+
+public class DomainServicesModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+		services.AddSingleton<GpxParser>();
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+	}
+}

+ 0 - 9
src/RunnersMeet.Server/Frontend/SpaDefaultPageMiddlewareExtensions.cs

@@ -1,9 +0,0 @@
-namespace RunnersMeet.Server.Frontend;
-
-public static class SpaDefaultPageMiddlewareExtensions
-{
-	public static IApplicationBuilder UseSpaDefaultPageMiddleware(this IApplicationBuilder builder)
-	{
-		return builder.UseMiddleware<SpaDefaultPageMiddleware>();
-	}
-}

+ 16 - 0
src/RunnersMeet.Server/Frontend/SpaRoutingModule.cs

@@ -0,0 +1,16 @@
+using RunnersMeet.Server.Frontend;
+
+namespace RunnersMeet.Server.Frontend;
+
+public class SpaRoutingModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+		app.UseMiddleware<SpaDefaultPageMiddleware>();
+		app.UseStaticFiles();
+	}
+}

+ 7 - 0
src/RunnersMeet.Server/IAppConfigurationModule.cs

@@ -0,0 +1,7 @@
+namespace RunnersMeet.Server;
+
+public interface IAppConfigurationModule
+{
+	void ConfigureServices(IServiceCollection services, IConfigurationRoot config);
+	void ConfigureApplication(WebApplication app);
+}

+ 18 - 0
src/RunnersMeet.Server/Persistence/PersistenceModule.cs

@@ -0,0 +1,18 @@
+namespace RunnersMeet.Server.Persistence;
+
+public class PersistenceModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+		services.Configure<PersistenceOptions>(config.GetSection(PersistenceOptions.SectionName));
+		services.AddTransient<IPersistenceOptions, PersistenceOptionsAccessor>();
+
+		services.AddSingleton<IDatabase, Database>();
+		services.AddSingleton<IFileStorage, FileStorage>();
+		services.AddScoped<QueryFactory, QueryFactory>();
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+	}
+}

+ 20 - 0
src/RunnersMeet.Server/SwaggerModule.cs

@@ -0,0 +1,20 @@
+namespace RunnersMeet.Server;
+
+public class SwaggerModule : IAppConfigurationModule
+{
+	public void ConfigureServices(IServiceCollection services, IConfigurationRoot config)
+	{
+		// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+		services.AddEndpointsApiExplorer();
+		services.AddSwaggerGen();
+	}
+
+	public void ConfigureApplication(WebApplication app)
+	{
+		if (app.Environment.IsDevelopment())
+		{
+			app.UseSwagger();
+			app.UseSwaggerUI();
+		}
+	}
+}