using Azure.Identity; using FastEndpoints; using FastEndpoints.Swagger; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Options; using Socialize; using Socialize.Api.Infrastructure.BlobStorage.Configuration; using Socialize.Api.Infrastructure.BlobStorage.Services; using Socialize.Api.Infrastructure; using Socialize.Api.Infrastructure.Development; using Socialize.Api.Modules.Approvals; using Socialize.Api.Modules.Assets; using Socialize.Api.Modules.Clients; using Socialize.Api.Modules.Comments; using Socialize.Api.Modules.ContentItems; using Socialize.Api.Modules.Identity; using Socialize.Api.Modules.Notifications; using Socialize.Api.Modules.Projects; using Socialize.Api.Modules.Workspaces; var builder = WebApplication.CreateBuilder(args); if (!builder.Environment.IsDevelopment()) { var vaultUri = Environment.GetEnvironmentVariable("VaultUri") ?? throw new InvalidOperationException("Missing VaultUri configuration setting"); builder.Configuration.AddAzureKeyVault(new Uri(vaultUri), new DefaultAzureCredential()); } builder.Services.AddCors(options => options.AddPolicy( "AllowAll", policy => policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() ) ); // Add services to the container. builder.Services.AddWebServices(); builder.Services.AddAuthorizationAndAuthentication(builder.Configuration); builder.Services.AddFastEndpoints(); builder.Services.SwaggerDocument(o => { o.EnableGetRequestsWithBody = false; o.EnableJWTBearerAuth = true; o.DocumentSettings = s => { s.Title = "Socialize API"; s.Version = "v1"; }; }); var postgresConnectionString = builder.Configuration.GetConnectionString("PostgresConnection") ?? throw new InvalidOperationException( "Missing ConnectionStrings:PostgresConnection"); builder.Services.AddAppData(postgresConnectionString); builder.AddInfrastructureModule(); builder.AddIdentityModule(); builder.AddWorkspaceModule(); builder.AddClientsModule(); builder.AddProjectsModule(); builder.AddContentItemsModule(); builder.AddAssetsModule(); builder.AddCommentsModule(); builder.AddApprovalsModule(); builder.AddNotificationsModule(); var app = builder.Build(); app.UseForwardedHeaders( new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto } ); app.UseCors("AllowAll"); app.UseAuthentication(); app.UseAuthorization(); // Initialize and seed the db. await app.UseAppDataAsync(); await app.UseIdentityModuleAsync(); await app.UseDevelopmentSeedAsync(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { // 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.UseHealthChecks("/health"); LocalBlobStorageOptions localBlobStorageOptions = app.Services .GetRequiredService>() .Value; string localBlobStorageRoot = app.Services .GetRequiredService() .GetRootPath(); string localBlobStorageRootWithSeparator = Path.EndsInDirectorySeparator(localBlobStorageRoot) ? localBlobStorageRoot : $"{localBlobStorageRoot}{Path.DirectorySeparatorChar}"; Directory.CreateDirectory(localBlobStorageRoot); app.MapGet( $"{LocalBlobStorage.NormalizeRequestPath(localBlobStorageOptions.RequestPath)}/{{**blobPath}}", async ( string blobPath, CancellationToken ct) => { string filePath = Path.GetFullPath(Path.Combine(localBlobStorageRoot, blobPath)); if (!filePath.StartsWith(localBlobStorageRootWithSeparator, StringComparison.Ordinal) || filePath.EndsWith(".content-type", StringComparison.OrdinalIgnoreCase) || !File.Exists(filePath)) { return Results.NotFound(); } string contentType = LocalBlobStorage.ReadContentType(filePath) ?? "application/octet-stream"; byte[] bytes = await File.ReadAllBytesAsync(filePath, ct); return Results.File(bytes, contentType); }); if (!app.Environment.IsDevelopment()) { app.UseHttpsRedirection(); } app.UseFastEndpoints(); app.UseSwaggerGen(); await app.RunAsync();