From 5d4cba07edaead915964afe90f63437dbe97fd7a Mon Sep 17 00:00:00 2001 From: Thang Chung Date: Sun, 19 Aug 2018 16:43:04 +0700 Subject: [PATCH 1/2] Upgrade .NET code to new NetCoreKit version --- .../coolstore/templates/nginx-ingress.yaml | 2 +- deploys/dockers/mysqldb/Dockerfile | 5 ++ deploys/dockers/mysqldb/mysqldb-init.sql | 2 + src/services/cart/Dockerfile | 7 ++- src/services/cart/Program.cs | 13 ++-- src/services/cart/Startup.cs | 53 ++++++++-------- .../cart/VND.CoolStore.Services.Cart.csproj | 24 ++++--- .../cart/appsettings.Development.json | 3 +- src/services/cart/appsettings.json | 11 ++++ .../cart/v1/UseCases/CartController.cs | 62 +++++++++++++++++++ .../cart/v1/UseCases/Checkout/Controller.cs | 27 -------- .../v1/UseCases/Checkout/RequestHandler.cs | 4 +- .../UseCases/DeleteItemInCart/Controller.cs | 27 -------- .../DeleteItemInCart/RequestHandler.cs | 4 +- .../v1/UseCases/GetCartById/Controller.cs | 27 -------- .../v1/UseCases/GetCartById/RequestHandler.cs | 4 +- .../cart/v1/UseCases/HealthController.cs | 35 ----------- .../cart/v1/UseCases/HomeController.cs | 26 -------- .../InsertItemToNewCart/Controller.cs | 21 ------- .../InsertItemToNewCart/RequestHandler.cs | 4 +- .../UseCases/UpdateItemInCart/Controller.cs | 21 ------- .../UpdateItemInCart/RequestHandler.cs | 4 +- src/services/cart/v2/CartController.cs | 5 +- src/services/inventory/Dockerfile | 7 ++- src/services/inventory/Program.cs | 13 ++-- src/services/inventory/Startup.cs | 54 ++++++++-------- .../VND.CoolStore.Services.Inventory.csproj | 21 ++++--- .../inventory/appsettings.Development.json | 3 +- src/services/inventory/appsettings.json | 11 ++++ .../v1/UseCases/AvailabilityController.cs | 33 ++++++++++ .../v1/UseCases/GetInventory/Controller.cs | 32 ---------- .../UseCases/GetInventory/RequestHandler.cs | 4 +- .../inventory/v1/UseCases/HealthController.cs | 35 ----------- .../inventory/v1/UseCases/HomeController.cs | 24 ------- src/services/review/Dockerfile | 7 ++- src/services/review/Domain/Review.cs | 2 +- src/services/review/Domain/ReviewAuthor.cs | 2 +- src/services/review/Domain/ReviewProduct.cs | 8 ++- src/services/review/Dtos/ReviewDto.cs | 2 + .../review/Extensions/ReviewExtensions.cs | 4 +- ...> 20180819091438_InitReviewDb.Designer.cs} | 10 +-- ...ewDb.cs => 20180819091438_InitReviewDb.cs} | 6 +- .../ReviewDbContextModelSnapshot.cs | 8 +-- src/services/review/Program.cs | 14 ++--- src/services/review/Startup.cs | 54 ++++++++-------- .../VND.CoolStore.Services.Review.csproj | 22 ++++--- .../review/appsettings.Development.json | 5 +- src/services/review/appsettings.json | 11 ++++ src/services/review/v1/HealthController.cs | 35 ----------- src/services/review/v1/HomeController.cs | 26 -------- .../v1/UseCases/AddReview/Controller.cs | 21 ------- .../v1/UseCases/AddReview/RequestHandler.cs | 10 +-- .../v1/UseCases/GetReviews/Controller.cs | 27 -------- .../v1/UseCases/GetReviews/RequestHandler.cs | 17 ++--- .../v1/UseCases/RemoveReview/Controller.cs | 27 -------- .../UseCases/RemoveReview/RequestHandler.cs | 9 ++- .../review/v1/UseCases/ReviewController.cs | 59 ++++++++++++++++++ .../v1/UseCases/UpdateReview/Controller.cs | 31 ---------- .../UseCases/UpdateReview/RequestHandler.cs | 10 ++- 59 files changed, 409 insertions(+), 646 deletions(-) create mode 100644 deploys/dockers/mysqldb/Dockerfile create mode 100644 deploys/dockers/mysqldb/mysqldb-init.sql create mode 100644 src/services/cart/v1/UseCases/CartController.cs delete mode 100644 src/services/cart/v1/UseCases/Checkout/Controller.cs delete mode 100644 src/services/cart/v1/UseCases/DeleteItemInCart/Controller.cs delete mode 100644 src/services/cart/v1/UseCases/GetCartById/Controller.cs delete mode 100644 src/services/cart/v1/UseCases/HealthController.cs delete mode 100644 src/services/cart/v1/UseCases/HomeController.cs delete mode 100644 src/services/cart/v1/UseCases/InsertItemToNewCart/Controller.cs delete mode 100644 src/services/cart/v1/UseCases/UpdateItemInCart/Controller.cs create mode 100644 src/services/inventory/v1/UseCases/AvailabilityController.cs delete mode 100644 src/services/inventory/v1/UseCases/GetInventory/Controller.cs delete mode 100644 src/services/inventory/v1/UseCases/HealthController.cs delete mode 100644 src/services/inventory/v1/UseCases/HomeController.cs rename src/services/review/Migrations/{20180810131836_InitReviewDb.Designer.cs => 20180819091438_InitReviewDb.Designer.cs} (89%) rename src/services/review/Migrations/{20180810131836_InitReviewDb.cs => 20180819091438_InitReviewDb.cs} (91%) delete mode 100644 src/services/review/v1/HealthController.cs delete mode 100644 src/services/review/v1/HomeController.cs delete mode 100644 src/services/review/v1/UseCases/AddReview/Controller.cs delete mode 100644 src/services/review/v1/UseCases/GetReviews/Controller.cs delete mode 100644 src/services/review/v1/UseCases/RemoveReview/Controller.cs create mode 100644 src/services/review/v1/UseCases/ReviewController.cs delete mode 100644 src/services/review/v1/UseCases/UpdateReview/Controller.cs diff --git a/deploys/charts/coolstore/templates/nginx-ingress.yaml b/deploys/charts/coolstore/templates/nginx-ingress.yaml index ab8ede70..15e95e09 100644 --- a/deploys/charts/coolstore/templates/nginx-ingress.yaml +++ b/deploys/charts/coolstore/templates/nginx-ingress.yaml @@ -14,7 +14,7 @@ spec: - path: / backend: serviceName: spa-service - servicePort: 8080 + servicePort: 80 - host: {{ .Values.hosts.idp }} http: paths: diff --git a/deploys/dockers/mysqldb/Dockerfile b/deploys/dockers/mysqldb/Dockerfile new file mode 100644 index 00000000..c0f997ca --- /dev/null +++ b/deploys/dockers/mysqldb/Dockerfile @@ -0,0 +1,5 @@ +FROM mysql:8.0.12 + +# MYSQL_ROOT_PASSWORD must be supplied as an env var + +COPY ./deploys/dockers/mysqldb/mysqldb-init.sql /docker-entrypoint-initdb.d \ No newline at end of file diff --git a/deploys/dockers/mysqldb/mysqldb-init.sql b/deploys/dockers/mysqldb/mysqldb-init.sql new file mode 100644 index 00000000..8b36ecf0 --- /dev/null +++ b/deploys/dockers/mysqldb/mysqldb-init.sql @@ -0,0 +1,2 @@ +CREATE DATABASE maindb; +USE maindb; \ No newline at end of file diff --git a/src/services/cart/Dockerfile b/src/services/cart/Dockerfile index ed464401..68e4f6b4 100644 --- a/src/services/cart/Dockerfile +++ b/src/services/cart/Dockerfile @@ -1,6 +1,9 @@ FROM microsoft/dotnet:2.1.2-aspnetcore-runtime-alpine AS base WORKDIR /app +ENV PROJECT /src/src/services/cart +ENV EXECUTE_FILE VND.CoolStore.Services.Cart.dll + ARG service_version ENV SERVICE_VERSION ${service_version:-0.0.1} @@ -14,7 +17,7 @@ FROM microsoft/dotnet:2.1.302-sdk-alpine AS build WORKDIR /src COPY . . -WORKDIR /src/src/services/cart +WORKDIR $PROJECT RUN dotnet restore -nowarn:msb3202,nu1503 RUN dotnet build --no-restore -c Release -o /app @@ -25,4 +28,4 @@ RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . -ENTRYPOINT ["dotnet", "VND.CoolStore.Services.Cart.dll"] +ENTRYPOINT ["dotnet", "$EXECUTE_FILE"] diff --git a/src/services/cart/Program.cs b/src/services/cart/Program.cs index acc8831b..d27d18d1 100644 --- a/src/services/cart/Program.cs +++ b/src/services/cart/Program.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using NetCoreKit.Infrastructure.EfCore.Extensions; using VND.CoolStore.Services.Cart.Infrastructure.Db; @@ -9,17 +10,15 @@ public class Program { public static void Main(string[] args) { - var webHost = BuildWebHost(args); - if ((webHost.Services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment).IsDevelopment()) - { + var webHost = CreateWebHostBuilder(args).Build(); + var env = webHost.Services.GetService(); + if (env.IsDevelopment()) webHost = webHost.RegisterDbContext(); - } webHost.Run(); } - public static IWebHost BuildWebHost(string[] args) => + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); + .UseStartup(); } } diff --git a/src/services/cart/Startup.cs b/src/services/cart/Startup.cs index 00964177..c3f8c71d 100644 --- a/src/services/cart/Startup.cs +++ b/src/services/cart/Startup.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using NetCoreKit.Infrastructure.AspNetCore.Miniservice; -using NetCoreKit.Infrastructure.EfCore.SqlServer; +using NetCoreKit.Infrastructure.EfCore.MySql; using VND.CoolStore.Services.Cart.Infrastructure.Db; using VND.CoolStore.Services.Cart.v1.Services; using VND.CoolStore.Services.Cart.v2.Services; @@ -14,35 +13,33 @@ public class Startup { public void ConfigureServices(IServiceCollection services) { - var assemblies = new HashSet - { - typeof(Startup).GetTypeInfo().Assembly, - typeof(MiniServiceExtensions).GetTypeInfo().Assembly - }; + services.AddMiniService( + new[] {typeof(Startup)}, + svc => + { + //svc.AddEfCoreMySqlDb(); + svc.AddExternalSystemHealthChecks(); + }, + () => new Dictionary + { + { + Constants.ClaimToScopeMap, new Dictionary + { + {"access_cart_api", "cart_api_scope"} + } + }, + { + Constants.Scopes, new Dictionary + { + {"cart_api_scope", "Cart APIs"} + } + }, + {Constants.Audience, "api"} + } + ); - var claimToScopeMap = new Dictionary - { - {"access_cart_api", "cart_api_scope"} - }; - - var scopes = new Dictionary - { - {"cart_api_scope", "Cart APIs"} - }; - - var serviceParams = new ServiceParams - { - {"assemblies", assemblies}, - {"audience", "api"}, - {"claimToScopeMap", claimToScopeMap}, - {"scopes", scopes} - }; - - services.AddScoped(sp => serviceParams); - services.AddEfCoreSqlServer(); services.AddScoped(); services.AddScoped(); - services.AddMiniService(); } public void Configure(IApplicationBuilder app) diff --git a/src/services/cart/VND.CoolStore.Services.Cart.csproj b/src/services/cart/VND.CoolStore.Services.Cart.csproj index 925e4e9c..e66fa30c 100644 --- a/src/services/cart/VND.CoolStore.Services.Cart.csproj +++ b/src/services/cart/VND.CoolStore.Services.Cart.csproj @@ -13,20 +13,26 @@ - - - - - - - - + + + + + + + + + + - + + + + + diff --git a/src/services/cart/appsettings.Development.json b/src/services/cart/appsettings.Development.json index 4bb36c5d..cdf00c54 100644 --- a/src/services/cart/appsettings.Development.json +++ b/src/services/cart/appsettings.Development.json @@ -1,6 +1,7 @@ { "ConnectionStrings": { - "mssqldb": "Server=tcp:127.0.0.1,1433;Database=maindb;User Id=cs;Password=P@ssw0rd;" + "mssqldb": "Server=tcp:127.0.0.1,1433;Database=maindb;User Id=cs;Password=P@ssw0rd;", + "mysqldb": "server=127.0.0.1;port=3306;uid=root;pwd=P@ssw0rd;database=maindb" }, "Hosts": { "Externals": { diff --git a/src/services/cart/appsettings.json b/src/services/cart/appsettings.json index 9fac70b8..c1cd920b 100644 --- a/src/services/cart/appsettings.json +++ b/src/services/cart/appsettings.json @@ -16,6 +16,17 @@ "Database": "maindb", "UserName": "cs", "Password": "P@ssw0rd" + }, + "mysqldb": { + "Host": "CART_DB_SERVICE_SERVICE_HOST", + "Port": "CART_DB_SERVICE_SERVICE_PORT", + "Database": "maindb", + "UserName": "root", + "Password": "P@ssw0rd", + "Major": 8, + "Minor": 0, + "Build": 12, + "DbType": 0 } }, "Hosts": { diff --git a/src/services/cart/v1/UseCases/CartController.cs b/src/services/cart/v1/UseCases/CartController.cs new file mode 100644 index 00000000..fb036abb --- /dev/null +++ b/src/services/cart/v1/UseCases/CartController.cs @@ -0,0 +1,62 @@ +using System; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using NetCoreKit.Infrastructure.AspNetCore.Authz; +using NetCoreKit.Infrastructure.AspNetCore.CleanArch; +using VND.CoolStore.Services.Cart.v1.UseCases.Checkout; +using VND.CoolStore.Services.Cart.v1.UseCases.DeleteItemInCart; +using VND.CoolStore.Services.Cart.v1.UseCases.GetCartById; +using VND.CoolStore.Services.Cart.v1.UseCases.InsertItemToNewCart; +using VND.CoolStore.Services.Cart.v1.UseCases.UpdateItemInCart; +using Controller = Microsoft.AspNetCore.Mvc.Controller; + +namespace VND.CoolStore.Services.Cart.v1.UseCases +{ + [ApiVersion("1.0")] + [Route("api/carts")] + public class CartController : Controller + { + [HttpGet] + [Route("{id}")] + [Auth(Policy = "access_cart_api")] + public async Task Get([FromServices] IMediator eventor, Guid id, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new GetCartRequest { CartId = id }, + x => x.Result); + } + + [HttpPost] + [Auth(Policy = "access_cart_api")] + public async Task Create([FromServices] IMediator eventor, InsertItemToNewCartRequest request, CancellationToken cancellationToken) => + await eventor.SendStream(request, x => x.Result); + + [HttpPut] + [Auth(Policy = "access_cart_api")] + public async Task Put([FromServices] IMediator eventor, UpdateItemInCartRequest request, CancellationToken cancellationToken) => + await eventor.SendStream(request, x => x.Result); + + [HttpDelete] + [Route("{cartId:guid}/items/{productId:guid}")] + [Auth(Policy = "access_cart_api")] + public async Task RemoveItemInCart([FromServices] IMediator eventor, Guid cartId, Guid productId, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new DeleteItemRequest { CartId = cartId, ProductId = productId }, + x => x.ProductId); + } + + [HttpPut] + [Route("{cartId:guid}/checkout")] + [Auth(Policy = "access_cart_api")] + public async Task CheckoutCart([FromServices] IMediator eventor, Guid cartId, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new CheckoutRequest { CartId = cartId }, + x => x.IsSucceed); + } + } +} diff --git a/src/services/cart/v1/UseCases/Checkout/Controller.cs b/src/services/cart/v1/UseCases/Checkout/Controller.cs deleted file mode 100644 index 94af4ca3..00000000 --- a/src/services/cart/v1/UseCases/Checkout/Controller.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Cart.v1.UseCases.Checkout -{ - [ApiVersion("1.0")] - [Route("api/carts")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpPut] - [Route("{cartId:guid}/checkout")] - [Auth(Policy = "access_cart_api")] - public async Task CheckoutCart(Guid cartId) - { - return await Eventor.SendStream( - new CheckoutRequest { CartId = cartId }, - x => x.IsSucceed); - } - } -} diff --git a/src/services/cart/v1/UseCases/Checkout/RequestHandler.cs b/src/services/cart/v1/UseCases/Checkout/RequestHandler.cs index 28e952e2..4d0fc4ce 100644 --- a/src/services/cart/v1/UseCases/Checkout/RequestHandler.cs +++ b/src/services/cart/v1/UseCases/Checkout/RequestHandler.cs @@ -14,7 +14,7 @@ public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf) { } - public override async Task TxHandle(CheckoutRequest request, CancellationToken cancellationToken) + public override async Task Handle(CheckoutRequest request, CancellationToken cancellationToken) { var cartRepository = UnitOfWork.Repository(); @@ -25,6 +25,8 @@ public override async Task TxHandle(CheckoutRequest request, C cart.IsCheckout = true; var checkoutCart = await cartRepository.UpdateAsync(cart); + await UnitOfWork.SaveChangesAsync(cancellationToken); + return new CheckoutResponse { IsSucceed = checkoutCart != null diff --git a/src/services/cart/v1/UseCases/DeleteItemInCart/Controller.cs b/src/services/cart/v1/UseCases/DeleteItemInCart/Controller.cs deleted file mode 100644 index d9cddd85..00000000 --- a/src/services/cart/v1/UseCases/DeleteItemInCart/Controller.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Cart.v1.UseCases.DeleteItemInCart -{ - [ApiVersion("1.0")] - [Route("api/carts")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpDelete] - [Route("{cartId:guid}/items/{productId:guid}")] - [Auth(Policy = "access_cart_api")] - public async Task RemoveItemInCart(Guid cartId, Guid productId) - { - return await Eventor.SendStream( - new DeleteItemRequest { CartId = cartId, ProductId = productId }, - x => x.ProductId); - } - } -} diff --git a/src/services/cart/v1/UseCases/DeleteItemInCart/RequestHandler.cs b/src/services/cart/v1/UseCases/DeleteItemInCart/RequestHandler.cs index 7fac41e5..527ec501 100644 --- a/src/services/cart/v1/UseCases/DeleteItemInCart/RequestHandler.cs +++ b/src/services/cart/v1/UseCases/DeleteItemInCart/RequestHandler.cs @@ -22,7 +22,7 @@ public RequestHandler(ICatalogGateway cgw, IUnitOfWorkAsync uow, IQueryRepositor _catalogGateway = cgw; } - public override async Task TxHandle(DeleteItemRequest request, CancellationToken cancellationToken) + public override async Task Handle(DeleteItemRequest request, CancellationToken cancellationToken) { var cartRepository = UnitOfWork.Repository(); var cartItemRepository = UnitOfWork.Repository(); @@ -43,6 +43,8 @@ public override async Task TxHandle(DeleteItemRequest reques var isSucceed = await cartRepository.UpdateAsync(cart) != null; await cartItemRepository.DeleteAsync(cartItem); + await UnitOfWork.SaveChangesAsync(cancellationToken); + return new DeleteItemResponse { ProductId = cartItem.Product.ProductId }; } } diff --git a/src/services/cart/v1/UseCases/GetCartById/Controller.cs b/src/services/cart/v1/UseCases/GetCartById/Controller.cs deleted file mode 100644 index 69366a96..00000000 --- a/src/services/cart/v1/UseCases/GetCartById/Controller.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Cart.v1.UseCases.GetCartById -{ - [ApiVersion("1.0")] - [Route("api/carts")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpGet] - [Route("{id}")] - [Auth(Policy = "access_cart_api")] - public async Task Get(Guid id) - { - return await Eventor.SendStream( - new GetCartRequest { CartId = id }, - x => x.Result); - } - } -} diff --git a/src/services/cart/v1/UseCases/GetCartById/RequestHandler.cs b/src/services/cart/v1/UseCases/GetCartById/RequestHandler.cs index 30d1e8be..cf67a2e9 100644 --- a/src/services/cart/v1/UseCases/GetCartById/RequestHandler.cs +++ b/src/services/cart/v1/UseCases/GetCartById/RequestHandler.cs @@ -15,8 +15,8 @@ public class RequestHandler : RequestHandlerBase(); - } - catch (Exception) - { - - return new BadRequestResult(); - } - - return Ok(); - } - } -} diff --git a/src/services/cart/v1/UseCases/HomeController.cs b/src/services/cart/v1/UseCases/HomeController.cs deleted file mode 100644 index 76849f82..00000000 --- a/src/services/cart/v1/UseCases/HomeController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using NetCoreKit.Infrastructure.AspNetCore.Extensions; -using NetCoreKit.Infrastructure.AspNetCore.Miniservice.Options; - -namespace VND.CoolStore.Services.Cart.v1.UseCases -{ - [Route("")] - [ApiVersionNeutral] - [ApiExplorerSettings(IgnoreApi = true)] - public class HomeController : Controller - { - private readonly string _basePath; - public HomeController(IConfiguration config, IOptions options) - { - _basePath = config.GetBasePath() ?? "/"; - } - - [HttpGet] - public IActionResult Index() - { - return Redirect($"~{_basePath}swagger"); - } - } -} diff --git a/src/services/cart/v1/UseCases/InsertItemToNewCart/Controller.cs b/src/services/cart/v1/UseCases/InsertItemToNewCart/Controller.cs deleted file mode 100644 index e3539810..00000000 --- a/src/services/cart/v1/UseCases/InsertItemToNewCart/Controller.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Cart.v1.UseCases.InsertItemToNewCart -{ - [ApiVersion("1.0")] - [Route("api/carts")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpPost] - [Auth(Policy = "access_cart_api")] - public async Task Create(InsertItemToNewCartRequest request) => - await Eventor.SendStream(request, x => x.Result); - } -} diff --git a/src/services/cart/v1/UseCases/InsertItemToNewCart/RequestHandler.cs b/src/services/cart/v1/UseCases/InsertItemToNewCart/RequestHandler.cs index 7e522cfc..efd73f08 100644 --- a/src/services/cart/v1/UseCases/InsertItemToNewCart/RequestHandler.cs +++ b/src/services/cart/v1/UseCases/InsertItemToNewCart/RequestHandler.cs @@ -22,7 +22,7 @@ public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf, _priceCalculator = priceCalculator; } - public override async Task TxHandle(InsertItemToNewCartRequest request, CancellationToken cancellationToken) + public override async Task Handle(InsertItemToNewCartRequest request, CancellationToken cancellationToken) { var cartRepository = UnitOfWork.Repository(); @@ -40,6 +40,8 @@ public override async Task TxHandle(InsertItemToNew await cartRepository.AddAsync(cart); + await UnitOfWork.SaveChangesAsync(cancellationToken); + return new InsertItemToNewCartResponse { Result = cart.ToDto() }; } } diff --git a/src/services/cart/v1/UseCases/UpdateItemInCart/Controller.cs b/src/services/cart/v1/UseCases/UpdateItemInCart/Controller.cs deleted file mode 100644 index f6a1fb87..00000000 --- a/src/services/cart/v1/UseCases/UpdateItemInCart/Controller.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Cart.v1.UseCases.UpdateItemInCart -{ - [ApiVersion("1.0")] - [Route("api/carts")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpPut] - [Auth(Policy = "access_cart_api")] - public async Task Put(UpdateItemInCartRequest request) => - await Eventor.SendStream(request, x => x.Result); - } -} diff --git a/src/services/cart/v1/UseCases/UpdateItemInCart/RequestHandler.cs b/src/services/cart/v1/UseCases/UpdateItemInCart/RequestHandler.cs index c65ed693..86a6b633 100644 --- a/src/services/cart/v1/UseCases/UpdateItemInCart/RequestHandler.cs +++ b/src/services/cart/v1/UseCases/UpdateItemInCart/RequestHandler.cs @@ -25,7 +25,7 @@ public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf, _priceCalculator = priceCalculator; } - public override async Task TxHandle(UpdateItemInCartRequest request, + public override async Task Handle(UpdateItemInCartRequest request, CancellationToken cancellationToken) { var cartRepository = UnitOfWork.Repository(); @@ -66,6 +66,8 @@ public override async Task TxHandle(UpdateItemInCartRe else await cartItemRepository.AddAsync(item); + await UnitOfWork.SaveChangesAsync(cancellationToken); + return new UpdateItemInCartResponse {Result = cart.ToDto()}; } } diff --git a/src/services/cart/v2/CartController.cs b/src/services/cart/v2/CartController.cs index aa1edc33..2edc1a23 100644 --- a/src/services/cart/v2/CartController.cs +++ b/src/services/cart/v2/CartController.cs @@ -1,6 +1,7 @@ using System; +using System.Threading; using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; +using NetCoreKit.Infrastructure.AspNetCore.Authz; namespace VND.CoolStore.Services.Cart.v2 { @@ -19,7 +20,7 @@ public CartController(ICartService cartService, TenPercentTaxCalculator taxCacul [HttpGet] [Route("{id}")] [Auth(Policy = "access_cart_api")] - public ActionResult Get(Guid id) + public ActionResult Get(Guid id, CancellationToken cancellationToken) { return Ok("2.0"); } diff --git a/src/services/inventory/Dockerfile b/src/services/inventory/Dockerfile index 5deaa409..6c5082af 100644 --- a/src/services/inventory/Dockerfile +++ b/src/services/inventory/Dockerfile @@ -1,6 +1,9 @@ FROM microsoft/dotnet:2.1.2-aspnetcore-runtime-alpine AS base WORKDIR /app +ENV PROJECT /src/src/services/inventory +ENV EXECUTE_FILE VND.CoolStore.Services.Inventory.dll + ARG service_version ENV SERVICE_VERSION ${service_version:-0.0.1} @@ -14,7 +17,7 @@ FROM microsoft/dotnet:2.1.302-sdk-alpine AS build WORKDIR /src COPY . . -WORKDIR /src/src/services/inventory +WORKDIR $PROJECT RUN dotnet restore -nowarn:msb3202,nu1503 RUN dotnet build --no-restore -c Release -o /app @@ -25,4 +28,4 @@ RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . -ENTRYPOINT ["dotnet", "VND.CoolStore.Services.Inventory.dll"] +ENTRYPOINT ["dotnet", "$EXECUTE_FILE"] diff --git a/src/services/inventory/Program.cs b/src/services/inventory/Program.cs index 8a4df6c9..ff2a2441 100644 --- a/src/services/inventory/Program.cs +++ b/src/services/inventory/Program.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using NetCoreKit.Infrastructure.EfCore.Extensions; using VND.CoolStore.Services.Inventory.Infrastructure.Db; @@ -9,17 +10,15 @@ public class Program { public static void Main(string[] args) { - var webHost = BuildWebHost(args); - if ((webHost.Services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment).IsDevelopment()) - { + var webHost = CreateWebHostBuilder(args).Build(); + var env = webHost.Services.GetService(); + if (env.IsDevelopment()) webHost = webHost.RegisterDbContext(); - } webHost.Run(); } - public static IWebHost BuildWebHost(string[] args) => + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); + .UseStartup(); } } diff --git a/src/services/inventory/Startup.cs b/src/services/inventory/Startup.cs index 3789e1bf..b9ef3a1c 100644 --- a/src/services/inventory/Startup.cs +++ b/src/services/inventory/Startup.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using NetCoreKit.Infrastructure.AspNetCore.Miniservice; -using NetCoreKit.Infrastructure.EfCore.SqlServer; +using NetCoreKit.Infrastructure.EfCore.MySql; using VND.CoolStore.Services.Inventory.Infrastructure.Db; namespace VND.CoolStore.Services.Inventory @@ -12,33 +11,30 @@ public class Startup { public void ConfigureServices(IServiceCollection services) { - var assemblies = new HashSet - { - typeof(Startup).GetTypeInfo().Assembly, - typeof(MiniServiceExtensions).GetTypeInfo().Assembly - }; - - var claimToScopeMap = new Dictionary - { - {"access_inventory_api", "inventory_api_scope"} - }; - - var scopes = new Dictionary - { - {"inventory_api_scope", "Inventory APIs"} - }; - - var serviceParams = new ServiceParams - { - {"assemblies", assemblies}, - {"audience", "api"}, - {"claimToScopeMap", claimToScopeMap}, - {"scopes", scopes} - }; - - services.AddScoped(sp => serviceParams); - services.AddEfCoreSqlServer(); - services.AddMiniService(); + services.AddMiniService( + new[] { typeof(Startup) }, + svc => + { + //svc.AddEfCoreMySqlDb(); + svc.AddExternalSystemHealthChecks(); + }, + () => new Dictionary + { + { + Constants.ClaimToScopeMap, new Dictionary + { + {"access_inventory_api", "inventory_api_scope"} + } + }, + { + Constants.Scopes, new Dictionary + { + {"inventory_api_scope", "Inventory APIs"} + } + }, + {Constants.Audience, "api"} + } + ); } public void Configure(IApplicationBuilder app) diff --git a/src/services/inventory/VND.CoolStore.Services.Inventory.csproj b/src/services/inventory/VND.CoolStore.Services.Inventory.csproj index 811dc7bd..b1226410 100644 --- a/src/services/inventory/VND.CoolStore.Services.Inventory.csproj +++ b/src/services/inventory/VND.CoolStore.Services.Inventory.csproj @@ -10,16 +10,21 @@ - - - - - - - - + + + + + + + + + + + + + diff --git a/src/services/inventory/appsettings.Development.json b/src/services/inventory/appsettings.Development.json index f7f9ef3c..ce5b6709 100644 --- a/src/services/inventory/appsettings.Development.json +++ b/src/services/inventory/appsettings.Development.json @@ -1,6 +1,7 @@ { "ConnectionStrings": { - "mssqldb": "Server=tcp:127.0.0.1,1433;Database=maindb;User Id=cs;Password=P@ssw0rd;" + "mssqldb": "Server=tcp:127.0.0.1,1433;Database=maindb;User Id=cs;Password=P@ssw0rd;", + "mysqldb": "server=127.0.0.1;port=3306;uid=root;pwd=P@ssw0rd;database=maindb" }, "Hosts": { "Externals": { diff --git a/src/services/inventory/appsettings.json b/src/services/inventory/appsettings.json index bc0fac7d..2ddc9888 100644 --- a/src/services/inventory/appsettings.json +++ b/src/services/inventory/appsettings.json @@ -16,6 +16,17 @@ "Database": "maindb", "UserName": "cs", "Password": "P@ssw0rd" + }, + "mysqldb": { + "Host": "CART_DB_SERVICE_SERVICE_HOST", + "Port": "CART_DB_SERVICE_SERVICE_PORT", + "Database": "maindb", + "UserName": "root", + "Password": "P@ssw0rd", + "Major": 8, + "Minor": 0, + "Build": 12, + "DbType": 0 } }, "Hosts": { diff --git a/src/services/inventory/v1/UseCases/AvailabilityController.cs b/src/services/inventory/v1/UseCases/AvailabilityController.cs new file mode 100644 index 00000000..716b1919 --- /dev/null +++ b/src/services/inventory/v1/UseCases/AvailabilityController.cs @@ -0,0 +1,33 @@ +using System; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using NetCoreKit.Infrastructure.AspNetCore.Authz; +using NetCoreKit.Infrastructure.AspNetCore.CleanArch; +using VND.CoolStore.Services.Inventory.v1.UseCases.GetInventory; +using Controller = Microsoft.AspNetCore.Mvc.Controller; + +namespace VND.CoolStore.Services.Inventory.v1.UseCases +{ + [ApiVersion("1.0")] + [Route("api/availability")] + public class AvailabilityController : Controller + { + [HttpGet("{id}")] + [Auth(Policy = "access_inventory_api")] + public async Task Get([FromServices] IMediator eventor, Guid id, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new GetInventoryRequest { InventoryId = id }, + x => x.Result); + } + + [HttpGet] + public ActionResult Sample(CancellationToken cancellationToken) + { + return "1.0"; + } + } +} diff --git a/src/services/inventory/v1/UseCases/GetInventory/Controller.cs b/src/services/inventory/v1/UseCases/GetInventory/Controller.cs deleted file mode 100644 index b1e6004a..00000000 --- a/src/services/inventory/v1/UseCases/GetInventory/Controller.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Inventory.v1.UseCases.GetInventory -{ - [ApiVersion("1.0")] - [Route("api/availability")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) {} - - [HttpGet("{id}")] - [Auth(Policy = "access_inventory_api")] - public async Task Get(Guid id) - { - return await Eventor.SendStream( - new GetInventoryRequest { InventoryId = id }, - x => x.Result); - } - - [HttpGet] - public ActionResult Sample() - { - return "1.0"; - } - } -} diff --git a/src/services/inventory/v1/UseCases/GetInventory/RequestHandler.cs b/src/services/inventory/v1/UseCases/GetInventory/RequestHandler.cs index 1d0d6362..e9e18eaf 100644 --- a/src/services/inventory/v1/UseCases/GetInventory/RequestHandler.cs +++ b/src/services/inventory/v1/UseCases/GetInventory/RequestHandler.cs @@ -9,8 +9,8 @@ namespace VND.CoolStore.Services.Inventory.v1.UseCases.GetInventory { public class RequestHandler : RequestHandlerBase { - public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory queryRepositoryFactory) - : base(uow, queryRepositoryFactory) + public RequestHandler(IQueryRepositoryFactory queryRepositoryFactory) + : base(queryRepositoryFactory) { } diff --git a/src/services/inventory/v1/UseCases/HealthController.cs b/src/services/inventory/v1/UseCases/HealthController.cs deleted file mode 100644 index 3f373569..00000000 --- a/src/services/inventory/v1/UseCases/HealthController.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.EfCore.Extensions; -using VND.CoolStore.Services.Inventory.Infrastructure.Db; - -namespace VND.CoolStore.Services.Inventory.v1.UseCases -{ - [Route("")] - [ApiVersionNeutral] - [ApiExplorerSettings(IgnoreApi = true)] - public class HealthController : Controller - { - private readonly IServiceProvider _serviceProvider; - public HealthController(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - [HttpGet("/healthz")] - public ActionResult Get() - { - try - { - _serviceProvider.MigrateDbContext(); - } - catch (Exception) - { - - return new BadRequestResult(); - } - - return Ok(); - } - } -} diff --git a/src/services/inventory/v1/UseCases/HomeController.cs b/src/services/inventory/v1/UseCases/HomeController.cs deleted file mode 100644 index 897300f3..00000000 --- a/src/services/inventory/v1/UseCases/HomeController.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using NetCoreKit.Infrastructure.AspNetCore.Extensions; - -namespace VND.CoolStore.Services.Inventory.v1.UseCases -{ - [Route("")] - [ApiVersionNeutral] - [ApiExplorerSettings(IgnoreApi = true)] - public class HomeController : Controller - { - private readonly string _basePath; - public HomeController(IConfiguration config) - { - _basePath = config.GetBasePath() ?? "/"; - } - - [HttpGet] - public IActionResult Index() - { - return Redirect($"~{_basePath}swagger"); - } - } -} diff --git a/src/services/review/Dockerfile b/src/services/review/Dockerfile index 29a050cb..b9a3f37e 100644 --- a/src/services/review/Dockerfile +++ b/src/services/review/Dockerfile @@ -1,6 +1,9 @@ FROM microsoft/dotnet:2.1.2-aspnetcore-runtime-alpine AS base WORKDIR /app +ENV PROJECT /src/src/services/review +ENV EXECUTE_FILE VND.CoolStore.Services.Review.dll + ARG service_version ENV SERVICE_VERSION ${service_version:-0.0.1} @@ -14,7 +17,7 @@ FROM microsoft/dotnet:2.1.302-sdk-alpine AS build WORKDIR /src COPY . . -WORKDIR /src/src/services/review +WORKDIR $PROJECT RUN dotnet restore -nowarn:msb3202,nu1503 RUN dotnet build --no-restore -c Release -o /app @@ -25,4 +28,4 @@ RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . -ENTRYPOINT ["dotnet", "VND.CoolStore.Services.Review.dll"] +ENTRYPOINT ["dotnet", "$EXECUTE_FILE"] diff --git a/src/services/review/Domain/Review.cs b/src/services/review/Domain/Review.cs index b2620108..b68dc42c 100644 --- a/src/services/review/Domain/Review.cs +++ b/src/services/review/Domain/Review.cs @@ -11,7 +11,7 @@ internal Review(string content) : base(Guid.NewGuid()) Content = content; } - public Review(Guid id, string content) : base(id) + internal Review(Guid id, string content) : base(id) { Content = content; } diff --git a/src/services/review/Domain/ReviewAuthor.cs b/src/services/review/Domain/ReviewAuthor.cs index 3d9060bf..43530978 100644 --- a/src/services/review/Domain/ReviewAuthor.cs +++ b/src/services/review/Domain/ReviewAuthor.cs @@ -6,7 +6,7 @@ namespace VND.CoolStore.Services.Review.Domain { public class ReviewAuthor : IdentityBase { - internal ReviewAuthor() : base() + private ReviewAuthor() { } diff --git a/src/services/review/Domain/ReviewProduct.cs b/src/services/review/Domain/ReviewProduct.cs index 7e1c2d9b..8c5739ec 100644 --- a/src/services/review/Domain/ReviewProduct.cs +++ b/src/services/review/Domain/ReviewProduct.cs @@ -6,17 +6,21 @@ namespace VND.CoolStore.Services.Review.Domain { public class ReviewProduct : IdentityBase { + private ReviewProduct() + { + } + internal ReviewProduct(Guid id) : this(id, string.Empty, 0.0D, string.Empty) { } - public ReviewProduct(string name, double price, string desc) + internal ReviewProduct(string name, double price, string desc) : this(Guid.NewGuid(), name, price, desc) { } - public ReviewProduct(Guid id, string name, double price, string desc) + internal ReviewProduct(Guid id, string name, double price, string desc) { Id = id; Name = name; diff --git a/src/services/review/Dtos/ReviewDto.cs b/src/services/review/Dtos/ReviewDto.cs index 66a8e5b9..c6359446 100644 --- a/src/services/review/Dtos/ReviewDto.cs +++ b/src/services/review/Dtos/ReviewDto.cs @@ -8,5 +8,7 @@ public partial class ReviewDto public string Content { get; set; } public Guid AuthorId { get; set; } public string AuthorName { get; set; } + public Guid ProductId { get; set; } + public string ProductName { get; set; } } } diff --git a/src/services/review/Extensions/ReviewExtensions.cs b/src/services/review/Extensions/ReviewExtensions.cs index 0929d23e..0c20f88f 100644 --- a/src/services/review/Extensions/ReviewExtensions.cs +++ b/src/services/review/Extensions/ReviewExtensions.cs @@ -11,7 +11,9 @@ public static ReviewDto ToDto(this Domain.Review review) Id = review.Id, Content = review.Content, AuthorId = review.ReviewAuthor.Id, - AuthorName = review.ReviewAuthor.UserName + AuthorName = review.ReviewAuthor.UserName, + ProductId = review.ReviewProduct.Id, + ProductName = review.ReviewProduct.Name }; } } diff --git a/src/services/review/Migrations/20180810131836_InitReviewDb.Designer.cs b/src/services/review/Migrations/20180819091438_InitReviewDb.Designer.cs similarity index 89% rename from src/services/review/Migrations/20180810131836_InitReviewDb.Designer.cs rename to src/services/review/Migrations/20180819091438_InitReviewDb.Designer.cs index 2ce9bfb4..e4a3370e 100644 --- a/src/services/review/Migrations/20180810131836_InitReviewDb.Designer.cs +++ b/src/services/review/Migrations/20180819091438_InitReviewDb.Designer.cs @@ -2,7 +2,6 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using VND.CoolStore.Services.Review.Infrastructure.Db; @@ -10,7 +9,7 @@ namespace VND.CoolStore.Services.Review.Migrations { [DbContext(typeof(ReviewDbContext))] - [Migration("20180810131836_InitReviewDb")] + [Migration("20180819091438_InitReviewDb")] partial class InitReviewDb { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -18,8 +17,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "2.1.1-rtm-30846") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("VND.CoolStore.Services.Review.Domain.Review", b => { @@ -51,8 +49,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("UserId"); - b.HasKey("Id"); b.ToTable("ReviewAuthors"); @@ -63,8 +59,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ProductId"); - b.HasKey("Id"); b.ToTable("ReviewProducts"); diff --git a/src/services/review/Migrations/20180810131836_InitReviewDb.cs b/src/services/review/Migrations/20180819091438_InitReviewDb.cs similarity index 91% rename from src/services/review/Migrations/20180810131836_InitReviewDb.cs rename to src/services/review/Migrations/20180819091438_InitReviewDb.cs index df37a353..32b1db4a 100644 --- a/src/services/review/Migrations/20180810131836_InitReviewDb.cs +++ b/src/services/review/Migrations/20180819091438_InitReviewDb.cs @@ -11,8 +11,7 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "ReviewAuthors", columns: table => new { - Id = table.Column(nullable: false), - UserId = table.Column(nullable: false) + Id = table.Column(nullable: false) }, constraints: table => { @@ -23,8 +22,7 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "ReviewProducts", columns: table => new { - Id = table.Column(nullable: false), - ProductId = table.Column(nullable: false) + Id = table.Column(nullable: false) }, constraints: table => { diff --git a/src/services/review/Migrations/ReviewDbContextModelSnapshot.cs b/src/services/review/Migrations/ReviewDbContextModelSnapshot.cs index e7263679..6bd929f3 100644 --- a/src/services/review/Migrations/ReviewDbContextModelSnapshot.cs +++ b/src/services/review/Migrations/ReviewDbContextModelSnapshot.cs @@ -2,7 +2,6 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using VND.CoolStore.Services.Review.Infrastructure.Db; @@ -16,8 +15,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "2.1.1-rtm-30846") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("VND.CoolStore.Services.Review.Domain.Review", b => { @@ -49,8 +47,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("UserId"); - b.HasKey("Id"); b.ToTable("ReviewAuthors"); @@ -61,8 +57,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ProductId"); - b.HasKey("Id"); b.ToTable("ReviewProducts"); diff --git a/src/services/review/Program.cs b/src/services/review/Program.cs index 8a155d8e..8dc05b51 100644 --- a/src/services/review/Program.cs +++ b/src/services/review/Program.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using NetCoreKit.Infrastructure.EfCore.Extensions; using VND.CoolStore.Services.Review.Infrastructure.Db; @@ -9,18 +10,15 @@ public class Program { public static void Main(string[] args) { - var webHost = BuildWebHost(args); - if ((webHost.Services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment).IsDevelopment()) - { + var webHost = CreateWebHostBuilder(args).Build(); + var env = webHost.Services.GetService(); + if (env.IsDevelopment()) webHost = webHost.RegisterDbContext(); - } - webHost.Run(); } - public static IWebHost BuildWebHost(string[] args) => + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); + .UseStartup(); } } diff --git a/src/services/review/Startup.cs b/src/services/review/Startup.cs index f462dc8d..8db27f86 100644 --- a/src/services/review/Startup.cs +++ b/src/services/review/Startup.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using NetCoreKit.Infrastructure.AspNetCore.Miniservice; -using NetCoreKit.Infrastructure.EfCore.SqlServer; +using NetCoreKit.Infrastructure.EfCore.MySql; using VND.CoolStore.Services.Review.Infrastructure.Db; namespace VND.CoolStore.Services.Review @@ -13,33 +12,30 @@ public class Startup { public void ConfigureServices(IServiceCollection services) { - var assemblies = new HashSet - { - typeof(Startup).GetTypeInfo().Assembly, - typeof(MiniServiceExtensions).GetTypeInfo().Assembly - }; - - var claimToScopeMap = new Dictionary - { - {"access_review_api", "review_api_scope"} - }; - - var scopes = new Dictionary - { - {"review_api_scope", "Review APIs"} - }; - - var serviceParams = new ServiceParams - { - {"assemblies", assemblies}, - {"audience", "api"}, - {"claimToScopeMap", claimToScopeMap}, - {"scopes", scopes} - }; - - services.AddScoped(sp => serviceParams); - services.AddEfCoreSqlServer(); - services.AddMiniService(); + services.AddMiniService( + new[] { typeof(Startup) }, + svc => + { + //svc.AddEfCoreMySqlDb(); + svc.AddExternalSystemHealthChecks(); + }, + () => new Dictionary + { + { + Constants.ClaimToScopeMap, new Dictionary + { + {"access_review_api", "review_api_scope"} + } + }, + { + Constants.Scopes, new Dictionary + { + {"review_api_scope", "Review APIs"} + } + }, + {Constants.Audience, "api"} + } + ); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) diff --git a/src/services/review/VND.CoolStore.Services.Review.csproj b/src/services/review/VND.CoolStore.Services.Review.csproj index 236b4f83..b00f5d55 100644 --- a/src/services/review/VND.CoolStore.Services.Review.csproj +++ b/src/services/review/VND.CoolStore.Services.Review.csproj @@ -7,18 +7,24 @@ - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/services/review/appsettings.Development.json b/src/services/review/appsettings.Development.json index 0b406aff..26f15268 100644 --- a/src/services/review/appsettings.Development.json +++ b/src/services/review/appsettings.Development.json @@ -1,10 +1,11 @@ { "ConnectionStrings": { - "mssqldb": "Server=tcp:127.0.0.1,1433;Database=maindb;User Id=cs;Password=P@ssw0rd;" + "mssqldb": "Server=tcp:127.0.0.1,1433;Database=maindb;User Id=cs;Password=P@ssw0rd;", + "mysqldb": "server=127.0.0.1;port=3306;uid=root;pwd=P@ssw0rd;database=maindb" }, "Hosts": { "Externals": { - "CurrentUri": "http://localhost:5003", + "CurrentUri": "http://localhost:5006", "Auth": { "Uri": "http://localhost:5001" } diff --git a/src/services/review/appsettings.json b/src/services/review/appsettings.json index eca7924e..101e08dd 100644 --- a/src/services/review/appsettings.json +++ b/src/services/review/appsettings.json @@ -16,6 +16,17 @@ "Database": "maindb", "UserName": "cs", "Password": "P@ssw0rd" + }, + "mysqldb": { + "Host": "CART_DB_SERVICE_SERVICE_HOST", + "Port": "CART_DB_SERVICE_SERVICE_PORT", + "Database": "maindb", + "UserName": "root", + "Password": "P@ssw0rd", + "Major": 8, + "Minor": 0, + "Build": 12, + "DbType": 0 } }, "Hosts": { diff --git a/src/services/review/v1/HealthController.cs b/src/services/review/v1/HealthController.cs deleted file mode 100644 index 0be618ef..00000000 --- a/src/services/review/v1/HealthController.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.EfCore.Extensions; -using VND.CoolStore.Services.Review.Infrastructure.Db; - -namespace VND.CoolStore.Services.Review.v1 -{ - [Route("")] - [ApiVersionNeutral] - [ApiExplorerSettings(IgnoreApi = true)] - public class HealthController : Controller - { - private readonly IServiceProvider _serviceProvider; - public HealthController(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - [HttpGet("/healthz")] - public ActionResult Get() - { - try - { - _serviceProvider.MigrateDbContext(); - } - catch (Exception) - { - - return new BadRequestResult(); - } - - return Ok(); - } - } -} diff --git a/src/services/review/v1/HomeController.cs b/src/services/review/v1/HomeController.cs deleted file mode 100644 index 6dd9ab37..00000000 --- a/src/services/review/v1/HomeController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using NetCoreKit.Infrastructure.AspNetCore.Extensions; -using NetCoreKit.Infrastructure.AspNetCore.Miniservice.Options; - -namespace VND.CoolStore.Services.Review.v1 -{ - [Route("")] - [ApiVersionNeutral] - [ApiExplorerSettings(IgnoreApi = true)] - public class HomeController : Controller - { - private readonly string _basePath; - public HomeController(IConfiguration config, IOptions options) - { - _basePath = config.GetBasePath() ?? "/"; - } - - [HttpGet] - public IActionResult Index() - { - return Redirect($"~{_basePath}swagger"); - } - } -} diff --git a/src/services/review/v1/UseCases/AddReview/Controller.cs b/src/services/review/v1/UseCases/AddReview/Controller.cs deleted file mode 100644 index 184ea425..00000000 --- a/src/services/review/v1/UseCases/AddReview/Controller.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Review.v1.UseCases.AddReview -{ - [ApiVersion("1.0")] - [Route("api/reviews")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpPost] - [Auth(Policy = "access_review_api")] - public async Task Post(AddReviewRequest request) => - await Eventor.SendStream(request, x => x.Result); - } -} diff --git a/src/services/review/v1/UseCases/AddReview/RequestHandler.cs b/src/services/review/v1/UseCases/AddReview/RequestHandler.cs index 32f57410..23923d95 100644 --- a/src/services/review/v1/UseCases/AddReview/RequestHandler.cs +++ b/src/services/review/v1/UseCases/AddReview/RequestHandler.cs @@ -12,17 +12,19 @@ public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf) : base( { } - public override async Task TxHandle(AddReviewRequest request, + public override async Task Handle(AddReviewRequest request, CancellationToken cancellationToken) { var reviewRepository = UnitOfWork.Repository(); var review = Domain.Review.Load(request.Content) - .AddAuthor(request.UserId) - .AddProduct(request.ProductId); + .AddAuthor(request.UserId) + .AddProduct(request.ProductId); var result = await reviewRepository.AddAsync(review); - return new AddReviewResponse { Result = result.ToDto()}; + await UnitOfWork.SaveChangesAsync(cancellationToken); + + return new AddReviewResponse {Result = result.ToDto()}; } } } diff --git a/src/services/review/v1/UseCases/GetReviews/Controller.cs b/src/services/review/v1/UseCases/GetReviews/Controller.cs deleted file mode 100644 index 1d1a8f63..00000000 --- a/src/services/review/v1/UseCases/GetReviews/Controller.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Review.v1.UseCases.GetReviews -{ - [ApiVersion("1.0")] - [Route("api/products")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpGet] - [Auth(Policy = "access_review_api")] - [Route("{productId:guid}/reviews")] - public async Task Delete(Guid productId) - { - return await Eventor.SendStream( - new GetReviewsRequest {ProductId = productId}, - x => x.Reviews); - } - } -} diff --git a/src/services/review/v1/UseCases/GetReviews/RequestHandler.cs b/src/services/review/v1/UseCases/GetReviews/RequestHandler.cs index e3fc7eb6..24e67628 100644 --- a/src/services/review/v1/UseCases/GetReviews/RequestHandler.cs +++ b/src/services/review/v1/UseCases/GetReviews/RequestHandler.cs @@ -1,7 +1,5 @@ using System; using System.Linq; -using System.Reactive.Linq; -using System.Reactive.Threading.Tasks; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -14,7 +12,7 @@ namespace VND.CoolStore.Services.Review.v1.UseCases.GetReviews { public class RequestHandler : RequestHandlerBase { - public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf) : base(uow, qrf) + public RequestHandler(IQueryRepositoryFactory qrf) : base(qrf) { } @@ -27,18 +25,15 @@ public override async Task Handle(GetReviewsRequest request, .ListAsync( queryable => queryable .Include(x => x.ReviewAuthor) - .Include(x => x.ReviewProduct)) - .ToObservable() - .Select(x => x.Where(y => y.ReviewProduct.Id == request.ProductId)); + .Include(x => x.ReviewProduct)); - if (reviews == null) - { - throw new Exception($"Could not find a review with product#{request.ProductId}."); - } + var result = reviews.Where(x => x.ReviewProduct?.Id == request.ProductId); + + if (reviews == null) throw new Exception($"Couldn't find a review with product#{request.ProductId}."); return new GetReviewsResponse { - Reviews = reviews + Reviews = result .Select(x => x.ToDto()) .ToList() }; diff --git a/src/services/review/v1/UseCases/RemoveReview/Controller.cs b/src/services/review/v1/UseCases/RemoveReview/Controller.cs deleted file mode 100644 index ad4e015a..00000000 --- a/src/services/review/v1/UseCases/RemoveReview/Controller.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Review.v1.UseCases.RemoveReview -{ - [ApiVersion("1.0")] - [Route("api/reviews")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpDelete] - [Auth(Policy = "access_review_api")] - [Route("{reviewId:guid}")] - public async Task Delete(Guid reviewId) - { - return await Eventor.SendStream( - new RemoveReviewRequest {ReviewId = reviewId}, - x => x.ReviewId); - } - } -} diff --git a/src/services/review/v1/UseCases/RemoveReview/RequestHandler.cs b/src/services/review/v1/UseCases/RemoveReview/RequestHandler.cs index 24d7adeb..309bc1dc 100644 --- a/src/services/review/v1/UseCases/RemoveReview/RequestHandler.cs +++ b/src/services/review/v1/UseCases/RemoveReview/RequestHandler.cs @@ -13,19 +13,18 @@ public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf) : base( { } - public override async Task TxHandle(RemoveReviewRequest request, + public override async Task Handle(RemoveReviewRequest request, CancellationToken cancellationToken) { var reviewQueryRepo = QueryRepositoryFactory.QueryEfRepository(); var reviewRepo = UnitOfWork.Repository(); var review = await reviewQueryRepo.FindOneAsync(x => x.Id == request.ReviewId); - if (review == null) - { - throw new Exception($"Could not find a review #{request.ReviewId}."); - } + if (review == null) throw new Exception($"Could not find a review #{request.ReviewId}."); var result = await reviewRepo.DeleteAsync(review); + await UnitOfWork.SaveChangesAsync(cancellationToken); + return new RemoveReviewResponse {ReviewId = result.Id}; } } diff --git a/src/services/review/v1/UseCases/ReviewController.cs b/src/services/review/v1/UseCases/ReviewController.cs new file mode 100644 index 00000000..df71620d --- /dev/null +++ b/src/services/review/v1/UseCases/ReviewController.cs @@ -0,0 +1,59 @@ +using System; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using NetCoreKit.Infrastructure.AspNetCore.Authz; +using NetCoreKit.Infrastructure.AspNetCore.CleanArch; +using VND.CoolStore.Services.Review.v1.UseCases.AddReview; +using VND.CoolStore.Services.Review.v1.UseCases.GetReviews; +using VND.CoolStore.Services.Review.v1.UseCases.RemoveReview; +using VND.CoolStore.Services.Review.v1.UseCases.UpdateReview; + +namespace VND.CoolStore.Services.Review.v1.UseCases +{ + [ApiVersion("1.0")] + [Route("api/reviews")] + public class ReviewController : Controller + { + [HttpGet] + //[Auth(Policy = "access_review_api")] + [Route("{productId:guid}/reviews")] + public async Task Get([FromServices] IMediator eventor, Guid productId, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new GetReviewsRequest { ProductId = productId }, + x => x.Reviews); + } + + [HttpPost] + [Auth(Policy = "access_review_api")] + public async Task Post([FromServices] IMediator eventor, AddReviewRequest request, CancellationToken cancellationToken) => + await eventor.SendStream(request, x => x.Result); + + [HttpDelete] + [Auth(Policy = "access_review_api")] + [Route("{reviewId:guid}")] + public async Task Delete([FromServices] IMediator eventor, Guid reviewId, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new RemoveReviewRequest { ReviewId = reviewId }, + x => x.ReviewId); + } + + [HttpPut] + [Auth(Policy = "access_review_api")] + [Route("{reviewId:guid}/{content}")] + public async Task Put([FromServices] IMediator eventor, Guid reviewId, string content, CancellationToken cancellationToken) + { + return await eventor.SendStream( + new UpdateReviewRequest + { + ReviewId = reviewId, + Content = content + }, + x => x.Result); + } + } +} diff --git a/src/services/review/v1/UseCases/UpdateReview/Controller.cs b/src/services/review/v1/UseCases/UpdateReview/Controller.cs deleted file mode 100644 index 7372dab1..00000000 --- a/src/services/review/v1/UseCases/UpdateReview/Controller.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Reactive.Linq; -using System.Threading.Tasks; -using MediatR; -using Microsoft.AspNetCore.Mvc; -using NetCoreKit.Infrastructure.AspNetCore; -using NetCoreKit.Infrastructure.AspNetCore.CleanArch; - -namespace VND.CoolStore.Services.Review.v1.UseCases.UpdateReview -{ - [ApiVersion("1.0")] - [Route("api/reviews")] - public class Controller : EvtControllerBase - { - public Controller(IMediator mediator) : base(mediator) { } - - [HttpPut] - [Auth(Policy = "access_review_api")] - [Route("{reviewId:guid}/{content}")] - public async Task Put(Guid reviewId, string content) - { - return await Eventor.SendStream( - new UpdateReviewRequest - { - ReviewId = reviewId, - Content = content - }, - x => x.Result); - } - } -} diff --git a/src/services/review/v1/UseCases/UpdateReview/RequestHandler.cs b/src/services/review/v1/UseCases/UpdateReview/RequestHandler.cs index 78978561..8cb68a3c 100644 --- a/src/services/review/v1/UseCases/UpdateReview/RequestHandler.cs +++ b/src/services/review/v1/UseCases/UpdateReview/RequestHandler.cs @@ -14,22 +14,20 @@ public RequestHandler(IUnitOfWorkAsync uow, IQueryRepositoryFactory qrf) : base( { } - public override async Task TxHandle(UpdateReviewRequest request, + public override async Task Handle(UpdateReviewRequest request, CancellationToken cancellationToken) { var reviewQueryRepo = QueryRepositoryFactory.QueryEfRepository(); var reviewRepo = UnitOfWork.Repository(); var review = await reviewQueryRepo.FindOneAsync(x => x.Id == request.ReviewId); - if (review == null) - { - throw new Exception($"Could not find a review #{request.ReviewId}."); - } + if (review == null) throw new Exception($"Could not find a review #{request.ReviewId}."); review.Content = request.Content; var result = await reviewRepo.UpdateAsync(review); + await UnitOfWork.SaveChangesAsync(cancellationToken); - return new UpdateReviewResponse { Result = result.ToDto()}; + return new UpdateReviewResponse {Result = result.ToDto()}; } } } From 6ce2014ac2c3543827db7ea33edf9fd3dd2ff30d Mon Sep 17 00:00:00 2001 From: Thang Chung Date: Sun, 19 Aug 2018 17:23:10 +0700 Subject: [PATCH 2/2] update readme --- README.md | 85 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 1b991b32..3f68570a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cool Store Application on Service Mesh +# Cool Store: Cloud-Native Microservices Application on Service Mesh

