diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 5c1a9082c..1719fc18d 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -272,7 +272,7 @@ services: - MarketingUrlHC=http://marketing.api/hc - PaymentUrlHC=http://payment.api/hc - LocationUrlHC=http://locations.api/hc - - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 + - IdentityUrlExternal=http://10.0.75.1:5105 ports: - "5203:80" volumes: @@ -305,6 +305,8 @@ services: - urls__catalog=http://catalog.api - urls__orders=http://ordering.api - urls__identity=http://identity.api + - urls__grpcBasket=http://10.0.75.1:5580 + - urls__grpcOrdering=http://10.0.75.1:5581 - CatalogUrlHC=http://catalog.api/hc - OrderingUrlHC=http://ordering.api/hc - IdentityUrlHC=http://identity.api/hc diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj index 40060ea29..80886821d 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs index 0dc91cbc0..f536ec19a 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs @@ -32,20 +32,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator ReloadOnChange = false }); }) - .ConfigureKestrel(options => - { - var ports = GetDefinedPorts(_configuration); - - options.Listen(IPAddress.Any, ports.httpPort, listenOptions => - { - listenOptions.Protocols = HttpProtocols.Http1AndHttp2; - }); - - options.Listen(IPAddress.Any, ports.grpcPort, listenOptions => - { - listenOptions.Protocols = HttpProtocols.Http2; - }); - }) .UseStartup() .UseSerilog((builderContext, config) => { @@ -67,12 +53,5 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator return builder.Build(); } - - private static (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) - { - var grpcPort = config.GetValue("GRPC_PORT", 5001); - var port = config.GetValue("PORT", 80); - return (port, grpcPort); - } } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs index 6bf502fdc..0f7a13483 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs @@ -29,5 +29,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config public string Basket { get; set; } public string Catalog { get; set; } public string Orders { get; set; } + public string GrpcBasket { get; set; } + public string GrpcOrdering { get; set; } } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs index 2fefb9d8a..a3be37611 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -31,7 +31,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] public async Task> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data) { - Log.Information("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ UpdateAllBasketAsync @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + Log.Debug("UpdateAllBasketAsync"); if (data.Items == null || !data.Items.Any()) { @@ -41,10 +41,12 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers // Retrieve the current basket Log.Information("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GetByIdAsync @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - var basket = await _basket.GetByIdAsync(data.BuyerId) ?? new BasketData(data.BuyerId); - Log.Information("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ basket @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + var basket = await _basket.GetById(data.BuyerId) ?? new BasketData(data.BuyerId); + + Log.Debug("get basket by id response={@response}", basket); var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); + Log.Debug("get catalog items response={@response}", catalogItems); foreach (var bitem in data.Items) { @@ -82,7 +84,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers } // Retrieve the current basket - var currentBasket = await _basket.GetByIdAsync(data.BasketId); + var currentBasket = await _basket.GetById(data.BasketId); if (currentBasket == null) { return BadRequest($"Basket with id {data.BasketId} not found."); @@ -122,7 +124,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers //item.PictureUri = // Step 2: Get current basket status - var currentBasket = (await _basket.GetByIdAsync(data.BasketId)) ?? new BasketData(data.BasketId); + var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); // Step 3: Search if exist product into basket var product = currentBasket.Items.SingleOrDefault(i => i.ProductId == item.Id.ToString()); diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs index de3e4cc55..4b88c45b6 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs @@ -16,11 +16,11 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers public class OrderController : ControllerBase { private readonly IBasketService _basketService; - private readonly IOrderApiClient _orderClient; - public OrderController(IBasketService basketService, IOrderApiClient orderClient) + private readonly IOrderingService _orderingService; + public OrderController(IBasketService basketService, IOrderingService orderingService) { _basketService = basketService; - _orderClient = orderClient; + _orderingService = orderingService; } [Route("draft/{basketId}")] @@ -34,14 +34,14 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers return BadRequest("Need a valid basketid"); } // Get the basket data and build a order draft based on it - var basket = await _basketService.GetByIdAsync(basketId); + var basket = await _basketService.GetById(basketId); if (basket == null) { return BadRequest($"No basket found for id {basketId}"); } - return await _orderClient.GetOrderDraftFromBasketAsync(basket); + return await _orderingService.GetOrderDraftAsync(basket); } } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile index fbce2f0ab..2a3b551a2 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base +FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build +FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build WORKDIR /src COPY scripts scripts/ diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index e93ec157c..45c191104 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -1,7 +1,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters { using Microsoft.AspNetCore.Authorization; - using Swashbuckle.AspNetCore.Swagger; + using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Collections.Generic; using System.Linq; @@ -10,7 +10,7 @@ { public class AuthorizeCheckOperationFilter : IOperationFilter { - public void Apply(Operation operation, OperationFilterContext context) + public void Apply(OpenApiOperation operation, OperationFilterContext context) { // Check for authorize attribute var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || @@ -18,14 +18,19 @@ if (!hasAuthorize) return; - operation.Responses.TryAdd("401", new Response { Description = "Unauthorized" }); - operation.Responses.TryAdd("403", new Response { Description = "Forbidden" }); + operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); - operation.Security = new List>> + var oAuthScheme = new OpenApiSecurityScheme { - new Dictionary> + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } + }; + + operation.Security = new List + { + new OpenApiSecurityRequirement { - { "oauth2", new [] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } } + [ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } } }; } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs index d29afb5c6..34c170e08 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs @@ -6,7 +6,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models { public string BuyerId { get; set; } - public List Items { get; set; } + public List Items { get; set; } = new List(); public BasketData() { @@ -16,7 +16,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models public BasketData(string buyerId) { BuyerId = buyerId; - Items = new List(); } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs index 6589719fa..b601d67f2 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs @@ -33,5 +33,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator .WriteTo.Console(); }) .Build(); + } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Protos/basket.api b/src/ApiGateways/Web.Bff.Shopping/aggregator/Protos/basket.api deleted file mode 100644 index 1fc22bc99..000000000 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Protos/basket.api +++ /dev/null @@ -1,34 +0,0 @@ -syntax = "proto3"; - -option csharp_namespace = "GrpcBasket"; - -package BasketApi; - -service Basket { - rpc GetBasketById(BasketRequest) returns (CustomerBasketResponse); - rpc UpdateBasket(CustomerBasketRequest) returns (CustomerBasketResponse); -} - -message BasketRequest { - string id = 1; -} - -message CustomerBasketRequest { - string buyerid = 1; - repeated BasketItemResponse items = 2; -} - -message CustomerBasketResponse { - string buyerid = 1; - repeated BasketItemResponse items = 2; -} - -message BasketItemResponse { - string id = 1; - string productid = 2; - string productname = 3; - double unitprice = 4; - double oldunitprice = 5; - int32 quantity = 6; - string pictureurl = 7; -} \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs index 92b96dec5..3e68816c1 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs @@ -5,91 +5,125 @@ using Microsoft.Extensions.Options; using Newtonsoft.Json; using System.Net.Http; using System.Threading.Tasks; +using Grpc.Net.Client; +using System; +using System.Linq; +using GrpcBasket; +using Grpc.Core; namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services { public class BasketService : IBasketService { - private readonly HttpClient _apiClient; - private readonly ILogger _logger; + private readonly HttpClient _httpClient; private readonly UrlsConfig _urls; + private readonly ILogger _logger; - public BasketService(HttpClient httpClient,ILogger logger, IOptions config) + public BasketService(HttpClient httpClient, IOptions config, ILogger logger) { - _apiClient = httpClient; - _logger = logger; + _httpClient = httpClient; _urls = config.Value; + _logger = logger; } - public async Task GetByIdAsync(string id) + public async Task GetById(string id) { - - _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GetById @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true); - using (var httpClientHandler = new HttpClientHandler()) + + using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; using (var httpClient = new HttpClient(httpClientHandler)) { + //httpClient.BaseAddress = new Uri("http://10.0.75.1:5580"); + httpClient.BaseAddress = new Uri(_urls.GrpcBasket); - _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Http2UnencryptedSupport disable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - - httpClient.BaseAddress = new Uri("http://localhost:5580"); + _logger.LogDebug("Creating grpc client for basket {@httpClient.BaseAddress} ", httpClient.BaseAddress); - _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ {httpClient.BaseAddress} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", httpClient.BaseAddress); + var client = GrpcClient.Create(httpClient); - var client = GrpcClient.Create(httpClient); + _logger.LogDebug("grpc client created, request = {@id}", id); - _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ client create @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + try + { - try{ + var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id }); - var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id }); - _logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ call grpc server @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + _logger.LogDebug("grpc response {@response}", response); - _logger.LogInformation("############## DATA: {@a}", response.Buyerid); - _logger.LogInformation("############## DATA:response {@response}", response); + return MapToBasketData(response); } catch (RpcException e) { - Console.WriteLine($"Error calling via grpc: {e.Status} - {e.Message}"); - _logger.logError($"Error calling via grpc: {e.Status} - {e.Message}"); - - } - - - //if (streaming.IsCompleted) - //{ - // _logger.LogInformation("############## DATA: {@a}", streaming.GetResult()); - //} - //var streaming = client.GetBasketById(new BasketRequest { Id = id }); + _logger.LogError($"Error calling via grpc: {e.Status} - {e.Message}"); + } + } + } + return null; + } - //var status = streaming.GetStatus(); + public async Task UpdateAsync(BasketData currentBasket) + { + _httpClient.BaseAddress = new Uri(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket()); - //if (status.StatusCode == Grpc.Core.StatusCode.OK) - //{ - // return null; - //} + var client = GrpcClient.Create(_httpClient); + var request = MapToCustomerBasketRequest(currentBasket); - return response; + await client.UpdateBasketAsync(request); + } - } - } + private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) + { + if (customerBasketRequest == null) + { + return null; + } - // var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id)); - // var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null; + var map = new BasketData + { + BuyerId = customerBasketRequest.Buyerid + }; - // return basket; + customerBasketRequest.Items.ToList().ForEach(item => map.Items.Add(new BasketDataItem + { + Id = item.Id, + OldUnitPrice = (decimal)item.Oldunitprice, + PictureUrl = item.Pictureurl, + ProductId = item.Productid, + ProductName = item.Productname, + Quantity = item.Quantity, + UnitPrice = (decimal)item.Unitprice + })); + + return map; } - public async Task UpdateAsync(BasketData currentBasket) + private CustomerBasketRequest MapToCustomerBasketRequest(BasketData basketData) { - var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json"); + if (basketData == null) + { + return null; + } - await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent); + var map = new CustomerBasketRequest + { + Buyerid = basketData.BuyerId + }; + + basketData.Items.ToList().ForEach(item => map.Items.Add(new BasketItemResponse + { + Id = item.Id, + Oldunitprice = (double)item.OldUnitPrice, + Pictureurl = item.PictureUrl, + Productid = item.ProductId, + Productname = item.ProductName, + Quantity = item.Quantity, + Unitprice = (double)item.UnitPrice + })); + + return map; } } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs index 046ef753d..fba539b7a 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs @@ -5,7 +5,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services { public interface IBasketService { - Task GetByIdAsync(string id); + Task GetById(string id); Task UpdateAsync(BasketData currentBasket); } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs new file mode 100644 index 000000000..a20520747 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs @@ -0,0 +1,10 @@ +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public interface IOrderingService + { + Task GetOrderDraftAsync(BasketData basketData); + } +} \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs new file mode 100644 index 000000000..bba3b851c --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs @@ -0,0 +1,113 @@ +using Grpc.Net.Client; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using GrpcOrdering; +using Grpc.Core; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public class OrderingService : IOrderingService + { + private readonly HttpClient _httpClient; + private readonly UrlsConfig _urls; + private readonly ILogger _logger; + + public OrderingService(HttpClient httpClient, IOptions config, ILogger logger) + { + _httpClient = httpClient; + _urls = config.Value; + _logger = logger; + } + + public async Task GetOrderDraftAsync(BasketData basketData) + { + AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); + AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true); + + using (var httpClientHandler = new HttpClientHandler()) + { + httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; + using (var httpClient = new HttpClient(httpClientHandler)) + { + httpClient.BaseAddress = new Uri(_urls.GrpcOrdering); + + _logger.LogDebug(" Creating grpc client for ordering {@httpClient.BaseAddress}", httpClient.BaseAddress); + + var client = GrpcClient.Create(httpClient); + + _logger.LogDebug(" grpc client created, basketData={@basketData}", basketData); + + try + { + + var command = MapToOrderDraftCommand(basketData); + var response = await client.CreateOrderDraftFromBasketDataAsync(command); + + _logger.LogDebug(" grpc response: {@response}", response); + + return MapToResponse(response); + } + catch (RpcException e) + { + _logger.LogError($"Error calling via grpc to ordering: {e.Status} - {e.Message}"); + } + } + } + + return null; + } + + private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft) + { + if (orderDraft == null) + { + return null; + } + + var data = new OrderData + { + Total = (decimal)orderDraft.Total, + }; + + orderDraft.OrderItems.ToList().ForEach(o => data.OrderItems.Add(new OrderItemData + { + Discount = (decimal)o.Discount, + PictureUrl = o.PictureUrl, + ProductId = o.ProductId, + ProductName = o.ProductName, + UnitPrice = (decimal)o.UnitPrice, + Units = o.Units, + })); + + return data; + } + + private CreateOrderDraftCommand MapToOrderDraftCommand(BasketData basketData) + { + var command = new CreateOrderDraftCommand + { + BuyerId = basketData.BuyerId, + }; + + basketData.Items.ForEach(i => command.Items.Add(new BasketItem + { + Id = i.Id, + OldUnitPrice = (double)i.OldUnitPrice, + PictureUrl = i.PictureUrl, + ProductId = i.ProductId, + ProductName = i.ProductName, + Quantity = i.Quantity, + UnitPrice = (double)i.UnitPrice, + })); + + return command; + } + + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs index 7c18f10ec..9613fe462 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs @@ -14,6 +14,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Models; using Polly; using Polly.Extensions.Http; using Swashbuckle.AspNetCore.Swagger; @@ -62,19 +63,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator app.UsePathBase(pathBase); } - app.UseHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - - app.UseHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); - - app.UseCors("CorsPolicy"); - if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); @@ -85,18 +73,37 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator app.UseHsts(); } - app.UseAuthentication(); + app.UseCors("CorsPolicy"); app.UseHttpsRedirection(); - app.UseMvc(); - app.UseSwagger() - .UseSwaggerUI(c => + app.UseSwagger().UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); + + c.OAuthClientId("webshoppingaggswaggerui"); + c.OAuthClientSecret(string.Empty); + c.OAuthRealm(string.Empty); + c.OAuthAppName("web shopping bff Swagger UI"); + }); + + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); - //c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); - c.OAuthClientId("webshoppingaggswaggerui"); - c.OAuthAppName("web shopping bff Swagger UI"); + Predicate = r => r.Name.Contains("self") }); + }); } } @@ -104,29 +111,20 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator { public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + var identityUrl = configuration.GetValue("urls:identity"); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(options => + }) + .AddJwtBearer(options => { options.Authority = identityUrl; options.RequireHttpsMetadata = false; options.Audience = "webshoppingagg"; - options.Events = new JwtBearerEvents() - { - OnAuthenticationFailed = async ctx => - { - int i = 0; - }, - OnTokenValidated = async ctx => - { - int i = 0; - } - }; }); return services; @@ -137,30 +135,35 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator services.AddOptions(); services.Configure(configuration.GetSection("urls")); - services.AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddControllers() + .AddNewtonsoftJson(); services.AddSwaggerGen(options => { options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info + + options.SwaggerDoc("v1", new OpenApiInfo { - Title = "Shopping Aggregator for Web Clients", + Title = "Shopping Aggregator for Mobile Clients", Version = "v1", - Description = "Shopping Aggregator for Web Clients", - TermsOfService = "Terms Of Service" + Description = "Shopping Aggregator for Mobile Clients" }); - options.AddSecurityDefinition("oauth2", new OAuth2Scheme + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { - Type = "oauth2", - Flow = "implicit", - AuthorizationUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize", - TokenUrl = $"{configuration.GetValue("IdentityUrlExternal")}/connect/token", - Scopes = new Dictionary() + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() { - { "webshoppingagg", "Shopping Aggregator for Web Clients" }, - { "basket", "basket api" } + Implicit = new OpenApiOAuthFlow() + { + AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), + TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), + + Scopes = new Dictionary() + { + { "webshoppingagg", "Shopping Aggregator for Web Clients" } + } + } } }); @@ -204,6 +207,12 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator .AddPolicyHandler(GetCircuitBreakerPolicy()) .AddDevspacesSupport(); + services.AddHttpClient() + .AddHttpMessageHandler() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); + return services; } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj index ed51b4860..b712ad270 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj @@ -33,10 +33,12 @@ - netcoreapp2.2 + $(NetCoreTargetVersion) Web.Shopping.HttpAggregator Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator ..\..\..\docker-compose.dcproj + false + true $(LangVersion) @@ -45,26 +47,32 @@ - - - - - - - - - - - - + + + - + + + + + + + + + + + + + + + + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json index 57b5e894d..ad33f3414 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json @@ -3,6 +3,8 @@ "basket": "http://localhost:55105", "catalog": "http://localhost:55101", "orders": "http://localhost:55102", - "identity": "http://localhost:55105" + "identity": "http://localhost:55105", + "grpcBasket": "http://localhost:5580", + "grpcOrdering": "http://localhost:5581" } } diff --git a/src/_build/dependencies.props b/src/_build/dependencies.props index c16619251..16cf2f2b5 100644 --- a/src/_build/dependencies.props +++ b/src/_build/dependencies.props @@ -19,6 +19,7 @@ 0.1.22-pre3 0.1.22-pre3 3.9.1 + 1.22.0 2.23.0 0.1.22-pre2