diff --git a/Directory.Build.targets b/Directory.Build.targets index 058a4e87..b1dedc3e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -16,10 +16,6 @@ - - - - diff --git a/Directory.Packages.props b/Directory.Packages.props index 90878b36..7dc54e04 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,11 +2,10 @@ true true - 8.0.0 - 8.0.0 + 8.0.1 + 8.1.0 8.0.0 - 8.0.0 - 8.0.0-preview.2.23619.3 + 8.0.0-preview.3.24105.21 2.59.0 @@ -38,9 +37,9 @@ - - - + + + @@ -50,7 +49,6 @@ - diff --git a/src/Basket.API/Extensions/Extensions.cs b/src/Basket.API/Extensions/Extensions.cs index 488e07c4..0023fa47 100644 --- a/src/Basket.API/Extensions/Extensions.cs +++ b/src/Basket.API/Extensions/Extensions.cs @@ -15,7 +15,7 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder) builder.Services.AddSingleton(); - builder.AddRabbitMqEventBus("EventBus") + builder.AddRabbitMqEventBus("eventbus") .AddSubscription() .ConfigureJsonOptions(options => options.TypeInfoResolverChain.Add(IntegrationEventContext.Default)); } diff --git a/src/Catalog.API/Apis/CatalogApi.cs b/src/Catalog.API/Apis/CatalogApi.cs index 23f5827b..68659104 100644 --- a/src/Catalog.API/Apis/CatalogApi.cs +++ b/src/Catalog.API/Apis/CatalogApi.cs @@ -47,8 +47,6 @@ public static async Task>, BadRequest(pageIndex, pageSize, totalItems, itemsOnPage)); } @@ -57,7 +55,6 @@ public static async Task>> GetItemsByIds( int[] ids) { var items = await services.Context.CatalogItems.Where(item => ids.Contains(item.Id)).ToListAsync(); - items = ChangeUriPlaceholder(services.Options.Value, items); return TypedResults.Ok(items); } @@ -77,7 +74,6 @@ public static async Task, NotFound, BadRequest>> return TypedResults.NotFound(); } - item.PictureUri = services.Options.Value.PicBaseUrl.Replace("[0]", item.Id.ToString()); return TypedResults.Ok(item); } @@ -99,8 +95,6 @@ public static async Task>> GetItemsByName( .Take(pageSize) .ToListAsync(); - itemsOnPage = ChangeUriPlaceholder(services.Options.Value, itemsOnPage); - return TypedResults.Ok(new PaginatedItems(pageIndex, pageSize, totalItems, itemsOnPage)); } @@ -166,8 +160,6 @@ public static async Task, RedirectToRouteHttpResult, .ToListAsync(); } - itemsOnPage = ChangeUriPlaceholder(services.Options.Value, itemsOnPage); - return TypedResults.Ok(new PaginatedItems(pageIndex, pageSize, totalItems, itemsOnPage)); } @@ -195,7 +187,6 @@ public static async Task>> GetItemsByBrandAndType .Take(pageSize) .ToListAsync(); - itemsOnPage = ChangeUriPlaceholder(services.Options.Value, itemsOnPage); return TypedResults.Ok(new PaginatedItems(pageIndex, pageSize, totalItems, itemsOnPage)); } @@ -222,7 +213,6 @@ public static async Task>> GetItemsByBrandId( .Take(pageSize) .ToListAsync(); - itemsOnPage = ChangeUriPlaceholder(services.Options.Value, itemsOnPage); return TypedResults.Ok(new PaginatedItems(pageIndex, pageSize, totalItems, itemsOnPage)); } @@ -305,16 +295,6 @@ public static async Task> DeleteItemById( return TypedResults.NoContent(); } - private static List ChangeUriPlaceholder(CatalogOptions options, List items) - { - foreach (var item in items) - { - item.PictureUri = options.PicBaseUrl.Replace("[0]", item.Id.ToString()); - } - - return items; - } - private static string GetImageMimeTypeFromImageFileExtension(string extension) => extension switch { ".png" => "image/png", diff --git a/src/Catalog.API/Catalog.API.csproj b/src/Catalog.API/Catalog.API.csproj index 55873319..bfa7d515 100644 --- a/src/Catalog.API/Catalog.API.csproj +++ b/src/Catalog.API/Catalog.API.csproj @@ -31,6 +31,9 @@ + + + diff --git a/src/Catalog.API/Extensions/Extensions.cs b/src/Catalog.API/Extensions/Extensions.cs index 8f885741..02149c84 100644 --- a/src/Catalog.API/Extensions/Extensions.cs +++ b/src/Catalog.API/Extensions/Extensions.cs @@ -4,7 +4,7 @@ public static class Extensions { public static void AddApplicationServices(this IHostApplicationBuilder builder) { - builder.AddNpgsqlDbContext("CatalogDB", configureDbContextOptions: dbContextOptionsBuilder => + builder.AddNpgsqlDbContext("catalogdb", configureDbContextOptions: dbContextOptionsBuilder => { dbContextOptionsBuilder.UseNpgsql(builder => { @@ -20,7 +20,7 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder) builder.Services.AddTransient(); - builder.AddRabbitMqEventBus("EventBus") + builder.AddRabbitMqEventBus("eventbus") .AddSubscription() .AddSubscription(); diff --git a/src/Catalog.API/appsettings.Development.json b/src/Catalog.API/appsettings.Development.json index 426254f1..56ab0b05 100644 --- a/src/Catalog.API/appsettings.Development.json +++ b/src/Catalog.API/appsettings.Development.json @@ -1,8 +1,5 @@ { "ConnectionStrings": { "CatalogDB": "Host=localhost;Database=CatalogDB;Username=postgres;Password=yourWeak(!)Password" - }, - "CatalogOptions": { - "PicBaseUrl": "http://localhost:5222/api/v1/catalog/items/[0]/pic/" } } \ No newline at end of file diff --git a/src/Identity.API/Identity.API.csproj b/src/Identity.API/Identity.API.csproj index 5a3b4f83..70d8a94c 100644 --- a/src/Identity.API/Identity.API.csproj +++ b/src/Identity.API/Identity.API.csproj @@ -46,6 +46,11 @@ + + + + + diff --git a/src/Identity.API/Program.cs b/src/Identity.API/Program.cs index 31f101fc..cfd578f6 100644 --- a/src/Identity.API/Program.cs +++ b/src/Identity.API/Program.cs @@ -4,7 +4,7 @@ builder.Services.AddControllersWithViews(); -builder.AddNpgsqlDbContext("IdentityDB"); +builder.AddNpgsqlDbContext("identitydb"); // Apply database migration automatically. Note that this approach is not // recommended for production scenarios. Consider generating SQL scripts from @@ -24,13 +24,17 @@ options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; + + // TODO: Remove this line in production. + options.KeyManagement.Enabled = false; }) .AddInMemoryIdentityResources(Config.GetResources()) .AddInMemoryApiScopes(Config.GetApiScopes()) .AddInMemoryApiResources(Config.GetApis()) .AddInMemoryClients(Config.GetClients(builder.Configuration)) .AddAspNetIdentity() -.AddDeveloperSigningCredential(); // Not recommended for production - you need to store your key material somewhere secure +// TODO: Not recommended for production - you need to store your key material somewhere secure +.AddDeveloperSigningCredential(); builder.Services.AddTransient(); builder.Services.AddTransient, EFLoginService>(); diff --git a/src/Identity.API/Properties/launchSettings.json b/src/Identity.API/Properties/launchSettings.json index 4976a7ad..5c176f33 100644 --- a/src/Identity.API/Properties/launchSettings.json +++ b/src/Identity.API/Properties/launchSettings.json @@ -7,6 +7,14 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5243;http://localhost:5223", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } } } } \ No newline at end of file diff --git a/src/Mobile.Bff.Shopping/Mobile.Bff.Shopping.csproj b/src/Mobile.Bff.Shopping/Mobile.Bff.Shopping.csproj index 8b71a2cb..81d91494 100644 --- a/src/Mobile.Bff.Shopping/Mobile.Bff.Shopping.csproj +++ b/src/Mobile.Bff.Shopping/Mobile.Bff.Shopping.csproj @@ -2,7 +2,6 @@ net8.0 - mobileshoppingagg diff --git a/src/Mobile.Bff.Shopping/Properties/launchSettings.json b/src/Mobile.Bff.Shopping/Properties/launchSettings.json index aa49e3a3..6fba4bfb 100644 --- a/src/Mobile.Bff.Shopping/Properties/launchSettings.json +++ b/src/Mobile.Bff.Shopping/Properties/launchSettings.json @@ -3,7 +3,7 @@ "http": { "commandName": "Project", "launchBrowser": true, - "applicationUrl": "http://localhost:61632/", + "applicationUrl": "http://localhost:11632/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/OrderProcessor/Extensions/Extensions.cs b/src/OrderProcessor/Extensions/Extensions.cs index 3bf762bf..7c6748a5 100644 --- a/src/OrderProcessor/Extensions/Extensions.cs +++ b/src/OrderProcessor/Extensions/Extensions.cs @@ -7,10 +7,10 @@ public static class Extensions { public static void AddApplicationServices(this IHostApplicationBuilder builder) { - builder.AddRabbitMqEventBus("EventBus") + builder.AddRabbitMqEventBus("eventbus") .ConfigureJsonOptions(options => options.TypeInfoResolverChain.Add(IntegrationEventContext.Default)); - builder.AddNpgsqlDataSource("OrderingDB"); + builder.AddNpgsqlDataSource("orderingdb"); builder.Services.AddOptions() .BindConfiguration(nameof(BackgroundTaskOptions)); diff --git a/src/Ordering.API/Extensions/Extensions.cs b/src/Ordering.API/Extensions/Extensions.cs index 12efcfdf..265bbb66 100644 --- a/src/Ordering.API/Extensions/Extensions.cs +++ b/src/Ordering.API/Extensions/Extensions.cs @@ -10,7 +10,7 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder) // Pooling is disabled because of the following error: // Unhandled exception. System.InvalidOperationException: // The DbContext of type 'OrderingContext' cannot be pooled because it does not have a public constructor accepting a single parameter of type DbContextOptions or has more than one constructor. - builder.AddNpgsqlDbContext("OrderingDB", settings => settings.DbContextPooling = false); + builder.AddNpgsqlDbContext("orderingdb", settings => settings.DbContextPooling = false); services.AddMigration(); @@ -19,7 +19,7 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder) services.AddTransient(); - builder.AddRabbitMqEventBus("EventBus") + builder.AddRabbitMqEventBus("eventbus") .AddEventBusSubscriptions(); services.AddHttpContextAccessor(); diff --git a/src/Webhooks.API/Extensions/Extensions.cs b/src/Webhooks.API/Extensions/Extensions.cs index 58ffe832..021ad20e 100644 --- a/src/Webhooks.API/Extensions/Extensions.cs +++ b/src/Webhooks.API/Extensions/Extensions.cs @@ -4,10 +4,10 @@ public static void AddApplicationServices(this IHostApplicationBuilder builder) { builder.AddDefaultAuthentication(); - builder.AddRabbitMqEventBus("EventBus") + builder.AddRabbitMqEventBus("eventbus") .AddEventBusSubscriptions(); - builder.AddNpgsqlDbContext("WebHooksDB"); + builder.AddNpgsqlDbContext("webhooksdb"); builder.Services.AddMigration(); diff --git a/src/eShop.AppHost/Extensions.cs b/src/eShop.AppHost/Extensions.cs new file mode 100644 index 00000000..697fd097 --- /dev/null +++ b/src/eShop.AppHost/Extensions.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Aspire.Hosting.Lifecycle; + +namespace eShop.AppHost; + +internal static class Extensions +{ + /// + /// Adds a hook to set the ASPNETCORE_FORWARDEDHEADERS_ENABLED environment variable to true for all projects in the application. + /// + public static IDistributedApplicationBuilder AddForwardedHeaders(this IDistributedApplicationBuilder builder) + { + builder.Services.TryAddLifecycleHook(); + return builder; + } + + private class AddForwardHeadersHook : IDistributedApplicationLifecycleHook + { + public Task BeforeStartAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default) + { + foreach (var p in appModel.GetProjectResources()) + { + p.Annotations.Add(new EnvironmentCallbackAnnotation(context => + { + context.EnvironmentVariables["ASPNETCORE_FORWARDEDHEADERS_ENABLED"] = "true"; + })); + } + + return Task.CompletedTask; + } + } +} diff --git a/src/eShop.AppHost/Program.cs b/src/eShop.AppHost/Program.cs index d7c43a98..5e6a9c24 100644 --- a/src/eShop.AppHost/Program.cs +++ b/src/eShop.AppHost/Program.cs @@ -1,7 +1,11 @@ -var builder = DistributedApplication.CreateBuilder(args); +using eShop.AppHost; + +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddForwardedHeaders(); var redis = builder.AddRedisContainer("redis"); -var rabbitMq = builder.AddRabbitMQContainer("EventBus"); +var rabbitMq = builder.AddRabbitMQContainer("eventbus"); var postgres = builder.AddPostgresContainer("postgres") .WithAnnotation(new ContainerImageAnnotation { @@ -9,19 +13,22 @@ Tag = "latest" }); -var catalogDb = postgres.AddDatabase("CatalogDB"); -var identityDb = postgres.AddDatabase("IdentityDB"); -var orderDb = postgres.AddDatabase("OrderingDB"); -var webhooksDb = postgres.AddDatabase("WebHooksDB"); +var catalogDb = postgres.AddDatabase("catalogdb"); +var identityDb = postgres.AddDatabase("identitydb"); +var orderDb = postgres.AddDatabase("orderingdb"); +var webhooksDb = postgres.AddDatabase("webhooksdb"); // Services var identityApi = builder.AddProject("identity-api") - .WithReference(identityDb); + .WithReference(identityDb) + .WithLaunchProfile("https"); + +var idpHttps = identityApi.GetEndpoint("https"); var basketApi = builder.AddProject("basket-api") .WithReference(redis) .WithReference(rabbitMq) - .WithEnvironment("Identity__Url", identityApi.GetEndpoint("http")); + .WithEnvironment("Identity__Url", idpHttps); var catalogApi = builder.AddProject("catalog-api") .WithReference(rabbitMq) @@ -30,7 +37,7 @@ var orderingApi = builder.AddProject("ordering-api") .WithReference(rabbitMq) .WithReference(orderDb) - .WithEnvironment("Identity__Url", identityApi.GetEndpoint("http")); + .WithEnvironment("Identity__Url", idpHttps); builder.AddProject("order-processor") .WithReference(rabbitMq) @@ -42,7 +49,7 @@ var webHooksApi = builder.AddProject("webhooks-api") .WithReference(rabbitMq) .WithReference(webhooksDb) - .WithEnvironment("Identity__Url", identityApi.GetEndpoint("http")); + .WithEnvironment("Identity__Url", idpHttps); // Reverse proxies builder.AddProject("mobile-bff") @@ -52,14 +59,14 @@ // Apps var webhooksClient = builder.AddProject("webhooksclient") .WithReference(webHooksApi) - .WithEnvironment("IdentityUrl", identityApi.GetEndpoint("http")); + .WithEnvironment("IdentityUrl", idpHttps); var webApp = builder.AddProject("webapp") .WithReference(basketApi) .WithReference(catalogApi) .WithReference(orderingApi) .WithReference(rabbitMq) - .WithEnvironment("IdentityUrl", identityApi.GetEndpoint("http")) + .WithEnvironment("IdentityUrl", idpHttps) .WithLaunchProfile("https"); // Wire up the callback urls (self referencing) diff --git a/src/eShop.ServiceDefaults/Extensions.cs b/src/eShop.ServiceDefaults/Extensions.cs index 47e45f5e..60a73173 100644 --- a/src/eShop.ServiceDefaults/Extensions.cs +++ b/src/eShop.ServiceDefaults/Extensions.cs @@ -49,10 +49,10 @@ public static IHostApplicationBuilder AddBasicServiceDefaults(this IHostApplicat public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) { - builder.Logging.AddOpenTelemetry(o => + builder.Logging.AddOpenTelemetry(logging => { - o.IncludeFormattedMessage = true; - o.IncludeScopes = true; + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; }); builder.Services.AddOpenTelemetry() @@ -65,10 +65,12 @@ public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicati { if (builder.Environment.IsDevelopment()) { + // We want to view all traces in development tracing.SetSampler(new AlwaysOnSampler()); } tracing.AddAspNetCoreInstrumentation() + .AddGrpcClientInstrumentation() .AddHttpClientInstrumentation(); }); @@ -123,7 +125,7 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app) app.MapHealthChecks("/health"); // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks("/liveness", new HealthCheckOptions + app.MapHealthChecks("/alive", new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); diff --git a/tests/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj b/tests/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj index 0a014080..76a3942a 100644 --- a/tests/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj +++ b/tests/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj @@ -20,7 +20,7 @@ - + diff --git a/tests/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj b/tests/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj index c5140309..2500f32c 100644 --- a/tests/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj +++ b/tests/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj @@ -18,12 +18,12 @@ - + - + - - + + \ No newline at end of file