Price @@ -12,14 +12,16 @@ CoolStore is a containerised polyglot microservices application consisting of se It demonstrates how to wire up small microservices into a larger application using microservice architectural principals. ### Presentation +Our team uses this application to demonstrate Kubernetes, AKS, Istio and similar cloud-native technologies in events as following + - [From Microservices to Service Mesh - DevCafe Event - July 2018](https://www.slideshare.net/ThangChung/from-microservices-to-service-mesh-devcafe-event-july-2018) - [Service Mesh for Microservices- Vietnam Mobile Day Event - June 2018](https://www.slideshare.net/ThangChung/service-mesh-for-microservices-vietnam-mobile-day-june-2017) # Table of contents * [Prerequisites](https://github.com/vietnam-devs/coolstore-microservices#prerequisites) -* [Services](https://github.com/vietnam-devs/coolstore-microservices#services) -* [Up and Running](https://github.com/vietnam-devs/coolstore-microservices#up-and-running) +* [µServices](https://github.com/vietnam-devs/coolstore-microservices#services) +* [Installation](https://github.com/vietnam-devs/coolstore-microservices#up-and-running) * [µService Development](https://github.com/vietnam-devs/coolstore-microservices#microservice-development) * [Open API](https://github.com/vietnam-devs/coolstore-microservices#open-api) * [CI/CD](https://github.com/vietnam-devs/coolstore-microservices#ci-cd) @@ -27,49 +29,46 @@ It demonstrates how to wire up small microservices into a larger application usi * [Contributors](https://github.com/vietnam-devs/coolstore-microservices#contributors) * [Licence](https://github.com/vietnam-devs/coolstore-microservices#licence) -### Prerequisites +## Prerequisites - Windows 10 - Windows Subsystem Linux (WSL - Ubuntu OS) -- Docker for Windows (Kubernetes enabled) +- Docker for Desktop (Kubernetes enabled) - kubectl - helm - istioctl -### Services - -There are several individual microservices and infrastructure components that make up this app: - -1. Catalog Service: NodeJS service and MongoDB, serves products and prices for retail products - - [`http://localhost:5002`](http://localhost:5002) - - [`http://api.coolstore.local/catalog`](http://api.coolstore.local/catalog/swagger/) -2. Cart Service: .NET Core service which manages shopping cart for each customer - - [`http://localhost:5003`](http://localhost:5003) - - [`http://api.coolstore.local/cart`](http://api.coolstore.local/cart/swagger/) -3. Inventory Service: .NET Core service and SQL Server, serves inventory and availability data for retail products - - [`http://localhost:5004`](http://localhost:5004) - - [`http://api.coolstore.local/inventory`](http://api.coolstore.local/inventory/swagger/) -4. Pricing Service: .NET Core service which is a business rules application for product pricing - - [`http://localhost:5005`](http://localhost:5005) - - [`http://api.coolstore.local/pricing`](http://api.coolstore.local/pricing/swagger/) -5. Review Service: .NET Core service and SQL Server running for writing and displaying reviews for products - - [`http://localhost:5006`](http://localhost:5006) - - [`http://api.coolstore.local/review`](http://api.coolstore.local/review/swagger/) -6. Rating Service: NodeJS service running for rating products - - [`http://localhost:5007`](http://localhost:5007) - - [`http://api.coolstore.local/rating`](http://api.coolstore.local/rating/swagger/) -7. IdP: Identity Provider using [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) to authentication with OAuth 2.0 and OpenID Connect for the whole stack - - [`http://localhost:5001`](http://localhost:5001) - - [`http://id.coolstore.local`](http://id.coolstore.local) -8. Web UI (PWA): A frontend based on [vuejs](https://vuejs.org/) and [Node.js](https://nodejs.org) - - [`http://localhost:8080`](http://localhost:8080) - - [`http://coolstore.local`](http://coolstore.local) +## µServices + +There are several individual µservices and infrastructure components that make up this app: + +| No. | Service | Language | Database | Description | Endpoints | +|-----|---------|----------|----------|-------------|-----------| +| 1 | Catalog | Node.js | Mongo | Serves products and prices for retail products | [`http://localhost:5002`](http://localhost:5002) or [`http://api.coolstore.local/catalog`](http://api.coolstore.local/catalog/swagger) +| 2 | Cart | .NET Core | MySQL | Manages shopping cart for each customer | [`http://localhost:5003`](http://localhost:5003) or [`http://api.coolstore.local/cart`](http://api.coolstore.local/cart/swagger) +| 3 | Inventory | .NET Core | MySQL | Serves inventory and availability data for retail products | [`http://localhost:5004`](http://localhost:5004) or [`http://api.coolstore.local/inventory`](http://api.coolstore.local/inventory/swagger) +| 4 | Pricing | .NET Core | MySQL | Handles a business rules application for product pricing | [`http://localhost:5005`](http://localhost:5005) or [`http://api.coolstore.local/pricing`](http://api.coolstore.local/pricing/swagger) +| 5 | Review | .NET Core | MySQL | Runs for writing and displaying reviews for products | [`http://localhost:5006`](http://localhost:5006) or [`http://api.coolstore.local/review`](http://api.coolstore.local/review/swagger) +| 6 | Rating | Node.js | Mongo | Runs for rating products | [`http://localhost:5007`](http://localhost:5007) or [`http://api.coolstore.local/rating`](http://api.coolstore.local/rating/swagger) +| 7 | IdP | .NET Core | In Memory | Uses [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) to authentication with OAuth 2.0 and OpenID Connect for the whole stack | [`http://localhost:5001`](http://localhost:5001) or [`http://id.coolstore.local`](http://id.coolstore.local) +| 8 | Web UI (PWA) | Vuejs + Node.js | N/A | Frontend based on [vuejs](https://vuejs.org/) and [Node.js](https://nodejs.org) | [`http://localhost:8080`](http://localhost:8080) or [`http://coolstore.local`](http://coolstore.local) + +### Architecture of µServices ![Architecture Screenshot](assets/images/arch-diagram.png?raw=true 'Architecture Diagram') -### Up and Running +## Features +- **[Kubernetes](https://kubernetes.io)/[AKS](https://docs.microsoft.com/en-us/azure/aks):** + The app is designed to run on Kubernetes (both locally on "Docker for + Desktop", as well as on the cloud with AKS). +- **[Istio](https://istio.io):** Application works on Istio service mesh. +- **[NetCoreKit](https://github.com/cloudnative-netcore/netcore-kit):** Set of Cloud Native tools and utilities for .NET Core. -1. Make sure we have **`Docker for Windows`** running with **`Kubernetes`** option enabled. We need to install **`kubectl`**, **`helm`** and **`istioctl`** on the build machine as well. +## Installation + +### Option 1: Up and Running locally with "Docker for Desktop", development only + +1. Make sure we have **`Docker for Desktop`** running with **`Kubernetes`** option enabled. We need to install **`kubectl`**, **`helm`** and **`istioctl`** on the build machine as well. 2. From current console, type `bash` to enter `Linux Subsystem (Ubuntu)` @@ -149,19 +148,23 @@ Waiting for the container provision completed > helm install --name cs-nginx stable/nginx-ingress > ``` -### µService Development +### Option 2: Up and Running on Azure Kubernetes Service (AKS) + +TODO + +## µService Development ![µService Screenshot](assets/images/miniservice-development.PNG?raw=true 'Microservice') -### Open API +## Open API ![OpenAPI Screenshot](assets/images/open-api.png?raw=true 'OpenAPI') -### CI/CD +## CI/CD ![Lift and Shift](assets/images/lift-and-shift.PNG?raw=true 'liftandshift') -### Contributing +## Contributing 1. Fork it! 2. Create your feature branch: `git checkout -b my-new-feature` @@ -169,12 +172,12 @@ Waiting for the container provision completed 4. Push to the branch: `git push origin my-new-feature` 5. Submit a pull request :p -### Contributors +## Contributors | [Thang Chung](https://github.com/thangchung) | [Thinh Nguyen](https://github.com/thinhnotes) | | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | thangchung | thinhnguyen | -### Licence +## Licence Code released under [the MIT license](https://github.com/vietnam-devs/coolstore-microservices/blob/master/LICENSE).