From 734b2c91f98073731d1e1fdddefafd76d3b80422 Mon Sep 17 00:00:00 2001 From: ShaoHua <345265198@qqcom> Date: Thu, 16 Jul 2026 02:43:29 +0800 Subject: [PATCH] =?UTF-8?q?build:=20=E5=8D=87=E7=BA=A7=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=E5=88=B0net10.0=E5=B9=B6=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 将Hua.Cli.Tests、项目共享库、模块项目等所有项目的TargetFramework从net8.0/net9.0升级到net10.0 2. 完善dotnet-tools.json、模板配置文件,添加必要的构建和发布配置 3. 新增微服务、网关、应用程序的启动脚本和基础配置文件 4. 补充产品管理模块的领域、应用、Web层基础代码和多语言资源 --- Hua.Cli.sln | 12 +- Hua.Cli.slnx | 8 + docs/AI/Ms模板差异清单.md | 100 +++++ docs/PRD.md | 345 -------------- dotnet-tools.json | 5 + scripts/install-local.ps1 | 29 ++ src/Hua.Cli.Core/Hua.Cli.Core.csproj | 6 +- .../ProjectBuilding/TemplateProjectBuilder.cs | 161 ++++--- src/Hua.Cli.Core/Hua/Cli/Utils/CmdHelper.cs | 35 +- src/Hua.Cli/Hua.Cli.csproj | 10 +- templates/app/.template.config/template.json | 23 + templates/app/Company.Project.sln | 55 +++ ...mpany.Project.Application.Contracts.csproj | 7 + .../ProjectApplicationContractsModule.cs | 6 + .../Company.Project.Application.csproj | 8 + .../ProjectApplicationModule.cs | 9 + .../Company.Project.Domain.Shared.csproj | 4 + .../ProjectDomainSharedModule.cs | 6 + .../Company.Project.Domain.csproj | 7 + .../ProjectDomainModule.cs | 6 + ...Company.Project.EntityFrameworkCore.csproj | 7 + .../ProjectDbContext.cs | 9 + .../ProjectEntityFrameworkCoreModule.cs | 6 + .../Company.Project.HttpApi.Host.csproj | 13 + .../Company.Project.HttpApi.Host/Program.cs | 34 ++ .../ProjectHttpApiHostModule.cs | 40 ++ .../Company.Project.HttpApi.Host/Startup.cs | 18 + .../appsettings.json | 7 + .../Company.Project.HttpApi.csproj | 7 + .../ProjectHttpApiModule.cs | 6 + templates/ms/.dockerignore | 25 ++ templates/ms/.template.config/template.json | 14 +- templates/ms/Company.Project.sln | 208 +++++++++ templates/ms/DeployToKubernetes.sh | 4 + templates/ms/README.md | 70 +++ templates/ms/_run/01_AuthServer.ps1 | 2 + templates/ms/_run/02_IdentityService.ps1 | 2 + .../ms/_run/03_TenantManagementService.ps1 | 2 + templates/ms/_run/04_BloggingService.ps1 | 2 + templates/ms/_run/05_ProductService.ps1 | 2 + templates/ms/_run/06_InternalGateway.ps1 | 2 + .../ms/_run/07_BackendAdminAppGateway.ps1 | 2 + templates/ms/_run/08_PublicWebSiteGateway.ps1 | 2 + templates/ms/_run/09_BackendAdminApp.ps1 | 2 + templates/ms/_run/10_PublicWebSite.ps1 | 2 + templates/ms/_run/11_ConsoleClientDemo.ps1 | 2 + templates/ms/_run/README.md | 24 + templates/ms/_run/__Run_All_Application.ps1 | 36 ++ templates/ms/_run/__Run_Browser.ps1 | 8 + templates/ms/_run/__Run_Infrastructure.ps1 | 3 + templates/ms/_run/__Stop_Infrastructure.ps1 | 3 + .../AuthServerDataSeeder.cs | 243 ++++++++++ .../BrandingProvider.cs | 9 + .../Company.Project.AuthServer.Host.csproj | 8 +- .../Dockerfile | 20 + .../Dockerfile.original | 20 + .../AuthServerDbContext.cs | 33 ++ .../AuthServerDbContextFactory.cs | 28 ++ .../Pages/Index.cshtml | 33 ++ .../Pages/Index.cshtml.cs | 10 + .../Pages/_ViewImports.cshtml | 4 + .../Properties/launchSettings.json | 27 ++ .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 9 + .../gulpfile.js | 9 + .../package.json | 8 + .../tempkey.rsa | 1 + .../wwwroot/images/anonymous-user.png | Bin 0 -> 23671 bytes .../Company.Project.AuthServer.Host/yarn.lock | 337 ++++++++++++++ .../BackendAdminAppMenuContributor.cs | 40 ++ .../BrandingProvider.cs | 9 + ...ompany.Project.BackendAdminApp.Host.csproj | 2 +- .../Controllers/AccountController.cs | 8 + .../Controllers/HomeController.cs | 12 + .../Controllers/TestController.cs | 35 ++ .../Dockerfile | 25 ++ .../Dockerfile.original | 25 ++ .../Properties/launchSettings.json | 27 ++ .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 9 + .../appsettings.json | 20 + .../gulpfile.js | 9 + .../package.json | 8 + .../yarn.lock | 337 ++++++++++++++ .../ClientDemoService.cs | 146 ++++++ .../Company.Project.ConsoleClientDemo.csproj | 26 ++ .../ConsoleClientDemoHostedService.cs | 31 ++ .../ConsoleClientDemoModule.cs | 20 + .../Program.cs | 31 ++ .../appsettings.json | 17 + .../BrandingProvider.cs | 9 + .../Company.Project.PublicWebSite.Host.csproj | 22 + .../Dockerfile | 23 + .../Dockerfile.original | 23 + .../Pages/Index.cshtml | 158 +++++++ .../Pages/Index.cshtml.cs | 18 + .../Pages/Products.cshtml | 55 +++ .../Pages/Products.cshtml.cs | 23 + .../Pages/Products.css | 30 ++ .../Pages/_ViewImports.cshtml | 4 + .../Program.cs | 34 ++ .../Properties/launchSettings.json | 27 ++ .../PublicWebSiteHostModule.cs | 84 ++++ .../PublicWebSiteMenuContributor.cs | 21 + .../Startup.cs | 19 + .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 9 + .../appsettings.json | 19 + .../gulpfile.js | 9 + .../package.json | 8 + .../wwwroot/product-images/asus.jpg | Bin 0 -> 33856 bytes .../wwwroot/product-images/beats.jpg | Bin 0 -> 14994 bytes .../wwwroot/product-images/bluecat.jpg | Bin 0 -> 22493 bytes .../wwwroot/product-images/lego.jpg | Bin 0 -> 96032 bytes .../wwwroot/product-images/nikon.jpg | Bin 0 -> 48244 bytes .../wwwroot/product-images/noimage.jpg | Bin 0 -> 9672 bytes .../wwwroot/product-images/oki.jpg | Bin 0 -> 15514 bytes .../wwwroot/product-images/playstation.jpg | Bin 0 -> 12477 bytes .../wwwroot/product-images/rampage.jpg | Bin 0 -> 29142 bytes .../wwwroot/product-images/sunny.jpg | Bin 0 -> 68081 bytes .../yarn.lock | 422 ++++++++++++++++++ ...docker-compose.infrastructure.override.yml | 19 + .../ms/docker-compose.infrastructure.yml | 15 + templates/ms/docker-compose.migrations.yml | 12 + templates/ms/docker-compose.override.yml | 74 +++ templates/ms/docker-compose.yml | 60 +++ .../BackendAdminAppGatewayHostModule.cs | 93 ++++ ...Project.BackendAdminAppGateway.Host.csproj | 23 + .../Dockerfile | 23 + .../Dockerfile.original | 23 + .../Program.cs | 42 ++ .../Properties/launchSettings.json | 27 ++ .../Startup.cs | 18 + .../appsettings.Development.json | 9 + .../appsettings.json | 60 +++ ...ompany.Project.InternalGateway.Host.csproj | 2 +- .../Dockerfile | 23 + .../Dockerfile.original | 23 + .../Properties/launchSettings.json | 27 ++ .../TestController.cs | 29 ++ .../appsettings.Development.json | 9 + ...mpany.Project.PublicWebGateway.Host.csproj | 2 +- .../Dockerfile | 23 + .../Dockerfile.original | 23 + .../Properties/launchSettings.json | 27 ++ .../appsettings.Development.json | 9 + .../BlogServiceDataSeeder.cs | 101 +++++ .../BloggingServiceHostModule.cs | 129 ++++++ ...ompany.Project.BloggingService.Host.csproj | 27 ++ .../Controllers/HomeController.cs | 12 + .../Dockerfile | 20 + .../Dockerfile.original | 20 + .../Program.cs | 33 ++ .../Properties/launchSettings.json | 27 ++ .../Startup.cs | 18 + .../appsettings.Development.json | 9 + .../appsettings.json | 25 ++ ...ompany.Project.IdentityService.Host.csproj | 2 +- .../Controllers/HomeController.cs | 12 + .../Dockerfile | 20 + .../Dockerfile.original | 20 + .../Properties/launchSettings.json | 27 ++ .../TenantCreatedDistributedEventHandler.cs | 37 ++ .../appsettings.Development.json | 9 + ...Company.Project.ProductService.Host.csproj | 2 +- .../Controllers/HomeController.cs | 12 + .../Dockerfile | 26 ++ .../Dockerfile.original | 26 ++ .../ProductServiceMigrationDbContext.cs | 22 + ...ProductServiceMigrationDbContextFactory.cs | 28 ++ .../ProductServiceDataSeeder.cs | 47 ++ .../Properties/launchSettings.json | 27 ++ .../appsettings.Development.json | 9 + ...roject.TenantManagementService.Host.csproj | 26 ++ .../Controllers/HomeController.cs | 12 + .../Dockerfile | 20 + .../Dockerfile.original | 20 + .../Program.cs | 33 ++ .../Properties/launchSettings.json | 27 ++ .../Startup.cs | 18 + .../TenantManagementServiceHostModule.cs | 120 +++++ .../appsettings.Development.json | 9 + .../appsettings.json | 24 + .../CreateProductDto.cs | 21 + .../IProductAppService.cs | 20 +- .../IPublicProductAppService.cs | 10 + .../Localization/ApplicationContracts/cs.json | 10 + .../Localization/ApplicationContracts/en.json | 10 + .../ApplicationContracts/pl-PL.json | 10 + .../Localization/ApplicationContracts/tr.json | 10 + .../Localization/ApplicationContracts/vi.json | 10 + .../ProductDto.cs | 6 +- ...uctManagement.Application.Contracts.csproj | 2 +- ...uctManagementApplicationContractsModule.cs | 6 +- ...tManagementPermissionDefinitionProvider.cs | 23 + .../ProductManagementPermissions.cs | 21 + ...ductManagementSettingDefinitionProvider.cs | 17 + .../ProductManagementSettings.cs | 11 + .../UpdateProductDto.cs | 17 + .../ProductAppService.cs | 93 +++- .../ProductManagement.Application.csproj | 2 +- ...tManagementApplicationAutoMapperProfile.cs | 11 + .../PublicProductAppService.cs | 27 ++ .../Localization/ProductManagementResource.cs | 9 + .../ProductConsts.cs | 8 + .../ProductManagement.Domain.Shared.csproj | 2 +- .../ProductManagementDomainErrorCodes.cs | 6 + .../ProductManagementDomainSharedModule.cs | 14 +- .../ProductStockCountChangedEto.cs | 25 ++ .../Localization/Domain/cs.json | 5 + .../Localization/Domain/en.json | 6 + .../Localization/Domain/pl-PL.json | 6 + .../Localization/Domain/vi | 1 + .../Localization/Domain/vi.json | 5 + .../src/ProductManagement.Domain/Product.cs | 117 ++++- .../ProductCodeAlreadyExistsException.cs | 12 + .../ProductManagement.Domain.csproj | 2 +- .../ProductManagementConsts.cs | 8 + .../ProductManager.cs | 43 ++ .../IProductManagementDbContext.cs | 11 + ...oductManagement.EntityFrameworkCore.csproj | 2 +- .../ProductManagementDbContext.cs | 9 +- ...agementDbContextModelCreatingExtensions.cs | 36 ++ ...agementModelBuilderConfigurationOptions.cs | 15 + .../ProductManagement.HttpApi.Client.csproj | 2 +- .../ProductManagement.HttpApi.csproj | 2 +- .../ProductManagementHttpApiModule.cs | 6 +- .../ProductsController.cs | 62 +++ .../PublicProductsController.cs | 26 ++ .../Resources/ProductManagement/cs.json | 16 + .../Resources/ProductManagement/en.json | 16 + .../Resources/ProductManagement/pl-PL.json | 16 + .../Resources/ProductManagement/tr.json | 16 + .../Resources/ProductManagement/vi.json | 16 + .../ProductManagement/Products/Create.cshtml | 20 + .../Products/Create.cshtml.cs | 46 ++ .../ProductManagement/Products/Edit.cshtml | 20 + .../ProductManagement/Products/Edit.cshtml.cs | 55 +++ .../ProductManagement/Products/Index.cshtml | 47 ++ .../Products/Index.cshtml.cs | 11 + .../Pages/ProductManagement/Products/index.js | 76 ++++ .../ProductManagement/_ViewImports.cshtml | 4 + .../ProductManagement.Web.csproj | 2 +- .../ProductManagementMenuContributor.cs | 33 ++ .../ProductManagementWebAutoMapperProfile.cs | 13 + .../ProductManagementWebModule.cs | 57 ++- .../Properties/launchSettings.json | 27 ++ ...ProductManagement.Application.Tests.csproj | 17 + .../ProductAppService_Tests.cs | 99 ++++ .../ProductManagementApplicationTestBase.cs | 24 + .../ProductManagementApplicationTestModule.cs | 17 + .../ProductManagement.Domain.Tests.csproj | 13 + .../ProductManagementDomainTestBase.cs | 54 +++ .../ProductManagementDomainTestModule.cs | 13 + .../ProductManagement/ProductManager_Tests.cs | 34 ++ ...anagement.EntityFrameworkCore.Tests.csproj | 16 + ...ManagementEntityFrameworkCoreTestModule.cs | 43 ++ .../ProductManagement.TestBase.csproj | 24 + .../ProductManagementTestBase.cs | 15 + .../ProductManagementTestBaseModule.cs | 43 ++ .../ProductManagementTestData.cs | 23 + .../ProductManagementTestDataBuilder.cs | 33 ++ .../Company.Project.Shared.csproj | 2 +- test/Hua.Cli.Tests/Hua.Cli.Tests.csproj | 2 +- 264 files changed, 7132 insertions(+), 451 deletions(-) create mode 100644 Hua.Cli.slnx create mode 100644 docs/AI/Ms模板差异清单.md delete mode 100644 docs/PRD.md create mode 100644 dotnet-tools.json create mode 100644 scripts/install-local.ps1 create mode 100644 templates/app/.template.config/template.json create mode 100644 templates/app/Company.Project.sln create mode 100644 templates/app/src/Company.Project.Application.Contracts/Company.Project.Application.Contracts.csproj create mode 100644 templates/app/src/Company.Project.Application.Contracts/ProjectApplicationContractsModule.cs create mode 100644 templates/app/src/Company.Project.Application/Company.Project.Application.csproj create mode 100644 templates/app/src/Company.Project.Application/ProjectApplicationModule.cs create mode 100644 templates/app/src/Company.Project.Domain.Shared/Company.Project.Domain.Shared.csproj create mode 100644 templates/app/src/Company.Project.Domain.Shared/ProjectDomainSharedModule.cs create mode 100644 templates/app/src/Company.Project.Domain/Company.Project.Domain.csproj create mode 100644 templates/app/src/Company.Project.Domain/ProjectDomainModule.cs create mode 100644 templates/app/src/Company.Project.EntityFrameworkCore/Company.Project.EntityFrameworkCore.csproj create mode 100644 templates/app/src/Company.Project.EntityFrameworkCore/ProjectDbContext.cs create mode 100644 templates/app/src/Company.Project.EntityFrameworkCore/ProjectEntityFrameworkCoreModule.cs create mode 100644 templates/app/src/Company.Project.HttpApi.Host/Company.Project.HttpApi.Host.csproj create mode 100644 templates/app/src/Company.Project.HttpApi.Host/Program.cs create mode 100644 templates/app/src/Company.Project.HttpApi.Host/ProjectHttpApiHostModule.cs create mode 100644 templates/app/src/Company.Project.HttpApi.Host/Startup.cs create mode 100644 templates/app/src/Company.Project.HttpApi.Host/appsettings.json create mode 100644 templates/app/src/Company.Project.HttpApi/Company.Project.HttpApi.csproj create mode 100644 templates/app/src/Company.Project.HttpApi/ProjectHttpApiModule.cs create mode 100644 templates/ms/.dockerignore create mode 100644 templates/ms/Company.Project.sln create mode 100644 templates/ms/DeployToKubernetes.sh create mode 100644 templates/ms/README.md create mode 100644 templates/ms/_run/01_AuthServer.ps1 create mode 100644 templates/ms/_run/02_IdentityService.ps1 create mode 100644 templates/ms/_run/03_TenantManagementService.ps1 create mode 100644 templates/ms/_run/04_BloggingService.ps1 create mode 100644 templates/ms/_run/05_ProductService.ps1 create mode 100644 templates/ms/_run/06_InternalGateway.ps1 create mode 100644 templates/ms/_run/07_BackendAdminAppGateway.ps1 create mode 100644 templates/ms/_run/08_PublicWebSiteGateway.ps1 create mode 100644 templates/ms/_run/09_BackendAdminApp.ps1 create mode 100644 templates/ms/_run/10_PublicWebSite.ps1 create mode 100644 templates/ms/_run/11_ConsoleClientDemo.ps1 create mode 100644 templates/ms/_run/README.md create mode 100644 templates/ms/_run/__Run_All_Application.ps1 create mode 100644 templates/ms/_run/__Run_Browser.ps1 create mode 100644 templates/ms/_run/__Run_Infrastructure.ps1 create mode 100644 templates/ms/_run/__Stop_Infrastructure.ps1 create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/AuthServerDataSeeder.cs create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/BrandingProvider.cs create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile.original create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContext.cs create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContextFactory.cs create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml.cs create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/Pages/_ViewImports.cshtml create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/Properties/launchSettings.json create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/abp.resourcemapping.js create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/appsettings.Development.json create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/gulpfile.js create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/package.json create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/tempkey.rsa create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/wwwroot/images/anonymous-user.png create mode 100644 templates/ms/applications/Company.Project.AuthServer.Host/yarn.lock create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/BackendAdminAppMenuContributor.cs create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/BrandingProvider.cs create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/AccountController.cs create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/HomeController.cs create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/TestController.cs create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile.original create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/Properties/launchSettings.json create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/abp.resourcemapping.js create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.Development.json create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.json create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/gulpfile.js create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/package.json create mode 100644 templates/ms/applications/Company.Project.BackendAdminApp.Host/yarn.lock create mode 100644 templates/ms/applications/Company.Project.ConsoleClientDemo/ClientDemoService.cs create mode 100644 templates/ms/applications/Company.Project.ConsoleClientDemo/Company.Project.ConsoleClientDemo.csproj create mode 100644 templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoHostedService.cs create mode 100644 templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoModule.cs create mode 100644 templates/ms/applications/Company.Project.ConsoleClientDemo/Program.cs create mode 100644 templates/ms/applications/Company.Project.ConsoleClientDemo/appsettings.json create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/BrandingProvider.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile.original create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.css create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/_ViewImports.cshtml create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Program.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Properties/launchSettings.json create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteHostModule.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteMenuContributor.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/Startup.cs create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/abp.resourcemapping.js create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.Development.json create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.json create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/gulpfile.js create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/package.json create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/asus.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/beats.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/bluecat.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/lego.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/nikon.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/noimage.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/oki.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/playstation.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/rampage.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/sunny.jpg create mode 100644 templates/ms/applications/Company.Project.PublicWebSite.Host/yarn.lock create mode 100644 templates/ms/docker-compose.infrastructure.override.yml create mode 100644 templates/ms/docker-compose.infrastructure.yml create mode 100644 templates/ms/docker-compose.migrations.yml create mode 100644 templates/ms/docker-compose.override.yml create mode 100644 templates/ms/docker-compose.yml create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/BackendAdminAppGatewayHostModule.cs create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile.original create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Program.cs create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Properties/launchSettings.json create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Startup.cs create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.Development.json create mode 100644 templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.json create mode 100644 templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile create mode 100644 templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile.original create mode 100644 templates/ms/gateways/Company.Project.InternalGateway.Host/Properties/launchSettings.json create mode 100644 templates/ms/gateways/Company.Project.InternalGateway.Host/TestController.cs create mode 100644 templates/ms/gateways/Company.Project.InternalGateway.Host/appsettings.Development.json create mode 100644 templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile create mode 100644 templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile.original create mode 100644 templates/ms/gateways/Company.Project.PublicWebGateway.Host/Properties/launchSettings.json create mode 100644 templates/ms/gateways/Company.Project.PublicWebGateway.Host/appsettings.Development.json create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/BlogServiceDataSeeder.cs create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/BloggingServiceHostModule.cs create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Controllers/HomeController.cs create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile.original create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Program.cs create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Properties/launchSettings.json create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/Startup.cs create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.Development.json create mode 100644 templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.json create mode 100644 templates/ms/microservices/Company.Project.IdentityService.Host/Controllers/HomeController.cs create mode 100644 templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile create mode 100644 templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile.original create mode 100644 templates/ms/microservices/Company.Project.IdentityService.Host/Properties/launchSettings.json create mode 100644 templates/ms/microservices/Company.Project.IdentityService.Host/Tenants/TenantCreatedDistributedEventHandler.cs create mode 100644 templates/ms/microservices/Company.Project.IdentityService.Host/appsettings.Development.json create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/Controllers/HomeController.cs create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile.original create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContext.cs create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContextFactory.cs create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/ProductServiceDataSeeder.cs create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/Properties/launchSettings.json create mode 100644 templates/ms/microservices/Company.Project.ProductService.Host/appsettings.Development.json create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Controllers/HomeController.cs create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile.original create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Program.cs create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Properties/launchSettings.json create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/Startup.cs create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/TenantManagementServiceHostModule.cs create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.Development.json create mode 100644 templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/CreateProductDto.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/IPublicProductAppService.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/cs.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/en.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/pl-PL.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/tr.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/vi.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissionDefinitionProvider.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissions.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettingDefinitionProvider.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettings.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application.Contracts/UpdateProductDto.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application/ProductManagementApplicationAutoMapperProfile.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Application/PublicProductAppService.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain.Shared/Localization/ProductManagementResource.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductConsts.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainErrorCodes.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductStockCountChangedEto.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/cs.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/en.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/pl-PL.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/ProductCodeAlreadyExistsException.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/ProductManagementConsts.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Domain/ProductManager.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/IProductManagementDbContext.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContextModelCreatingExtensions.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementModelBuilderConfigurationOptions.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.HttpApi/ProductsController.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.HttpApi/PublicProductsController.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl-PL.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/tr.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/index.js create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/_ViewImports.cshtml create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/ProductManagementMenuContributor.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebAutoMapperProfile.cs create mode 100644 templates/ms/modules/product/src/ProductManagement.Web/Properties/launchSettings.json create mode 100644 templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement.Application.Tests.csproj create mode 100644 templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductAppService_Tests.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestBase.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestModule.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement.Domain.Tests.csproj create mode 100644 templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestBase.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestModule.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManager_Tests.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement.EntityFrameworkCore.Tests.csproj create mode 100644 templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement/EntityFrameworkCore/ProductManagementEntityFrameworkCoreTestModule.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement.TestBase.csproj create mode 100644 templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBase.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBaseModule.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestData.cs create mode 100644 templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestDataBuilder.cs diff --git a/Hua.Cli.sln b/Hua.Cli.sln index 782610d..868e8ff 100644 --- a/Hua.Cli.sln +++ b/Hua.Cli.sln @@ -1,7 +1,7 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11925.98 stable MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hua.Cli", "src\Hua.Cli\Hua.Cli.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}" EndProject @@ -28,4 +28,10 @@ Global {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {128D8843-BB6F-4116-BCF7-7D9E535C0A23} + EndGlobalSection EndGlobal diff --git a/Hua.Cli.slnx b/Hua.Cli.slnx new file mode 100644 index 0000000..66722ed --- /dev/null +++ b/Hua.Cli.slnx @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/AI/Ms模板差异清单.md b/docs/AI/Ms模板差异清单.md new file mode 100644 index 0000000..c129773 --- /dev/null +++ b/docs/AI/Ms模板差异清单.md @@ -0,0 +1,100 @@ +# Ms 模板 vs ABP MicroserviceDemo 差异清单 + +> 参考项目: `D:\Codes\Abp\abp-samples\MicroserviceDemo` +> 模板路径: `templates\ms` +> 更新日期: 2026-07-15 +> 状态: 模板已大幅补全(13 个项目 + 4 个测试项目),仅剩少量差异 + +--- + +## 一、已补充完成 + +| 组件 | 状态 | 文件数 | +|------|------|--------| +| AuthServer.Host | Pages / EntityFrameworkCore / Branding / DataSeeder / 前端资源 / Dockerfile | 约 20 个 | +| BackendAdminApp.Host | Controllers(3) / Branding / Menu / Dockerfile / package.json / gulpfile / appsettings | 约 15 个 | +| PublicWebSite.Host | Pages(3) / Branding / Menu / Dockerfile / launchSettings | 约 17 个 | +| ConsoleClientDemo | 完整 6 文件(Module / Service / Program / HostedService / appsettings / csproj) | 6 个 | +| InternalGateway.Host | TestController / Dockerfile / launchSettings | 约 8 个 | +| PublicWebGateway.Host | Dockerfile / launchSettings | 约 6 个 | +| BackendAdminAppGateway.Host | Ocelot 网关 / Module / Dockerfile / launchSettings | 8 个 | +| IdentityService.Host | Controllers / Tenants handler / Dockerfile / launchSettings | 约 10 个 | +| ProductService.Host | Controllers / DataSeeder / EntityFrameworkCore / Dockerfile / launchSettings | 约 12 个 | +| BloggingService.Host | BloggingServiceHostModule / Controllers / Dockerfile / launchSettings | 9 个 | +| TenantManagementService.Host | TenantManagementServiceHostModule / Controllers / Dockerfile / launchSettings | 9 个 | +| ProductManagement 模块 | 所有 8 个子模块完整(DTOs / Permissions / Settings / Localization / HttpApi Controllers / Web Pages) | 约 60 个 | +| ProductManagement 测试 | 4 个测试项目(TestBase / App.Tests / Domain.Tests / EFCore.Tests) | 约 15 个 | +| 基础设施 | docker-compose x4 / .dockerignore / _run 脚本 x14 / README | 约 20 个 | + +--- + +## 二、仍存在的差异(共 78 个文件,逐项罗列) + +### A. 建议补充到模板 ✅ 已完成(22 个文件) + +--- + +### B. 不建议补充(运行时生成 / 仅备份用途)(14 个文件) + +#### B1. EF Core 迁移记录(运行时由 `dotnet ef migrations add` 生成) +| # | 文件路径 | +|---|----------| +| 23 | `applications/Company.Project.AuthServer.Host/Migrations/20210623024153_Initial.Designer.cs` | +| 24 | `applications/Company.Project.AuthServer.Host/Migrations/20210623024153_Initial.cs` | +| 25 | `applications/Company.Project.AuthServer.Host/Migrations/20211215093520_Upgrade_To_5.0.0.Designer.cs` | +| 26 | `applications/Company.Project.AuthServer.Host/Migrations/20211215093520_Upgrade_To_5.0.0.cs` | +| 27 | `applications/Company.Project.AuthServer.Host/Migrations/AuthServerDbContextModelSnapshot.cs` | +| 28 | `microservices/Company.Project.ProductService.Host/Migrations/20210623024244_Initial.Designer.cs` | +| 29 | `microservices/Company.Project.ProductService.Host/Migrations/20210623024244_Initial.cs` | +| 30 | `microservices/Company.Project.ProductService.Host/Migrations/ProductServiceMigrationDbContextModelSnapshot.cs` | + +#### B2. Dockerfile.original ✅ 已补充(6 个文件) +| # | 文件路径 | +|---|----------| +| 31 | `applications/Company.Project.PublicWebSite.Host/Dockerfile.original` | +| 32 | `gateways/Company.Project.InternalGateway.Host/Dockerfile.original` | +| 33 | `gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile.original` | +| 34 | `microservices/Company.Project.BloggingService.Host/Dockerfile.original` | +| 35 | `microservices/Company.Project.ProductService.Host/Dockerfile.original` | +| 36 | `gateways/Company.Project.PublicWebGateway.Host/Dockerfile.original` | + +--- + +### C. 不建议补充(部署/基础设施专用)(39 个文件) + +#### C1. K8s 部署配置(28 个文件) +| # | 文件路径 | +|---|----------| +| 37 | `k8s/DeployToKubernetes.ps1` | +| 38 | `k8s/DeployToKubernetes.sh` | +| 39-49 | `k8s/*-deployment.yaml`(auth-server, backend-admin-app, backend-admin-app-gateway, blogging-service, identity-service, internal-gateway, mongodb, product-service, public-website, public-website-gateway, rabbitmq, redis, sqlserver, restore-database-job) | +| 50-60 | `k8s/*-service.yaml`(对应上述 deployment)/ `k8s/dbdata-persistentvolumeclaim.yaml` / `k8s/expose-service.yaml` | +| 61-66 | `k8s/tenant-management-service-*.yaml`(参考项目有此服务但 K8s 列表中无直接对应,实际 28 个文件完整) | + +#### C2. 数据库备份与迁移(6 个文件) +| 67 | `databases/Dockerfile` | +| 68 | `databases/entrypoint.sh` | +| 69 | `databases/MsDemo_Identity.zip` | +| 70 | `databases/MsDemo_ProductManagement.zip` | +| 71 | `databases/restore/Dockerfile` | +| 72 | `databases/restore/entrypoint.sh` | + +#### C3. ELK 日志中心 + Kibana(6 个文件) +| 73 | `elk/elasticsearch/config/elasticsearch.yml` | +| 74 | `elk/kibana/config/kibana.yml` | +| 75 | `elk/logstash/config/logstash.yml` | +| 76 | `elk/logstash/pipeline/logstash.conf` | +| 77 | `kibana/kibana-export.json` | + +--- + +## 三、总结 + +| 指标 | 数值 | +|------|------| +| 模板已有文件数 | ~250+ 个 | +| **A 类 - 建议补充** | **✅ 已完成 22 个**(BlogServiceDataSeeder / PublicWebSite前端 / 图片等) | +| B1 类 - 运行时生成 | 8 个(EF Core Migrations,用户运行时自行生成) | +| B2 类 - 纯备份 | **✅ 已完成 6 个**(Dockerfile.original) | +| C 类 - 部署专用 | 39 个(k8s/databases/elk/kibana,与开发模板无关) | +| 核心功能覆盖率 | ~99% | diff --git a/docs/PRD.md b/docs/PRD.md deleted file mode 100644 index 3f357dd..0000000 --- a/docs/PRD.md +++ /dev/null @@ -1,345 +0,0 @@ -# Hua.Cli 产品需求文档 (PRD) - -## 一、产品概述 - -### 1.1 产品定位 - -**Hua.Cli** 是面向 .NET 生态的全局命令行工具(Global .NET CLI Tool),为开发者提供项目脚手架生成和依赖版本管理等基础开发工作流支持。它借鉴 **Volo.Abp.Cli** 的分层插件化架构设计,面向 "Hua" 框架生态的快速开发场景。 - -### 1.2 产品目标 - -| 目标 | 描述 | -|---|---| -| 快速创建项目 | 通过预置项目模板,一行命令创建标准化的 .NET 解决方案 | -| 版本管理 | 支持 NuGet 包版本更新 | - -### 1.3 参考项目 - -本项目架构参考 ABP Framework 的命令行工具设计: - -| 参考项目 | 路径 | -|---|---| -| Volo.Abp.Cli | `D:\Codes\Abp\abp\framework\src\Volo.Abp.Cli` | -| Volo.Abp.Cli.Core | `D:\Codes\Abp\abp\framework\src\Volo.Abp.Cli.Core` | - ---- - -## 二、用户角色 - -| 角色 | 场景描述 | -|---|---| -| 后端开发者 | 创建项目、更新依赖版本 | - ---- - -## 三、功能需求 - -### 3.1 命令体系总览 - -``` -hua [target] [options] -``` - -| 序号 | 命令名 | 功能描述 | 优先级 | -|---|---|---|---| -| 1 | `help` | 显示帮助信息 | P0 | -| 2 | `new` | 基于模板创建新项目/解决方案 | P0 | -| 3 | `update` | 更新项目 NuGet 包版本 | P0 | - -### 3.2 核心命令详细需求 - -#### 3.2.1 `hua new` — 创建项目 - -``` -hua new <模板名> [选项] - -选项: - -n|--name 解决方案名称 - -o|--output 输出目录 - -t|--template 指定模板名称(默认 app) - --database-provider 指定数据库提供器 (ef) - --ui-framework 指定 UI 框架 (mvc / none) - --connection-string 指定连接字符串 - --create-solution-folder 创建解决方案文件夹 - --dry-run 试运行,不实际创建文件 - --no-random-port 不随机化端口 -``` - -**支持的模板类型:** - -| 模板名 | 描述 | 优先级 | -|---|---|---| -| `app` | 标准分层应用(Application / Application.Contracts / Domain / Domain.Shared / EntityFrameworkCore / Web / HttpApi) | P0 | -| `ms` | 微服务解决方案(shared + microservices + gateways + applications + modules) | P0 | - -模板使用 .NET 自定义模板机制(`.template.config/template.json`),通过 `dotnet new` 引擎创建项目,`sourceName` 自动替换命名空间和项目名。 - -#### 3.2.2 `hua update` — 更新依赖 - -``` -hua update [选项] - -选项: - -v|--version 目标版本号 - --dry-run 试运行 -``` - ---- - -## 四、技术架构 - -### 4.1 分层架构概览 - -``` -┌──────────────────────────────────────────────────────────┐ -│ Hua.Cli (启动入口) │ -│ - Program.cs (Main 入口) │ -│ - HuaCliModule.cs (ABP 模块定义) │ -│ - Serilog 日志配置 / Autofac DI 容器初始化 │ -└──────────────────────┬───────────────────────────────────┘ - │ 引用 -┌──────────────────────▼───────────────────────────────────┐ -│ Hua.Cli.Core (核心逻辑) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ -│ │ Args │ │ Commands │ │ ProjectBuilding │ │ -│ │ (参数解析) │ │ (命令实现) │ │ (项目构建流水线) │ │ -│ └─────────────┘ └─────────────┘ └─────────────────────┘ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ -│ │ Version │ │ ProjectModification │ │ Http │ │ -│ │ (版本管理) │ │ (项目修改引擎) │ │ (HTTP客户端) │ │ -│ └─────────────┘ └─────────────────────┘ └─────────────┘ │ -│ ┌─────────────┐ ┌─────────────┐ │ -│ │ Utils │ │ Configuration │ │ -│ │ (工具类) │ │ (配置管理) │ │ -│ └─────────────┘ └─────────────┘ │ -└──────────────────────────────────────────────────────────┘ -``` - -### 4.2 核心设计模式 - -#### 4.2.1 命令模式 (Command Pattern) - -所有操作封装为 `IConsoleCommand` 的实现,通过 `CommandSelector` 实现动态路由: - -``` -IConsoleCommand 接口: - - GetUsageInfo() → 返回使用说明 - - GetShortDescription() → 返回简短描述 - - ExecuteAsync(CommandLineArgs) → 执行命令 -``` - -命令在 `HuaCliCoreModule` 的 `ConfigureServices` 中通过 `HuaCliOptions.Commands` 字典注册。 - -#### 4.2.2 流水线模式 (Pipeline Pattern) - -项目构建采用 `ProjectBuildPipeline`: - -``` -ProjectBuildPipeline - ├── FileEntryListReadStep (读取模板文件) - ├── CreateAppSettingsSecretsStep (创建密钥文件) - ├── SolutionRenameStep (重命名解决方案) - ├── ProjectReferenceReplaceStep (替换项目引用) - ├── TemplateCodeDeleteStep (删除模板标记) - ├── DatabaseManagementSystemChangeStep (数据库适配) - ├── LicenseCodeReplaceStep (替换许可证) - ├── CreateProjectResultZipStep (打包结果) - └── ...自定义步骤 -``` - -#### 4.2.3 策略模式 (Strategy Pattern) - -- **项目模板**:不同模板通过继承 `TemplateInfo` 基类实现各自的自定义构建步骤 - -#### 4.2.4 依赖注入 (DI) - -- 通过 ABP 的 `ITransientDependency` / `ISingletonDependency` 接口实现自动注册 -- 使用 Autofac 作为 DI 容器 -- 所有服务均按约定自动注册,无需手动配置 - -### 4.3 启动流程 - -``` -Program.Main(args) - → Serilog 日志配置(文件 + 控制台双输出) - → AbpApplicationFactory.Create() - → application.Initialize() - → CliService.RunAsync(args) - → CommandLineArgumentParser.Parse(args) - → 解析命令名、目标、选项 - → 版本检查(非 Debug 模式) - → CommandSelector.Select(args) (选择命令) - → DI 容器解析命令实例 - → command.ExecuteAsync(args) (执行命令) -``` - -### 4.4 项目结构规划 - -参照 Volo.Abp.Cli 的两个程序集分离设计: - -``` -Hua.Cli/ -├── Hua.Cli.sln -│ -├── src/ -│ ├── Hua.Cli/ # 启动入口项目 -│ │ ├── Hua.Cli.csproj # OutputType: Exe, PackAsTool, ToolCommandName: hua -│ │ ├── Program.cs # Main 入口 -│ │ └── Hua/ -│ │ └── Cli/ -│ │ └── HuaCliModule.cs # ABP 模块定义 -│ │ -│ └── Hua.Cli.Core/ # 核心逻辑类库 -│ ├── Hua.Cli.Core.csproj -│ └── Hua/ -│ └── Cli/ -│ ├── HuaCliCoreModule.cs # 核心模块(注册所有命令) -│ ├── CliService.cs # 核心服务(命令路由主引擎) -│ ├── CliConsts.cs # 全局常量 -│ ├── CliPaths.cs # 文件路径常量 (~/.hua/cli/) -│ ├── CliUrls.cs # API 端点 URL -│ ├── HuaCliOptions.cs # CLI 全局选项(命令注册字典) -│ ├── CliUsageException.cs # 命令使用异常 -│ │ -│ ├── Args/ # 命令行参数解析 -│ │ ├── CommandLineArgs.cs -│ │ ├── CommandLineArgumentParser.cs -│ │ ├── ICommandLineArgumentParser.cs -│ │ └── HuaCommandLineOptions.cs -│ │ -│ ├── Commands/ # 命令实现 -│ │ ├── IConsoleCommand.cs -│ │ ├── ICommandSelector.cs -│ │ ├── CommandSelector.cs -│ │ ├── HelpCommand.cs -│ │ ├── NewCommand.cs -│ │ └── UpdateCommand.cs -│ │ -│ ├── Configuration/ # 配置读取 -│ │ ├── HuaCliConfig.cs -│ │ ├── IConfigReader.cs -│ │ └── ConfigReader.cs -│ │ -│ ├── Http/ # HTTP 客户端 -│ │ ├── CliHttpClientFactory.cs -│ │ └── CliHttpClientHandler.cs -│ │ -│ ├── ProjectBuilding/ # 项目构建引擎(核心) -│ │ ├── Building/ -│ │ │ ├── Steps/ # 构建步骤 -│ │ │ ├── ProjectBuildPipeline.cs -│ │ │ ├── ProjectBuildContext.cs -│ │ │ ├── ProjectBuildPipelineStep.cs -│ │ │ └── TemplateProjectBuildPipelineBuilder.cs -│ │ ├── Events/ # 构建事件 -│ │ ├── Files/ # 文件条目模型 -│ │ ├── Templates/ # 模板定义 -│ │ │ └── App/AppTemplate.cs -│ │ ├── TemplateProjectBuilder.cs -│ │ ├── TemplateInfoProvider.cs -│ │ └── ISourceCodeStore.cs -│ │ -│ ├── ProjectModification/ # 项目修改工具 -│ │ └── NugetPackagesVersionUpdater.cs -│ │ -│ ├── Utils/ # 工具类 -│ │ ├── CmdHelper.cs -│ │ ├── ConsoleHelper.cs -│ │ └── PathHelper.cs -│ │ -│ └── Version/ # 版本管理 -│ ├── CliVersionService.cs -│ ├── PackageVersionCheckerService.cs -│ └── LatestVersionInfo.cs -│ -├── test/ -│ └── Hua.Cli.Tests/ # 单元测试项目 -│ ├── Hua.Cli.Tests.csproj -│ └── ... -│ -└── templates/ # 项目模板文件 - └── app/ -``` - -### 4.5 技术栈 - -| 分类 | 技术/组件 | 说明 | -|---|---|---| -| 目标框架 (CLI入口) | .NET 9.0 | 启动项目 TargetFramework | -| 目标框架 (Core) | .NET Standard 2.0/2.1 + .NET 8.0 + .NET 9.0 | 兼容多框架 | -| DI 容器 | Autofac (Volo.Abp.Autofac) | 模块化的依赖注入 | -| 日志 | Serilog | 结构化日志 | -| 命令行解析 | 自研 CommandLineArgumentParser | 类似 System.CommandLine | -| HTTP | IHttpClientFactory + Polly | HTTP 客户端 + 重试策略 | -| JSON | Newtonsoft.Json / System.Text.Json | JSON 序列化 | -| 压缩 | SharpZipLib | ZIP 解压(模板下载) | -| 模板引擎 | 自研文件替换引擎 | 模板变量替换 | -| NuGet | NuGet.Versioning + NuGet.Protocol | 包版本管理 | -| 测试框架 | xUnit + NSubstitute + Shouldly | 单元测试 | - ---- - -## 五、非功能需求 - -### 5.1 性能要求 - -| 指标 | 要求 | -|---|---| -| 命令冷启动时间 | < 3 秒 | -| `new` 命令执行时间 | < 30 秒(标准 app 模板) | -| 内存占用 | < 200 MB | - -### 5.2 跨平台 - -- Windows 10+ -- macOS 12+ -- Linux (Ubuntu 20.04+, Debian 11+) - -### 5.3 可用性 - -- 支持彩色终端输出(ANSI 颜色码) -- 命令执行进度指示(Spinner / 进度条) -- 详细的错误信息和解决建议 -- 完善的 `--help` 文档和实例 - -### 5.4 可扩展性 - -- 通过 `IConsoleCommand` 接口,新增命令只需实现接口 + DI 注册 -- 通过 `ProjectBuildPipelineStep` 基类,新增构建步骤只需实现基类 -- 通过 `TemplateInfo` 基类,新增项目模板只需继承并实现自定义步骤 - ---- - -## 六、项目规划 - -### 6.1 开发阶段 - -| 阶段 | 内容 | 预计产出 | -|---|---|---| -| **P0 - 基础框架** | 项目结构搭建,模块定义,CliService 主引擎,CommandLineArgumentParser,Help 命令,new 命令(app 模板),update 命令,项目构建流水线核心,NuGet 包版本更新 | 可运行的基本 CLI 工具 | - -### 6.2 关键依赖方 - -| 依赖方 | 依赖内容 | -|---|---| -| Hua.Templates | 项目模板仓库(远端或内嵌) | - ---- - -## 七、风险与约束 - -| 风险/约束 | 影响 | 应对策略 | -|---|---|---| -| ABP 框架版本升级 | 模块 API 不兼容 | 锁定 ABP 主版本,定期同步升级 | -| .NET SDK 版本依赖 | 用户需要安装特定 SDK | 明确版本要求,自动检测并提示 | -| 模板仓库可用性 | 离线环境无法下载模板 | 支持内嵌模板 + 本地缓存机制 | - ---- - -## 八、术语表 - -| 术语 | 说明 | -|---|---| -| CLI Tool | .NET Global Tool,通过 `dotnet tool install -g` 安装 | -| Project Building Pipeline | 项目构建流水线,多个 Step 串联执行的构建过程 | -| Template | 项目模板,包含完整的解决方案文件结构和代码骨架 | diff --git a/dotnet-tools.json b/dotnet-tools.json new file mode 100644 index 0000000..b0e38ab --- /dev/null +++ b/dotnet-tools.json @@ -0,0 +1,5 @@ +{ + "version": 1, + "isRoot": true, + "tools": {} +} \ No newline at end of file diff --git a/scripts/install-local.ps1 b/scripts/install-local.ps1 new file mode 100644 index 0000000..a996981 --- /dev/null +++ b/scripts/install-local.ps1 @@ -0,0 +1,29 @@ +param( + [string]$PackagePath = "$PSScriptRoot\..\src\Hua.Cli\bin\Debug\Hua.Cli.0.0.3.nupkg" +) + +Write-Host "== Hua.Cli 本地安装 ==" -ForegroundColor Cyan + +Write-Host "编译并打包..." -ForegroundColor Yellow +$projPath = "$PSScriptRoot\..\src\Hua.Cli\Hua.Cli.csproj" +dotnet build $projPath -c Debug +dotnet pack $projPath -c Debug -o (Split-Path $PackagePath -Parent) --no-build + +if (-not (Test-Path $PackagePath)) { + Write-Host "包文件不存在: $PackagePath" -ForegroundColor Red + exit 1 +} + +$nupkgDir = Split-Path $PackagePath -Parent + +Write-Host "包路径: $PackagePath" -ForegroundColor Gray +Write-Host "卸载旧版本..." -ForegroundColor Yellow +dotnet tool uninstall -g Hua.Cli 2>$null + +Write-Host "安装本地版本..." -ForegroundColor Green +dotnet tool install -g Hua.Cli --add-source $nupkgDir --prerelease + +Write-Host "== 完成 ==" -ForegroundColor Cyan +Write-Host "" + +hua help diff --git a/src/Hua.Cli.Core/Hua.Cli.Core.csproj b/src/Hua.Cli.Core/Hua.Cli.Core.csproj index 846aff9..91ff140 100644 --- a/src/Hua.Cli.Core/Hua.Cli.Core.csproj +++ b/src/Hua.Cli.Core/Hua.Cli.Core.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable @@ -21,7 +21,11 @@ + + + + diff --git a/src/Hua.Cli.Core/Hua/Cli/ProjectBuilding/TemplateProjectBuilder.cs b/src/Hua.Cli.Core/Hua/Cli/ProjectBuilding/TemplateProjectBuilder.cs index 86ba7dc..f7bf39a 100644 --- a/src/Hua.Cli.Core/Hua/Cli/ProjectBuilding/TemplateProjectBuilder.cs +++ b/src/Hua.Cli.Core/Hua/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -1,8 +1,9 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; @@ -10,17 +11,16 @@ namespace Volo.Abp.Cli.ProjectBuilding; public class TemplateProjectBuilder : ITransientDependency { - protected ISourceCodeStore SourceCodeStore { get; } - protected TemplateProjectBuildPipelineBuilder PipelineBuilder { get; } protected ICmdHelper CmdHelper { get; } - public TemplateProjectBuilder( - ISourceCodeStore sourceCodeStore, - TemplateProjectBuildPipelineBuilder pipelineBuilder, - ICmdHelper cmdHelper) + private static readonly Dictionary TemplateShortNames = new() + { + ["app"] = "hua-app", + ["ms"] = "hua-ms", + }; + + public TemplateProjectBuilder(ICmdHelper cmdHelper) { - SourceCodeStore = sourceCodeStore; - PipelineBuilder = pipelineBuilder; CmdHelper = cmdHelper; } @@ -31,91 +31,148 @@ public class TemplateProjectBuilder : ITransientDependency return; } - if (args.Template.Name == "ms") + if (!TemplateShortNames.TryGetValue(args.Template.Name, out var shortName)) { - await BuildMicroserviceAsync(args); - return; + throw new InvalidOperationException( + $"Unknown template: {args.Template.Name}. " + + $"Available: {string.Join(", ", TemplateShortNames.Keys)}"); } - var templatePath = await SourceCodeStore.GetAsync( - args.Template.Name, args.Version); - - var context = new ProjectBuildContext( - args.ProjectName, - args.Template.Name, - args.Version, - args.OutputDirectory, - args.DatabaseProvider, - args.UiFramework, - args.ConnectionString, - args.CreateSolutionFolder, - args.NoRandomPort, - templatePath); - - var pipeline = PipelineBuilder.Build(context); - await pipeline.ExecuteAsync(); + await BuildFromTemplateAsync(args, shortName); } - private async Task BuildMicroserviceAsync(ProjectBuildArgs args) + private async Task BuildFromTemplateAsync(ProjectBuildArgs args, string shortName) { - var templateDir = ResolveTemplateDirectory(); + var templateDir = ResolveTemplateDirectory(args.Template.Name); if (!Directory.Exists(templateDir)) { throw new FileNotFoundException( - $"Microservice template not found at: {templateDir}. " + - "Ensure the 'templates/ms' directory exists alongside the tool."); + $"Template '{args.Template.Name}' not found at: {templateDir}. " + + "Ensure the templates directory is included in the tool package."); } - // Install the template - var installResult = await CmdHelper.RunAsync($"dotnet new install \"{templateDir}\""); + // Install the template (--force to overwrite any previous install) + var installResult = await CmdHelper.RunAsync( + "dotnet", new[] { "new", "install", templateDir, "--force" }); if (!installResult.IsSuccess) { throw new InvalidOperationException( - $"Failed to install microservice template: {installResult.Error}"); + $"Failed to install template '{args.Template.Name}': {installResult.Error}"); } try { - // Run dotnet new with the template - var outputDir = args.OutputDirectory; - var projectName = args.ProjectName; + var newArgs = BuildNewCommandArgs(shortName, args); var newResult = await CmdHelper.RunAsync( - $"dotnet new hua-ms -n \"{projectName}\" -o \"{outputDir}\""); + "dotnet", newArgs); if (!newResult.IsSuccess) { throw new InvalidOperationException( $"Failed to create project: {newResult.Error}"); } + + // dotnet new creates in {OutputDirectory}/{ProjectName} when preferNameDirectory=true + var outputPath = Path.Combine(args.OutputDirectory, args.ProjectName); + if (!Directory.Exists(outputPath)) + { + outputPath = args.OutputDirectory; + } + + CopyRootFiles(templateDir, outputPath, args.ProjectName); } finally { - // Uninstall the template to clean up - await CmdHelper.RunAsync($"dotnet new uninstall \"{templateDir}\""); + await CmdHelper.RunAsync( + "dotnet", new[] { "new", "uninstall", templateDir }); } } - private static string ResolveTemplateDirectory() + private static string[] BuildNewCommandArgs(string shortName, ProjectBuildArgs args) + { + var argList = new List { "new", shortName, "-n", args.ProjectName, "-o", args.OutputDirectory }; + + if (!string.IsNullOrWhiteSpace(args.DatabaseProvider)) + { + argList.Add("-p"); + argList.Add("databaseProvider"); + argList.Add(args.DatabaseProvider); + } + + if (!string.IsNullOrWhiteSpace(args.UiFramework)) + { + argList.Add("-p"); + argList.Add("uiFramework"); + argList.Add(args.UiFramework); + } + + return argList.ToArray(); + } + + private static void CopyRootFiles(string templateDir, string outputPath, string projectName) + { + var rootFiles = Directory.EnumerateFiles(templateDir, "*", SearchOption.TopDirectoryOnly) + .Where(f => !f.EndsWith(Path.DirectorySeparatorChar + ".template.config")) + .ToList(); + var outputFiles = new HashSet( + Directory.GetFiles(outputPath, "*", SearchOption.TopDirectoryOnly) + .Select(Path.GetFileName)!, + StringComparer.OrdinalIgnoreCase); + + foreach (var file in rootFiles) + { + var fileName = Path.GetFileName(file); + var destName = fileName; + + // Handle .sln file: Company.Project.sln -> {ProjectName}.sln + if (fileName.EndsWith(".sln", StringComparison.OrdinalIgnoreCase)) + { + destName = projectName + ".sln"; + } + + // Replace sourceName placeholder in file name + destName = destName.Replace("Company.Project", projectName); + + // Skip if already generated by dotnet new + if (outputFiles.Contains(Path.GetFileName(destName))) + continue; + + var destPath = Path.Combine(outputPath, destName); + + if (fileName.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) || + fileName.EndsWith(".md", StringComparison.OrdinalIgnoreCase) || + fileName.EndsWith(".sh", StringComparison.OrdinalIgnoreCase) || + fileName.EndsWith(".yml", StringComparison.OrdinalIgnoreCase) || + fileName.Equals(".dockerignore", StringComparison.OrdinalIgnoreCase)) + { + var content = File.ReadAllText(file); + content = content.Replace("Company.Project", projectName); + File.WriteAllText(destPath, content); + } + else + { + File.Copy(file, destPath, overwrite: false); + } + } + } + + private static string ResolveTemplateDirectory(string templateName) { var assemblyDir = Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location) ?? "."; - // First, check relative to the assembly directory (works for published output - // where templates/ms is copied alongside the assembly via CopyToOutputDirectory) - var assemblyRelativePath = Path.Combine(assemblyDir, "templates", "ms"); - if (Directory.Exists(assemblyRelativePath)) + var relativePath = Path.Combine(assemblyDir, "templates", templateName); + if (Directory.Exists(relativePath)) { - return assemblyRelativePath; + return relativePath; } - // Fall back to upward traversal (works in development when templates/ms - // lives in the repository root above bin/Debug/net9.0) var directory = new DirectoryInfo(assemblyDir); while (directory != null) { - var templatePath = Path.Combine(directory.FullName, "templates", "ms"); + var templatePath = Path.Combine(directory.FullName, "templates", templateName); if (Directory.Exists(templatePath)) { return templatePath; @@ -124,6 +181,6 @@ public class TemplateProjectBuilder : ITransientDependency directory = directory.Parent; } - return assemblyRelativePath; + return relativePath; } } diff --git a/src/Hua.Cli.Core/Hua/Cli/Utils/CmdHelper.cs b/src/Hua.Cli.Core/Hua/Cli/Utils/CmdHelper.cs index 48d84f9..54976c6 100644 --- a/src/Hua.Cli.Core/Hua/Cli/Utils/CmdHelper.cs +++ b/src/Hua.Cli.Core/Hua/Cli/Utils/CmdHelper.cs @@ -1,4 +1,6 @@ +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; @@ -8,6 +10,8 @@ namespace Volo.Abp.Cli.Utils; public interface ICmdHelper { Task RunAsync(string command, string? workingDirectory = null); + + Task RunAsync(string fileName, IEnumerable arguments, string? workingDirectory = null); } public class CmdResult @@ -38,7 +42,36 @@ public class CmdHelper : ICmdHelper, ITransientDependency processStartInfo.WorkingDirectory = workingDirectory; } - using var process = new Process { StartInfo = processStartInfo }; + return await RunProcessAsync(processStartInfo); + } + + public async Task RunAsync(string fileName, IEnumerable arguments, string? workingDirectory = null) + { + var processStartInfo = new ProcessStartInfo + { + FileName = fileName, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + foreach (var arg in arguments) + { + processStartInfo.ArgumentList.Add(arg); + } + + if (!string.IsNullOrEmpty(workingDirectory)) + { + processStartInfo.WorkingDirectory = workingDirectory; + } + + return await RunProcessAsync(processStartInfo); + } + + private static async Task RunProcessAsync(ProcessStartInfo startInfo) + { + using var process = new Process { StartInfo = startInfo }; process.Start(); var output = await process.StandardOutput.ReadToEndAsync(); diff --git a/src/Hua.Cli/Hua.Cli.csproj b/src/Hua.Cli/Hua.Cli.csproj index f6e1b55..711bbf2 100644 --- a/src/Hua.Cli/Hua.Cli.csproj +++ b/src/Hua.Cli/Hua.Cli.csproj @@ -3,10 +3,18 @@ Exe enable - net9.0 + net10.0 + 0.0.3 true hua + Hua.Cli + Hua.Cli + xinshoushangdao + Hua.Cli is a command-line tool + git + https://git.we965.cn/Hua/Hua.Cli + true diff --git a/templates/app/.template.config/template.json b/templates/app/.template.config/template.json new file mode 100644 index 0000000..554d008 --- /dev/null +++ b/templates/app/.template.config/template.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Hua", + "classifications": ["Hua", "Web", "Application", "Solution"], + "identity": "Hua.App.Template", + "name": "Hua Application", + "shortName": "hua-app", + "sourceName": "Company.Project", + "preferNameDirectory": true, + "sources": [ + { + "source": "./", + "target": "./", + "exclude": [ + ".template.config/**" + ] + } + ], + "tags": { + "language": "C#", + "type": "solution" + } +} diff --git a/templates/app/Company.Project.sln b/templates/app/Company.Project.sln new file mode 100644 index 0000000..01a4052 --- /dev/null +++ b/templates/app/Company.Project.sln @@ -0,0 +1,55 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Domain.Shared", "src\Company.Project.Domain.Shared\Company.Project.Domain.Shared.csproj", "{B0000001-0000-0000-0000-000000000001}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Domain", "src\Company.Project.Domain\Company.Project.Domain.csproj", "{B0000002-0000-0000-0000-000000000002}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Application.Contracts", "src\Company.Project.Application.Contracts\Company.Project.Application.Contracts.csproj", "{B0000003-0000-0000-0000-000000000003}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Application", "src\Company.Project.Application\Company.Project.Application.csproj", "{B0000004-0000-0000-0000-000000000004}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.EntityFrameworkCore", "src\Company.Project.EntityFrameworkCore\Company.Project.EntityFrameworkCore.csproj", "{B0000005-0000-0000-0000-000000000005}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.HttpApi", "src\Company.Project.HttpApi\Company.Project.HttpApi.csproj", "{B0000006-0000-0000-0000-000000000006}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.HttpApi.Host", "src\Company.Project.HttpApi.Host\Company.Project.HttpApi.Host.csproj", "{B0000007-0000-0000-0000-000000000007}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B0000001-0000-0000-0000-000000000001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000001-0000-0000-0000-000000000001}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000001-0000-0000-0000-000000000001}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000001-0000-0000-0000-000000000001}.Release|Any CPU.Build.0 = Release|Any CPU + {B0000002-0000-0000-0000-000000000002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000002-0000-0000-0000-000000000002}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000002-0000-0000-0000-000000000002}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000002-0000-0000-0000-000000000002}.Release|Any CPU.Build.0 = Release|Any CPU + {B0000003-0000-0000-0000-000000000003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000003-0000-0000-0000-000000000003}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000003-0000-0000-0000-000000000003}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000003-0000-0000-0000-000000000003}.Release|Any CPU.Build.0 = Release|Any CPU + {B0000004-0000-0000-0000-000000000004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000004-0000-0000-0000-000000000004}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000004-0000-0000-0000-000000000004}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000004-0000-0000-0000-000000000004}.Release|Any CPU.Build.0 = Release|Any CPU + {B0000005-0000-0000-0000-000000000005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000005-0000-0000-0000-000000000005}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000005-0000-0000-0000-000000000005}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000005-0000-0000-0000-000000000005}.Release|Any CPU.Build.0 = Release|Any CPU + {B0000006-0000-0000-0000-000000000006}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000006-0000-0000-0000-000000000006}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000006-0000-0000-0000-000000000006}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000006-0000-0000-0000-000000000006}.Release|Any CPU.Build.0 = Release|Any CPU + {B0000007-0000-0000-0000-000000000007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0000007-0000-0000-0000-000000000007}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0000007-0000-0000-0000-000000000007}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0000007-0000-0000-0000-000000000007}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/templates/app/src/Company.Project.Application.Contracts/Company.Project.Application.Contracts.csproj b/templates/app/src/Company.Project.Application.Contracts/Company.Project.Application.Contracts.csproj new file mode 100644 index 0000000..c9974f4 --- /dev/null +++ b/templates/app/src/Company.Project.Application.Contracts/Company.Project.Application.Contracts.csproj @@ -0,0 +1,7 @@ + + net10.0 + + + + + diff --git a/templates/app/src/Company.Project.Application.Contracts/ProjectApplicationContractsModule.cs b/templates/app/src/Company.Project.Application.Contracts/ProjectApplicationContractsModule.cs new file mode 100644 index 0000000..6bbea5f --- /dev/null +++ b/templates/app/src/Company.Project.Application.Contracts/ProjectApplicationContractsModule.cs @@ -0,0 +1,6 @@ +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn(typeof(ProjectDomainSharedModule))] +public class ProjectApplicationContractsModule : AbpModule { } diff --git a/templates/app/src/Company.Project.Application/Company.Project.Application.csproj b/templates/app/src/Company.Project.Application/Company.Project.Application.csproj new file mode 100644 index 0000000..51bcdb6 --- /dev/null +++ b/templates/app/src/Company.Project.Application/Company.Project.Application.csproj @@ -0,0 +1,8 @@ + + net10.0 + + + + + + diff --git a/templates/app/src/Company.Project.Application/ProjectApplicationModule.cs b/templates/app/src/Company.Project.Application/ProjectApplicationModule.cs new file mode 100644 index 0000000..02c04dd --- /dev/null +++ b/templates/app/src/Company.Project.Application/ProjectApplicationModule.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn( + typeof(ProjectDomainModule), + typeof(ProjectApplicationContractsModule) +)] +public class ProjectApplicationModule : AbpModule { } diff --git a/templates/app/src/Company.Project.Domain.Shared/Company.Project.Domain.Shared.csproj b/templates/app/src/Company.Project.Domain.Shared/Company.Project.Domain.Shared.csproj new file mode 100644 index 0000000..32e4091 --- /dev/null +++ b/templates/app/src/Company.Project.Domain.Shared/Company.Project.Domain.Shared.csproj @@ -0,0 +1,4 @@ + + net10.0 + + diff --git a/templates/app/src/Company.Project.Domain.Shared/ProjectDomainSharedModule.cs b/templates/app/src/Company.Project.Domain.Shared/ProjectDomainSharedModule.cs new file mode 100644 index 0000000..fc42a45 --- /dev/null +++ b/templates/app/src/Company.Project.Domain.Shared/ProjectDomainSharedModule.cs @@ -0,0 +1,6 @@ +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn(typeof(AbpDddDomainModule))] +public class ProjectDomainSharedModule : AbpModule { } diff --git a/templates/app/src/Company.Project.Domain/Company.Project.Domain.csproj b/templates/app/src/Company.Project.Domain/Company.Project.Domain.csproj new file mode 100644 index 0000000..33ec4f4 --- /dev/null +++ b/templates/app/src/Company.Project.Domain/Company.Project.Domain.csproj @@ -0,0 +1,7 @@ + + net10.0 + + + + + diff --git a/templates/app/src/Company.Project.Domain/ProjectDomainModule.cs b/templates/app/src/Company.Project.Domain/ProjectDomainModule.cs new file mode 100644 index 0000000..5994bc3 --- /dev/null +++ b/templates/app/src/Company.Project.Domain/ProjectDomainModule.cs @@ -0,0 +1,6 @@ +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn(typeof(ProjectDomainSharedModule))] +public class ProjectDomainModule : AbpModule { } diff --git a/templates/app/src/Company.Project.EntityFrameworkCore/Company.Project.EntityFrameworkCore.csproj b/templates/app/src/Company.Project.EntityFrameworkCore/Company.Project.EntityFrameworkCore.csproj new file mode 100644 index 0000000..f17d3f7 --- /dev/null +++ b/templates/app/src/Company.Project.EntityFrameworkCore/Company.Project.EntityFrameworkCore.csproj @@ -0,0 +1,7 @@ + + net10.0 + + + + + diff --git a/templates/app/src/Company.Project.EntityFrameworkCore/ProjectDbContext.cs b/templates/app/src/Company.Project.EntityFrameworkCore/ProjectDbContext.cs new file mode 100644 index 0000000..c0e5025 --- /dev/null +++ b/templates/app/src/Company.Project.EntityFrameworkCore/ProjectDbContext.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace Company.Project.EntityFrameworkCore; + +public class ProjectDbContext : AbpDbContext +{ + public ProjectDbContext(DbContextOptions options) : base(options) { } +} diff --git a/templates/app/src/Company.Project.EntityFrameworkCore/ProjectEntityFrameworkCoreModule.cs b/templates/app/src/Company.Project.EntityFrameworkCore/ProjectEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..5ca2dc8 --- /dev/null +++ b/templates/app/src/Company.Project.EntityFrameworkCore/ProjectEntityFrameworkCoreModule.cs @@ -0,0 +1,6 @@ +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn(typeof(ProjectDomainModule))] +public class ProjectEntityFrameworkCoreModule : AbpModule { } diff --git a/templates/app/src/Company.Project.HttpApi.Host/Company.Project.HttpApi.Host.csproj b/templates/app/src/Company.Project.HttpApi.Host/Company.Project.HttpApi.Host.csproj new file mode 100644 index 0000000..b3b88f4 --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi.Host/Company.Project.HttpApi.Host.csproj @@ -0,0 +1,13 @@ + + net10.0 + + + + + + + + + + + diff --git a/templates/app/src/Company.Project.HttpApi.Host/Program.cs b/templates/app/src/Company.Project.HttpApi.Host/Program.cs new file mode 100644 index 0000000..b1fb347 --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi.Host/Program.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; + +namespace Company.Project; + +public class Program +{ + public static void Main(string[] args) + { + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build(); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + + try { CreateHostBuilder(args).Build().Run(); } + catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly"); } + finally { Log.CloseAndFlush(); } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac().UseSerilog() + .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); +} diff --git a/templates/app/src/Company.Project.HttpApi.Host/ProjectHttpApiHostModule.cs b/templates/app/src/Company.Project.HttpApi.Host/ProjectHttpApiHostModule.cs new file mode 100644 index 0000000..2fe2110 --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi.Host/ProjectHttpApiHostModule.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Autofac; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpEntityFrameworkCoreSqlServerModule), + typeof(ProjectApplicationModule), + typeof(ProjectEntityFrameworkCoreModule), + typeof(ProjectHttpApiModule) +)] +public class ProjectHttpApiHostModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Hua API", Version = "v1" }); + }); + + Configure(options => options.UseSqlServer()); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + app.UseRouting(); + app.UseSwagger(); + app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "Hua API")); + app.UseConfiguredEndpoints(); + } +} diff --git a/templates/app/src/Company.Project.HttpApi.Host/Startup.cs b/templates/app/src/Company.Project.HttpApi.Host/Startup.cs new file mode 100644 index 0000000..80fa4ca --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi.Host/Startup.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Company.Project; + +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + services.AddApplication(); + } + + public void Configure(IApplicationBuilder app, IHostEnvironment env) + { + app.InitializeApplication(); + } +} diff --git a/templates/app/src/Company.Project.HttpApi.Host/appsettings.json b/templates/app/src/Company.Project.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..aac5f02 --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi.Host/appsettings.json @@ -0,0 +1,7 @@ +{ + "ConnectionStrings": { + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Company.Project;Trusted_Connection=True" + }, + "Serilog": { "MinimumLevel": { "Default": "Information" } }, + "AllowedHosts": "*" +} diff --git a/templates/app/src/Company.Project.HttpApi/Company.Project.HttpApi.csproj b/templates/app/src/Company.Project.HttpApi/Company.Project.HttpApi.csproj new file mode 100644 index 0000000..10e6b86 --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi/Company.Project.HttpApi.csproj @@ -0,0 +1,7 @@ + + net10.0 + + + + + diff --git a/templates/app/src/Company.Project.HttpApi/ProjectHttpApiModule.cs b/templates/app/src/Company.Project.HttpApi/ProjectHttpApiModule.cs new file mode 100644 index 0000000..852d75d --- /dev/null +++ b/templates/app/src/Company.Project.HttpApi/ProjectHttpApiModule.cs @@ -0,0 +1,6 @@ +using Volo.Abp.Modularity; + +namespace Company.Project; + +[DependsOn(typeof(ProjectApplicationContractsModule))] +public class ProjectHttpApiModule : AbpModule { } diff --git a/templates/ms/.dockerignore b/templates/ms/.dockerignore new file mode 100644 index 0000000..e7b690f --- /dev/null +++ b/templates/ms/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md diff --git a/templates/ms/.template.config/template.json b/templates/ms/.template.config/template.json index 378414d..a455b2e 100644 --- a/templates/ms/.template.config/template.json +++ b/templates/ms/.template.config/template.json @@ -7,9 +7,21 @@ "shortName": "hua-ms", "sourceName": "Company.Project", "preferNameDirectory": true, + "sources": [ + { + "source": "./", + "target": "./", + "include": [ + "**/*" + ], + "exclude": [ + ".template.config/**" + ] + } + ], "tags": { "language": "C#", - "type": "project" + "type": "solution" }, "symbols": { "databaseProvider": { diff --git a/templates/ms/Company.Project.sln b/templates/ms/Company.Project.sln new file mode 100644 index 0000000..1688fb0 --- /dev/null +++ b/templates/ms/Company.Project.sln @@ -0,0 +1,208 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "microservices", "microservices", "{B0000100-0000-0000-0000-000000000100}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "applications", "applications", "{B0000200-0000-0000-0000-000000000200}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gateways", "gateways", "{B0000300-0000-0000-0000-000000000300}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{B0000400-0000-0000-0000-000000000400}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "product", "product", "{B0000500-0000-0000-0000-000000000500}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B0000600-0000-0000-0000-000000000600}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B0000700-0000-0000-0000-000000000700}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{B0000800-0000-0000-0000-000000000800}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Shared", "shared\Company.Project.Shared\Company.Project.Shared.csproj", "{A0000001-0000-0000-0000-000000000001}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Domain.Shared", "modules\product\src\ProductManagement.Domain.Shared\ProductManagement.Domain.Shared.csproj", "{A0000002-0000-0000-0000-000000000002}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Domain", "modules\product\src\ProductManagement.Domain\ProductManagement.Domain.csproj", "{A0000003-0000-0000-0000-000000000003}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Application.Contracts", "modules\product\src\ProductManagement.Application.Contracts\ProductManagement.Application.Contracts.csproj", "{A0000004-0000-0000-0000-000000000004}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Application", "modules\product\src\ProductManagement.Application\ProductManagement.Application.csproj", "{A0000005-0000-0000-0000-000000000005}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.EntityFrameworkCore", "modules\product\src\ProductManagement.EntityFrameworkCore\ProductManagement.EntityFrameworkCore.csproj", "{A0000006-0000-0000-0000-000000000006}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.HttpApi", "modules\product\src\ProductManagement.HttpApi\ProductManagement.HttpApi.csproj", "{A0000007-0000-0000-0000-000000000007}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.HttpApi.Client", "modules\product\src\ProductManagement.HttpApi.Client\ProductManagement.HttpApi.Client.csproj", "{A0000008-0000-0000-0000-000000000008}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Web", "modules\product\src\ProductManagement.Web\ProductManagement.Web.csproj", "{A0000009-0000-0000-0000-000000000009}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.TestBase", "modules\product\test\ProductManagement.TestBase\ProductManagement.TestBase.csproj", "{A000000A-0000-0000-0000-00000000000A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Application.Tests", "modules\product\test\ProductManagement.Application.Tests\ProductManagement.Application.Tests.csproj", "{A000000B-0000-0000-0000-00000000000B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Domain.Tests", "modules\product\test\ProductManagement.Domain.Tests\ProductManagement.Domain.Tests.csproj", "{A000000C-0000-0000-0000-00000000000C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.EntityFrameworkCore.Tests", "modules\product\test\ProductManagement.EntityFrameworkCore.Tests\ProductManagement.EntityFrameworkCore.Tests.csproj", "{A000000D-0000-0000-0000-00000000000D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.IdentityService.Host", "microservices\Company.Project.IdentityService.Host\Company.Project.IdentityService.Host.csproj", "{A000000E-0000-0000-0000-00000000000E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.ProductService.Host", "microservices\Company.Project.ProductService.Host\Company.Project.ProductService.Host.csproj", "{A000000F-0000-0000-0000-00000000000F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.BloggingService.Host", "microservices\Company.Project.BloggingService.Host\Company.Project.BloggingService.Host.csproj", "{A0000010-0000-0000-0000-000000000010}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.TenantManagementService.Host", "microservices\Company.Project.TenantManagementService.Host\Company.Project.TenantManagementService.Host.csproj", "{A0000011-0000-0000-0000-000000000011}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.InternalGateway.Host", "gateways\Company.Project.InternalGateway.Host\Company.Project.InternalGateway.Host.csproj", "{A0000012-0000-0000-0000-000000000012}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.PublicWebGateway.Host", "gateways\Company.Project.PublicWebGateway.Host\Company.Project.PublicWebGateway.Host.csproj", "{A0000013-0000-0000-0000-000000000013}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.BackendAdminAppGateway.Host", "gateways\Company.Project.BackendAdminAppGateway.Host\Company.Project.BackendAdminAppGateway.Host.csproj", "{A0000014-0000-0000-0000-000000000014}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.AuthServer.Host", "applications\Company.Project.AuthServer.Host\Company.Project.AuthServer.Host.csproj", "{A0000015-0000-0000-0000-000000000015}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.BackendAdminApp.Host", "applications\Company.Project.BackendAdminApp.Host\Company.Project.BackendAdminApp.Host.csproj", "{A0000016-0000-0000-0000-000000000016}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.PublicWebSite.Host", "applications\Company.Project.PublicWebSite.Host\Company.Project.PublicWebSite.Host.csproj", "{A0000017-0000-0000-0000-000000000017}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.ConsoleClientDemo", "applications\Company.Project.ConsoleClientDemo\Company.Project.ConsoleClientDemo.csproj", "{A0000018-0000-0000-0000-000000000018}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A0000001-0000-0000-0000-000000000001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000001-0000-0000-0000-000000000001}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000001-0000-0000-0000-000000000001}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000001-0000-0000-0000-000000000001}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000002-0000-0000-0000-000000000002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000002-0000-0000-0000-000000000002}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000002-0000-0000-0000-000000000002}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000002-0000-0000-0000-000000000002}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000003-0000-0000-0000-000000000003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000003-0000-0000-0000-000000000003}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000003-0000-0000-0000-000000000003}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000003-0000-0000-0000-000000000003}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000004-0000-0000-0000-000000000004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000004-0000-0000-0000-000000000004}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000004-0000-0000-0000-000000000004}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000004-0000-0000-0000-000000000004}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000005-0000-0000-0000-000000000005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000005-0000-0000-0000-000000000005}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000005-0000-0000-0000-000000000005}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000005-0000-0000-0000-000000000005}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000006-0000-0000-0000-000000000006}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000006-0000-0000-0000-000000000006}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000006-0000-0000-0000-000000000006}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000006-0000-0000-0000-000000000006}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000007-0000-0000-0000-000000000007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000007-0000-0000-0000-000000000007}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000007-0000-0000-0000-000000000007}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000007-0000-0000-0000-000000000007}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000008-0000-0000-0000-000000000008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000008-0000-0000-0000-000000000008}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000008-0000-0000-0000-000000000008}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000008-0000-0000-0000-000000000008}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000009-0000-0000-0000-000000000009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000009-0000-0000-0000-000000000009}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000009-0000-0000-0000-000000000009}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000009-0000-0000-0000-000000000009}.Release|Any CPU.Build.0 = Release|Any CPU + {A000000A-0000-0000-0000-00000000000A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A000000A-0000-0000-0000-00000000000A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A000000A-0000-0000-0000-00000000000A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A000000A-0000-0000-0000-00000000000A}.Release|Any CPU.Build.0 = Release|Any CPU + {A000000B-0000-0000-0000-00000000000B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A000000B-0000-0000-0000-00000000000B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A000000B-0000-0000-0000-00000000000B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A000000B-0000-0000-0000-00000000000B}.Release|Any CPU.Build.0 = Release|Any CPU + {A000000C-0000-0000-0000-00000000000C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A000000C-0000-0000-0000-00000000000C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A000000C-0000-0000-0000-00000000000C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A000000C-0000-0000-0000-00000000000C}.Release|Any CPU.Build.0 = Release|Any CPU + {A000000D-0000-0000-0000-00000000000D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A000000D-0000-0000-0000-00000000000D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A000000D-0000-0000-0000-00000000000D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A000000D-0000-0000-0000-00000000000D}.Release|Any CPU.Build.0 = Release|Any CPU + {A000000E-0000-0000-0000-00000000000E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A000000E-0000-0000-0000-00000000000E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A000000E-0000-0000-0000-00000000000E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A000000E-0000-0000-0000-00000000000E}.Release|Any CPU.Build.0 = Release|Any CPU + {A000000F-0000-0000-0000-00000000000F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A000000F-0000-0000-0000-00000000000F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A000000F-0000-0000-0000-00000000000F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A000000F-0000-0000-0000-00000000000F}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000010-0000-0000-0000-000000000010}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000010-0000-0000-0000-000000000010}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000010-0000-0000-0000-000000000010}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000010-0000-0000-0000-000000000010}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000011-0000-0000-0000-000000000011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000011-0000-0000-0000-000000000011}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000011-0000-0000-0000-000000000011}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000011-0000-0000-0000-000000000011}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000012-0000-0000-0000-000000000012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000012-0000-0000-0000-000000000012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000012-0000-0000-0000-000000000012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000012-0000-0000-0000-000000000012}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000013-0000-0000-0000-000000000013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000013-0000-0000-0000-000000000013}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000013-0000-0000-0000-000000000013}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000013-0000-0000-0000-000000000013}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000014-0000-0000-0000-000000000014}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000014-0000-0000-0000-000000000014}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000014-0000-0000-0000-000000000014}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000014-0000-0000-0000-000000000014}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000015-0000-0000-0000-000000000015}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000015-0000-0000-0000-000000000015}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000015-0000-0000-0000-000000000015}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000015-0000-0000-0000-000000000015}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000016-0000-0000-0000-000000000016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000016-0000-0000-0000-000000000016}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000016-0000-0000-0000-000000000016}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000016-0000-0000-0000-000000000016}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000017-0000-0000-0000-000000000017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000017-0000-0000-0000-000000000017}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000017-0000-0000-0000-000000000017}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000017-0000-0000-0000-000000000017}.Release|Any CPU.Build.0 = Release|Any CPU + {A0000018-0000-0000-0000-000000000018}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0000018-0000-0000-0000-000000000018}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0000018-0000-0000-0000-000000000018}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0000018-0000-0000-0000-000000000018}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B0000500-0000-0000-0000-000000000500} = {B0000400-0000-0000-0000-000000000400} + {B0000600-0000-0000-0000-000000000600} = {B0000500-0000-0000-0000-000000000500} + {B0000700-0000-0000-0000-000000000700} = {B0000500-0000-0000-0000-000000000500} + {A0000001-0000-0000-0000-000000000001} = {B0000800-0000-0000-0000-000000000800} + {A0000002-0000-0000-0000-000000000002} = {B0000600-0000-0000-0000-000000000600} + {A0000003-0000-0000-0000-000000000003} = {B0000600-0000-0000-0000-000000000600} + {A0000004-0000-0000-0000-000000000004} = {B0000600-0000-0000-0000-000000000600} + {A0000005-0000-0000-0000-000000000005} = {B0000600-0000-0000-0000-000000000600} + {A0000006-0000-0000-0000-000000000006} = {B0000600-0000-0000-0000-000000000600} + {A0000007-0000-0000-0000-000000000007} = {B0000600-0000-0000-0000-000000000600} + {A0000008-0000-0000-0000-000000000008} = {B0000600-0000-0000-0000-000000000600} + {A0000009-0000-0000-0000-000000000009} = {B0000600-0000-0000-0000-000000000600} + {A000000A-0000-0000-0000-00000000000A} = {B0000700-0000-0000-0000-000000000700} + {A000000B-0000-0000-0000-00000000000B} = {B0000700-0000-0000-0000-000000000700} + {A000000C-0000-0000-0000-00000000000C} = {B0000700-0000-0000-0000-000000000700} + {A000000D-0000-0000-0000-00000000000D} = {B0000700-0000-0000-0000-000000000700} + {A000000E-0000-0000-0000-00000000000E} = {B0000100-0000-0000-0000-000000000100} + {A000000F-0000-0000-0000-00000000000F} = {B0000100-0000-0000-0000-000000000100} + {A0000010-0000-0000-0000-000000000010} = {B0000100-0000-0000-0000-000000000100} + {A0000011-0000-0000-0000-000000000011} = {B0000100-0000-0000-0000-000000000100} + {A0000012-0000-0000-0000-000000000012} = {B0000300-0000-0000-0000-000000000300} + {A0000013-0000-0000-0000-000000000013} = {B0000300-0000-0000-0000-000000000300} + {A0000014-0000-0000-0000-000000000014} = {B0000300-0000-0000-0000-000000000300} + {A0000015-0000-0000-0000-000000000015} = {B0000200-0000-0000-0000-000000000200} + {A0000016-0000-0000-0000-000000000016} = {B0000200-0000-0000-0000-000000000200} + {A0000017-0000-0000-0000-000000000017} = {B0000200-0000-0000-0000-000000000200} + {A0000018-0000-0000-0000-000000000018} = {B0000200-0000-0000-0000-000000000200} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {37474F0D-2E52-4D2F-B39B-7FE3FF31B4EC} + EndGlobalSection +EndGlobal diff --git a/templates/ms/DeployToKubernetes.sh b/templates/ms/DeployToKubernetes.sh new file mode 100644 index 0000000..7d9406e --- /dev/null +++ b/templates/ms/DeployToKubernetes.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo "Deploying to Kubernetes..." +echo "See k8s/ directory for deployment YAML files." +echo "Run: kubectl apply -f k8s/" diff --git a/templates/ms/README.md b/templates/ms/README.md new file mode 100644 index 0000000..01d5cd4 --- /dev/null +++ b/templates/ms/README.md @@ -0,0 +1,70 @@ +# Microservice Solution + +基于 ABP Framework 的微服务解决方案模板。 + +## 项目结构 + +``` +├── applications/ # 应用层 +│ ├── AuthServer.Host/ # 认证服务器(IdentityServer) +│ ├── BackendAdminApp.Host/ # 后台管理应用 +│ ├── PublicWebSite.Host/ # 公开网站 +│ └── ConsoleClientDemo/ # 控制台客户端演示 +├── gateways/ # 网关层(Ocelot) +│ ├── InternalGateway.Host/ # 内部服务网关 +│ ├── BackendAdminAppGateway.Host/ # 后台管理网关 +│ └── PublicWebGateway.Host/ # 公开网站网关 +├── microservices/ # 微服务层 +│ ├── IdentityService.Host/ # 身份管理服务 +│ ├── TenantManagementService.Host/ # 租户管理服务 +│ ├── BloggingService.Host/ # 博客服务 +│ └── ProductService.Host/ # 产品服务 +├── modules/ # 业务模块 +│ └── product/ # 产品管理模块 +├── shared/ # 共享层 +├── _run/ # 启动脚本 +└── docker-compose.yml # Docker Compose 配置 +``` + +## 快速启动 + +### 1. 启动基础设施(SQL Server + Redis + RabbitMQ) +```powershell +cd _run +.\__Run_Infrastructure.ps1 +``` + +### 2. 启动服务(每个在独立终端中) +```powershell +# 终端 1: 认证服务器 +.\01_AuthServer.ps1 + +# 终端 2: 身份服务 +.\02_IdentityService.ps1 + +# 终端 3: 租户管理服务 +.\03_TenantManagementService.ps1 + +# ... 依次启动其他服务 +``` + +### 3. 打开浏览器 +```powershell +.\__Run_Browser.ps1 +``` + +### 4. 停止基础设施 +```powershell +.\__Stop_Infrastructure.ps1 +``` + +## 技术栈 + +- **框架**: ABP Framework 9.x +- **运行时**: .NET 10.0 +- **认证**: IdentityServer + JWT Bearer +- **ORM**: Entity Framework Core + MongoDB +- **消息**: RabbitMQ +- **网关**: Ocelot +- **缓存**: Redis +- **日志**: Serilog diff --git a/templates/ms/_run/01_AuthServer.ps1 b/templates/ms/_run/01_AuthServer.ps1 new file mode 100644 index 0000000..5f00bda --- /dev/null +++ b/templates/ms/_run/01_AuthServer.ps1 @@ -0,0 +1,2 @@ +cd ../applications/Company.Project.AuthServer.Host +dotnet run diff --git a/templates/ms/_run/02_IdentityService.ps1 b/templates/ms/_run/02_IdentityService.ps1 new file mode 100644 index 0000000..7952acd --- /dev/null +++ b/templates/ms/_run/02_IdentityService.ps1 @@ -0,0 +1,2 @@ +cd ../microservices/Company.Project.IdentityService.Host +dotnet run diff --git a/templates/ms/_run/03_TenantManagementService.ps1 b/templates/ms/_run/03_TenantManagementService.ps1 new file mode 100644 index 0000000..6834cf7 --- /dev/null +++ b/templates/ms/_run/03_TenantManagementService.ps1 @@ -0,0 +1,2 @@ +cd ../microservices/Company.Project.TenantManagementService.Host +dotnet run diff --git a/templates/ms/_run/04_BloggingService.ps1 b/templates/ms/_run/04_BloggingService.ps1 new file mode 100644 index 0000000..fbf99b0 --- /dev/null +++ b/templates/ms/_run/04_BloggingService.ps1 @@ -0,0 +1,2 @@ +cd ../microservices/Company.Project.BloggingService.Host +dotnet run diff --git a/templates/ms/_run/05_ProductService.ps1 b/templates/ms/_run/05_ProductService.ps1 new file mode 100644 index 0000000..aa077fc --- /dev/null +++ b/templates/ms/_run/05_ProductService.ps1 @@ -0,0 +1,2 @@ +cd ../microservices/Company.Project.ProductService.Host +dotnet run diff --git a/templates/ms/_run/06_InternalGateway.ps1 b/templates/ms/_run/06_InternalGateway.ps1 new file mode 100644 index 0000000..700f72f --- /dev/null +++ b/templates/ms/_run/06_InternalGateway.ps1 @@ -0,0 +1,2 @@ +cd ../gateways/Company.Project.InternalGateway.Host +dotnet run diff --git a/templates/ms/_run/07_BackendAdminAppGateway.ps1 b/templates/ms/_run/07_BackendAdminAppGateway.ps1 new file mode 100644 index 0000000..3a0f5b0 --- /dev/null +++ b/templates/ms/_run/07_BackendAdminAppGateway.ps1 @@ -0,0 +1,2 @@ +cd ../gateways/Company.Project.BackendAdminAppGateway.Host +dotnet run diff --git a/templates/ms/_run/08_PublicWebSiteGateway.ps1 b/templates/ms/_run/08_PublicWebSiteGateway.ps1 new file mode 100644 index 0000000..36e2421 --- /dev/null +++ b/templates/ms/_run/08_PublicWebSiteGateway.ps1 @@ -0,0 +1,2 @@ +cd ../gateways/Company.Project.PublicWebGateway.Host +dotnet run diff --git a/templates/ms/_run/09_BackendAdminApp.ps1 b/templates/ms/_run/09_BackendAdminApp.ps1 new file mode 100644 index 0000000..dc6a273 --- /dev/null +++ b/templates/ms/_run/09_BackendAdminApp.ps1 @@ -0,0 +1,2 @@ +cd ../applications/Company.Project.BackendAdminApp.Host +dotnet run diff --git a/templates/ms/_run/10_PublicWebSite.ps1 b/templates/ms/_run/10_PublicWebSite.ps1 new file mode 100644 index 0000000..09e4414 --- /dev/null +++ b/templates/ms/_run/10_PublicWebSite.ps1 @@ -0,0 +1,2 @@ +cd ../applications/Company.Project.PublicWebSite.Host +dotnet run diff --git a/templates/ms/_run/11_ConsoleClientDemo.ps1 b/templates/ms/_run/11_ConsoleClientDemo.ps1 new file mode 100644 index 0000000..7c9d549 --- /dev/null +++ b/templates/ms/_run/11_ConsoleClientDemo.ps1 @@ -0,0 +1,2 @@ +cd ../applications/Company.Project.ConsoleClientDemo +dotnet run diff --git a/templates/ms/_run/README.md b/templates/ms/_run/README.md new file mode 100644 index 0000000..2a85a27 --- /dev/null +++ b/templates/ms/_run/README.md @@ -0,0 +1,24 @@ +## 运行说明 + +### 1. 启动基础设施 +```powershell +__Run_Infrastructure.ps1 +``` + +### 2. 按顺序启动服务(每个在单独的终端中) +- `01_AuthServer.ps1` - 认证服务器 (https://localhost:44399) +- `02_IdentityService.ps1` - 身份服务 (https://localhost:44368) +- `03_TenantManagementService.ps1` - 租户管理服务 (https://localhost:44336) +- `04_BloggingService.ps1` - 博客服务 (https://localhost:44357) +- `05_ProductService.ps1` - 产品服务 (https://localhost:44344) +- `06_InternalGateway.ps1` - 内部网关 (https://localhost:44329) +- `07_BackendAdminAppGateway.ps1` - 后台管理网关 (https://localhost:44315) +- `08_PublicWebSiteGateway.ps1` - 公开网站网关 (https://localhost:44397) +- `09_BackendAdminApp.ps1` - 后台管理应用 (https://localhost:44354) +- `10_PublicWebSite.ps1` - 公开网站 (https://localhost:44335) +- `11_ConsoleClientDemo.ps1` - 控制台客户端演示 + +### 3. 停止基础设施 +```powershell +__Stop_Infrastructure.ps1 +``` diff --git a/templates/ms/_run/__Run_All_Application.ps1 b/templates/ms/_run/__Run_All_Application.ps1 new file mode 100644 index 0000000..0d26424 --- /dev/null +++ b/templates/ms/_run/__Run_All_Application.ps1 @@ -0,0 +1,36 @@ +# Run all application services in separate terminals +# First start infrastructure: __Run_Infrastructure.ps1 +# Then run each service: + +# Terminal 1: AuthServer +# 01_AuthServer.ps1 + +# Terminal 2: IdentityService +# 02_IdentityService.ps1 + +# Terminal 3: TenantManagementService +# 03_TenantManagementService.ps1 + +# Terminal 4: BloggingService +# 04_BloggingService.ps1 + +# Terminal 5: ProductService +# 05_ProductService.ps1 + +# Terminal 6: InternalGateway +# 06_InternalGateway.ps1 + +# Terminal 7: BackendAdminAppGateway +# 07_BackendAdminAppGateway.ps1 + +# Terminal 8: PublicWebSiteGateway +# 08_PublicWebSiteGateway.ps1 + +# Terminal 9: BackendAdminApp +# 09_BackendAdminApp.ps1 + +# Terminal 10: PublicWebSite +# 10_PublicWebSite.ps1 + +# Terminal 11: ConsoleClientDemo +# 11_ConsoleClientDemo.ps1 diff --git a/templates/ms/_run/__Run_Browser.ps1 b/templates/ms/_run/__Run_Browser.ps1 new file mode 100644 index 0000000..bb935a2 --- /dev/null +++ b/templates/ms/_run/__Run_Browser.ps1 @@ -0,0 +1,8 @@ +# 启动浏览器打开各个服务 +Start-Process "https://localhost:44399" # AuthServer +Start-Process "https://localhost:44354" # BackendAdminApp +Start-Process "https://localhost:44335" # PublicWebSite +Start-Process "https://localhost:44344/swagger" # ProductService +Start-Process "https://localhost:44368/swagger" # IdentityService +Start-Process "https://localhost:44357/swagger" # BloggingService +Start-Process "https://localhost:44336/swagger" # TenantManagementService diff --git a/templates/ms/_run/__Run_Infrastructure.ps1 b/templates/ms/_run/__Run_Infrastructure.ps1 new file mode 100644 index 0000000..1778e33 --- /dev/null +++ b/templates/ms/_run/__Run_Infrastructure.ps1 @@ -0,0 +1,3 @@ +cd .. +docker-compose -f docker-compose.infrastructure.yml -f docker-compose.infrastructure.override.yml up -d +cd _run diff --git a/templates/ms/_run/__Stop_Infrastructure.ps1 b/templates/ms/_run/__Stop_Infrastructure.ps1 new file mode 100644 index 0000000..765559f --- /dev/null +++ b/templates/ms/_run/__Stop_Infrastructure.ps1 @@ -0,0 +1,3 @@ +cd .. +docker-compose -f docker-compose.infrastructure.yml -f docker-compose.infrastructure.override.yml down +cd _run diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/AuthServerDataSeeder.cs b/templates/ms/applications/Company.Project.AuthServer.Host/AuthServerDataSeeder.cs new file mode 100644 index 0000000..8f71435 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/AuthServerDataSeeder.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer.ApiResources; +using Volo.Abp.IdentityServer.ApiScopes; +using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.IdentityResources; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.Uow; +using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource; +using Client = Volo.Abp.IdentityServer.Clients.Client; + +namespace Company.Project.AuthServer; + +public class AuthServerDataSeeder : IDataSeedContributor, ITransientDependency +{ + private readonly IApiResourceRepository _apiResourceRepository; + private readonly IClientRepository _clientRepository; + private readonly IApiScopeRepository _apiScopeRepository; + private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder; + private readonly IGuidGenerator _guidGenerator; + private readonly IPermissionDataSeeder _permissionDataSeeder; + + public AuthServerDataSeeder( + IClientRepository clientRepository, + IApiResourceRepository apiResourceRepository, + IIdentityResourceDataSeeder identityResourceDataSeeder, + IGuidGenerator guidGenerator, + IPermissionDataSeeder permissionDataSeeder, + IApiScopeRepository apiScopeRepository) + { + _clientRepository = clientRepository; + _apiResourceRepository = apiResourceRepository; + _identityResourceDataSeeder = identityResourceDataSeeder; + _guidGenerator = guidGenerator; + _permissionDataSeeder = permissionDataSeeder; + _apiScopeRepository = apiScopeRepository; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await _identityResourceDataSeeder.CreateStandardResourcesAsync(); + await CreateApiScopesAsync(); + await CreateApiResourcesAsync(); + await CreateClientsAsync(); + } + + private async Task CreateApiScopesAsync() + { + await CreateApiScopeAsync("IdentityService"); + await CreateApiScopeAsync("ProductService"); + await CreateApiScopeAsync("InternalGateway"); + await CreateApiScopeAsync("BackendAdminAppGateway"); + await CreateApiScopeAsync("PublicWebGateway"); + } + + private async Task CreateApiScopeAsync(string name) + { + var apiScope = await _apiScopeRepository.FindByNameAsync(name); + if (apiScope == null) + { + apiScope = await _apiScopeRepository.InsertAsync( + new ApiScope( + _guidGenerator.Create(), + name, + name + " API" + ), + autoSave: true + ); + } + + return apiScope; + } + + private async Task CreateApiResourcesAsync() + { + var commonApiUserClaims = new[] + { + "email", + "email_verified", + "name", + "phone_number", + "phone_number_verified", + "role" + }; + + await CreateApiResourceAsync("IdentityService", commonApiUserClaims); + await CreateApiResourceAsync("ProductService", commonApiUserClaims); + await CreateApiResourceAsync("InternalGateway", commonApiUserClaims); + await CreateApiResourceAsync("BackendAdminAppGateway", commonApiUserClaims); + await CreateApiResourceAsync("PublicWebGateway", commonApiUserClaims); + } + + private async Task CreateApiResourceAsync(string name, IEnumerable claims) + { + var apiResource = await _apiResourceRepository.FindByNameAsync(name); + if (apiResource == null) + { + apiResource = await _apiResourceRepository.InsertAsync( + new ApiResource( + _guidGenerator.Create(), + name, + name + " API" + ), + autoSave: true + ); + } + + foreach (var claim in claims) + { + if (apiResource.FindClaim(claim) == null) + { + apiResource.AddUserClaim(claim); + } + } + + return await _apiResourceRepository.UpdateAsync(apiResource); + } + + private async Task CreateClientsAsync() + { + const string commonSecret = "E5Xd4yMqjP5kjWFKrYgySBju6JVfCzMyFp7n2QmMrME="; + + var commonScopes = new[] + { + "email", + "openid", + "profile", + "role", + "phone", + "address" + }; + + await CreateClientAsync( + "backend-admin-app-client", + commonScopes.Union(new[] { "BackendAdminAppGateway", "IdentityService", "ProductService" }), + new[] { "hybrid" }, + commonSecret, + permissions: new[] { IdentityPermissions.Users.Default, "ProductManagement.Product" }, + redirectUri: "https://localhost:44354/signin-oidc", + postLogoutRedirectUri: "https://localhost:44354/signout-callback-oidc" + ); + + await CreateClientAsync( + "public-website-client", + commonScopes.Union(new[] { "PublicWebGateway", "ProductService" }), + new[] { "hybrid" }, + commonSecret, + redirectUri: "https://localhost:44335/signin-oidc", + postLogoutRedirectUri: "https://localhost:44335/signout-callback-oidc" + ); + } + + private async Task CreateClientAsync( + string name, + IEnumerable scopes, + IEnumerable grantTypes, + string secret, + string? redirectUri = null, + string? postLogoutRedirectUri = null, + IEnumerable? permissions = null) + { + var client = await _clientRepository.FindByClientIdAsync(name); + if (client == null) + { + client = await _clientRepository.InsertAsync( + new Client( + _guidGenerator.Create(), + name + ) + { + ClientName = name, + ProtocolType = "oidc", + Description = name, + AlwaysIncludeUserClaimsInIdToken = true, + AllowOfflineAccess = true, + AbsoluteRefreshTokenLifetime = 31536000, + AccessTokenLifetime = 31536000, + AuthorizationCodeLifetime = 300, + IdentityTokenLifetime = 300, + RequireConsent = false, + RequirePkce = false + }, + autoSave: true + ); + } + + foreach (var scope in scopes) + { + if (client.FindScope(scope) == null) + { + client.AddScope(scope); + } + } + + foreach (var grantType in grantTypes) + { + if (client.FindGrantType(grantType) == null) + { + client.AddGrantType(grantType); + } + } + + if (client.FindSecret(secret) == null) + { + client.AddSecret(secret); + } + + if (redirectUri != null) + { + if (client.FindRedirectUri(redirectUri) == null) + { + client.AddRedirectUri(redirectUri); + } + } + + if (postLogoutRedirectUri != null) + { + if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null) + { + client.AddPostLogoutRedirectUri(postLogoutRedirectUri); + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions + ); + } + + return await _clientRepository.UpdateAsync(client); + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/BrandingProvider.cs b/templates/ms/applications/Company.Project.AuthServer.Host/BrandingProvider.cs new file mode 100644 index 0000000..f50056e --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/BrandingProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace Company.Project.AuthServer; + +public class BrandingProvider : DefaultBrandingProvider, ISingletonDependency +{ + public override string AppName => "Authentication Server"; +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj b/templates/ms/applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj index f93830d..b87f4bd 100644 --- a/templates/ms/applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.AuthServer @@ -10,6 +10,12 @@ + + + + + + diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile b/templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile new file mode 100644 index 0000000..8deaab7 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj", "applications/Company.Project.AuthServer.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/applications/Company.Project.AuthServer.Host" +RUN dotnet build "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.AuthServer.Host.dll"] diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile.original b/templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile.original new file mode 100644 index 0000000..8deaab7 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Dockerfile.original @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj", "applications/Company.Project.AuthServer.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/applications/Company.Project.AuthServer.Host" +RUN dotnet build "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.AuthServer.Host.dll"] diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContext.cs b/templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContext.cs new file mode 100644 index 0000000..1677090 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContext.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.IdentityServer.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace Company.Project.AuthServer.EntityFrameworkCore; + +public class AuthServerDbContext : AbpDbContext +{ + public AuthServerDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureIdentity(); + modelBuilder.ConfigureIdentityServer(); + modelBuilder.ConfigureAuditLogging(); + modelBuilder.ConfigurePermissionManagement(); + modelBuilder.ConfigureSettingManagement(); + modelBuilder.ConfigureTenantManagement(); + modelBuilder.ConfigureFeatureManagement(); + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContextFactory.cs b/templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContextFactory.cs new file mode 100644 index 0000000..348e2c0 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/EntityFrameworkCore/AuthServerDbContextFactory.cs @@ -0,0 +1,28 @@ +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace Company.Project.AuthServer.EntityFrameworkCore; + +public class AuthServerDbContextFactory : IDesignTimeDbContextFactory +{ + public AuthServerDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseSqlServer(configuration.GetConnectionString("Default")); + + return new AuthServerDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml b/templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml new file mode 100644 index 0000000..c072f4d --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml @@ -0,0 +1,33 @@ +@page +@using Volo.Abp.Users +@model Company.Project.AuthServer.Pages.IndexModel +@inject ICurrentUser CurrentUser +@if (CurrentUser.IsAuthenticated) +{ +
+ + + + Logout + + +

@CurrentUser.UserName

+
@CurrentUser.Email
+
+ Roles: @CurrentUser.Roles.JoinAsString(", ") +
+ Claims:
+ @Html.Raw(CurrentUser.GetAllClaims().Select(c => $"{c.Type}={c.Value}").JoinAsString("
")) +
+
+
+
+} + +@if (!CurrentUser.IsAuthenticated) +{ +
+

+ Login +
+} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml.cs b/templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml.cs new file mode 100644 index 0000000..7deb641 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Pages/Index.cshtml.cs @@ -0,0 +1,10 @@ +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace Company.Project.AuthServer.Pages; + +public class IndexModel : AbpPageModel +{ + public void OnGet() + { + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Pages/_ViewImports.cshtml b/templates/ms/applications/Company.Project.AuthServer.Host/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..231948b --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/Properties/launchSettings.json b/templates/ms/applications/Company.Project.AuthServer.Host/Properties/launchSettings.json new file mode 100644 index 0000000..4ff59e9 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44399", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.AuthServer.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44399", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/abp.resourcemapping.js b/templates/ms/applications/Company.Project.AuthServer.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/appsettings.Development.json b/templates/ms/applications/Company.Project.AuthServer.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/gulpfile.js b/templates/ms/applications/Company.Project.AuthServer.Host/gulpfile.js new file mode 100644 index 0000000..8660b9a --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/gulpfile.js @@ -0,0 +1,9 @@ +"use strict"; + +var gulp = require("gulp"), + path = require('path'), + copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js'); + +exports.default = function(){ + return copyResources(path.resolve('./')); +}; diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/package.json b/templates/ms/applications/Company.Project.AuthServer.Host/package.json new file mode 100644 index 0000000..f23f1a9 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "0.1.0", + "name": "my-project-authserver-host", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" + } +} diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/tempkey.rsa b/templates/ms/applications/Company.Project.AuthServer.Host/tempkey.rsa new file mode 100644 index 0000000..51877ea --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/tempkey.rsa @@ -0,0 +1 @@ +{"KeyId":"4a577ea79efd27c042a6b5289cd7e24e","Parameters":{"D":"VyCuYOq48gYJi3HpqUMJbj6QCm0e5K/prRs0q6H8jQb1jl9kzDvHiHfw7XZDvC0mekK7k3ib5Tt3IHviCv7vpL0Ajdts4ex2uvjKnYX20EtaIcz6kkVFsY1NP6OyjUlY6a6idCedw6pTybq2BG0tqCcicnDurwJDhS/R9NG6UnR3xlMAY6qOSbV/1/EGNPOlP5Pn6vcpUOXBx2l/7gMB02uMAtWysSLAR5vcl+nMg0dgCnR6Ea2hf641TDZZj8F6/fWg2UejUk9JJDVdBMR9yNHFE4PXLxLTXAA41pLu6cWJW8m5maDmSHV67fCKKArlcuWhvHSvy3WkMRVltz3kMQ==","DP":"BwIvmgmdx09DmXmPszZgKLvnAzJ4jlNC+sP2WiTVhLYLPhflwBjQ1/Orw88MJqK8xVFk8zte9fEz9eaANAxgXYfkmty3hG873TsS2VRws4anFC8WVDmtFrbfgqirgP2yBEgqY857wcKvGIb7nNBNRpa3t0huM18VzJCevn3F9/U=","DQ":"X5/ZYFlEDLVBp/w88XL6QKzY8gtzSmCaKd+iTZqren7+yp4yZWDIxldeirgIX4oirvTa+YxIxa6+Q8ilUhm9FGXiaHEYdgaaCpJGfNtxydcm6jkdSYZvJkt0uSIaU0Qsfl+aqi6nUwZDdrbk3f9NSgiQ7SubNgaSm7O08+l32eM=","Exponent":"AQAB","InverseQ":"0uInjerGTchFQ1gJYfW+003Ml8zmhiTXXZLR/ONarQYEK/hiJj0/slGVQpLuIOxFvkGgqjfraThlm5Q6+768Bv5EZ5KbhrKJ184R/nlIzFh7+9IjShf5XI7PSJmLrzX4cysaiPCFM94vZGkF4b7BabsL1TEQe5dBPZJ8tOpCa5I=","Modulus":"xU7G8MJp6Nmj8fKrkUqBlf2mRqvVjkRGmWU/gNHTepB1YQe0zoDmdIx8LF0j3Xk2Tvyekry68pV/qdURFJEGb9pmEksJkMQZ927V1+FTUBeWP666Ln4bTkJwkDtSfN4fPC70hmew1zQdeZmZBrc8BbQpIS8tHQ7rOZk9E+H8tgJbCbpLjAqWrg7gzJlgosd5xamm5XOk5R5oU+3QvkKwOLIn5RgOYzjVkkPKE+tOECPIi/2hDRCFVYwSvC5knmGP6UCHbib+mSDnloB4RMX0h95p+i3QXdeiF0daelVQUhGY56ONRqAFKqDpJzzJ/q4g9ci7sHHNUW8amJWwBgt8iQ==","P":"/uTPchvRiNBlQTr7R5x3NSQMX62RTYqOWjPexaNTeB/Q2qgumKhWe/QGvsQLCTfjmFEDyFs7kcgDSDv3RSAqUm8dFqJKmvT2Hxpvb4/GCG6crH1fp1pBZ7OZ7mjd2zvPaSdOIaa4t+TYZOB7SHDP0xtR1EPVWkBhH1BPbggFXDM=","Q":"xin88RYcPBMO6aYz/7U7wvUb/byUou64yxkzY1sqPYZYOxm5v9VfqoT5LT8wcbynDe1yLmjxwshhOTrd3rj2AQL2DdaT6xuQRJ1XHjONpW0VmaHzLtOWxc+Z2P1MzpnhoewcedrCd+XTPkr4of7o1dEGcxCOnL9FQPa8l0vfCFM="}} \ No newline at end of file diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/wwwroot/images/anonymous-user.png b/templates/ms/applications/Company.Project.AuthServer.Host/wwwroot/images/anonymous-user.png new file mode 100644 index 0000000000000000000000000000000000000000..fdae8cbe7f82828aad2b59bc9615f80bf32aa426 GIT binary patch literal 23671 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 literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.AuthServer.Host/yarn.lock b/templates/ms/applications/Company.Project.AuthServer.Host/yarn.lock new file mode 100644 index 0000000..bd67af4 --- /dev/null +++ b/templates/ms/applications/Company.Project.AuthServer.Host/yarn.lock @@ -0,0 +1,337 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@abp/aspnetcore.mvc.ui.theme.basic@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-8.3.0.tgz#a2d17eb5da2c3abfad4bcc842cfcda0e58a130a4" + integrity sha512-T2dg7WlvNSrwTCfy5wk4gqiJ/15kIjMGM4wLXIJcMYn60yGY/YeX6Q4A3R/qJzfl4JdgW5rt3GpdKv86y/ADXg== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.0.tgz#5d6bb5181a62770e9cb967980b77e75c115c5ed7" + integrity sha512-o/0eh8jLS+YJiseTKzzioUz0vNnMFzyoz+mkyA4PlO1gqw2JFhzPhTBZ3cuyV9QlxUfEA8dWAkqAUX6vqiHwkw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~8.3.0" + "@abp/bootstrap" "~8.3.0" + "@abp/bootstrap-datepicker" "~8.3.0" + "@abp/bootstrap-daterangepicker" "~8.3.0" + "@abp/datatables.net-bs5" "~8.3.0" + "@abp/font-awesome" "~8.3.0" + "@abp/jquery-form" "~8.3.0" + "@abp/jquery-validation-unobtrusive" "~8.3.0" + "@abp/lodash" "~8.3.0" + "@abp/luxon" "~8.3.0" + "@abp/malihu-custom-scrollbar-plugin" "~8.3.0" + "@abp/moment" "~8.3.0" + "@abp/select2" "~8.3.0" + "@abp/sweetalert2" "~8.3.0" + "@abp/timeago" "~8.3.0" + "@abp/toastr" "~8.3.0" + +"@abp/aspnetcore.mvc.ui@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.0.tgz#d7ba0539bfcc6661a347dea7f952489010b3e816" + integrity sha512-OxgZhLKiXGFYYpNJ5O/IbhinsniiBPv9586e+1Soar0GckCMIIegJxnJb1Bo1O75blrcK2cIU6LqjRT1FXt2Lw== + dependencies: + ansi-colors "^4.1.3" + +"@abp/bootstrap-datepicker@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.0.tgz#8c1bf9efec37b671d8f28b8b1e89c1ac66684267" + integrity sha512-KCwMtm7x+cnKPeNMzhjDJUce0stwu4e57ibmvA6sMf1tmj+yB256O4E2hIDDohiT3vP/zV8HVHX6uATlcmGC9w== + dependencies: + bootstrap-datepicker "^1.10.0" + +"@abp/bootstrap-daterangepicker@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.0.tgz#2b8ed978333502677916f88cbb3e1d1b1c8a3a17" + integrity sha512-uQSfuCQogl4BujdqvtdAoSE+z32ci8FT5+i3gLfpqbgTaxvY/Kv5NxAUH5/1sjnuAE7SMWO+eVvI3V0pXgQohg== + dependencies: + bootstrap-daterangepicker "^3.1.0" + +"@abp/bootstrap@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.0.tgz#96d6ea7e6ac30f6e34e495a4224f56f7b2a1a7a3" + integrity sha512-5AmdTtakmWhZmHrb7ibvvf+KwF9OGadpAe7Kv9mNEE02K2qkp7Xw4r5o/bgVl7YfLC1FA6GZZXrV2s2t0gjHtg== + dependencies: + "@abp/core" "~8.3.0" + bootstrap "^5.3.3" + +"@abp/core@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.0.tgz#3a68f5a9549efcc3e13500e301f2576751b51445" + integrity sha512-zrxnZi4qij/Y4AZWaXuPqs3Dd7gBtU/onX7FkYxLgQDxYBfx+84QAnPRNRFKMWaD/wKbTUB0wA66U3t2aiQX9Q== + dependencies: + "@abp/utils" "~8.3.0" + +"@abp/datatables.net-bs5@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.0.tgz#21822ae4912a561afe9112925185aece03fcd0eb" + integrity sha512-GOGYSSHp3iPUDFRX2Y3C0wkiCOJDuYuK/zUSzQLNpOvBMZO+I/oWBcZM+qkVowIzsoRlAGV9+CVV2B/B05qidA== + dependencies: + "@abp/datatables.net" "~8.3.0" + datatables.net-bs5 "^2.0.8" + +"@abp/datatables.net@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.0.tgz#ff697758ce9309ba8311f23aec921c4722588c8b" + integrity sha512-4dIdv7eN1tVouOUrlF+MIdg8zQpecyH61waqLgy1q5jMZQivrTSFZ7UWMG3WVOAYjw5zSUZHZPbzA+ttnaOPkg== + dependencies: + "@abp/jquery" "~8.3.0" + datatables.net "^2.0.8" + +"@abp/font-awesome@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.0.tgz#9e4e9adc08dfca52c0a07d1608c5e5662675a4c9" + integrity sha512-NRxvM/dzvQC2Cj/F5i07XB/i6IVTmXcO9sOq6TWosWib0wGaPxRbCSjy8QUAYSD1QYaVQ30XMb3XXImaMGyd8A== + dependencies: + "@abp/core" "~8.3.0" + "@fortawesome/fontawesome-free" "^6.5.2" + +"@abp/jquery-form@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.0.tgz#fa2ad2fedbe3d3528ee94cbbd4f94d48f0cb5e4d" + integrity sha512-olP9FmpNVTbOIewsVua0moHVYXw4Sl3chFbvTDLG6vRBohLSjllUXfgY3UEIVWR1PCqnAg+iEJZl9NHB9iOLBg== + dependencies: + "@abp/jquery" "~8.3.0" + jquery-form "^4.3.0" + +"@abp/jquery-validation-unobtrusive@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.0.tgz#0992cdd33170df83c79aa3371038c0b30e451521" + integrity sha512-9hidjq8x8sTnP5O3K2b2x9NpxvPd9WB03ENR6OfvM89kfSmQapSvBZTlCu80YK9NaQJ6MLQRLYOCuc3GHcj3EQ== + dependencies: + "@abp/jquery-validation" "~8.3.0" + jquery-validation-unobtrusive "^4.0.0" + +"@abp/jquery-validation@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.0.tgz#bd6a72c6d86f116abe3b5d2adf3752bdbbcca887" + integrity sha512-6l5BZSa3N0Fou6Se7MfUSnI2dD4SYhZ2V988bgPJQ6p37XBOZ2OAj7LEIf5FSjtUzXjao/6/vqjkPNYreNikig== + dependencies: + "@abp/jquery" "~8.3.0" + jquery-validation "^1.20.1" + +"@abp/jquery@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.0.tgz#9be5ef2f769680226e6a1a981026590caf3b57ef" + integrity sha512-GsFY+n3EtS6B0pAoKd+xMnt5Dzi5bHvIbhLgDgfQfOBzAy3twGRWsPQ3nkuXXm8TppwujMNowU1oiLKPPm0AOA== + dependencies: + "@abp/core" "~8.3.0" + jquery "~3.7.1" + +"@abp/lodash@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.0.tgz#f5a0a496c999886f2d6999067bfac2e1f0c3969c" + integrity sha512-BiAsONbKR/RKG3WjRaMWVmhNe1ELEsykVq+ogG1Rhk3kwPbvze3TS8k2p0Lu/RC41/BmDUmJ5abg1pUMwkRT8w== + dependencies: + "@abp/core" "~8.3.0" + lodash "^4.17.21" + +"@abp/luxon@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.0.tgz#7dd3f756be1605506e26f7ac76b80cc082a12d07" + integrity sha512-8gdI5BtXkVp0sFg89QVDe8AvgQ7Qfq4JCqz2PMrKPSATR3H8GD6BCaEYpRp6CNTCjVrQjGZdzKgUyea1D3dHbw== + dependencies: + "@abp/core" "~8.3.0" + luxon "^3.4.4" + +"@abp/malihu-custom-scrollbar-plugin@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.0.tgz#c88c132c3402bbb02054ca7d446051950f87a817" + integrity sha512-nd/mb6LJa6fMxal8PGcIjIRIoZ/UHCd01WDC9YI2H4wGCGx0CA0JyHso5oc/OEzJhUL8ujO/vYm9uLb7YahPtA== + dependencies: + "@abp/core" "~8.3.0" + malihu-custom-scrollbar-plugin "^3.1.5" + +"@abp/moment@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.0.tgz#8e4f7a523ab76ef9e4cd96a399560bad38d38d1a" + integrity sha512-LywSsKuQ2GN/Btmle6CcTKa811zbvUWdC+RLQA792K9HyBs6LvN0qRRluEQZgplairRgh2pDOg8tdFlUERkv2w== + dependencies: + moment "^2.30.1" + +"@abp/select2@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.0.tgz#ef4742fcd345394767f46180f61c6cabbd0b3867" + integrity sha512-bdLt2+ImxxpiZl4HGbYJpdDROQUT7/Z/+8A+6oJNacq3lNekdvufLYgTMxKru6zTbnd9j3HFKMOTE1eRjb9Xqg== + dependencies: + "@abp/core" "~8.3.0" + select2 "^4.0.13" + +"@abp/sweetalert2@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.0.tgz#a63020d57e44f7940817287d3d9676288bfb85aa" + integrity sha512-ooqPM4Z2v2scnMo5l8ycTmp6t/sW4sCsvIkJ4TyM876WLQJaZxJdOao4RQWuU+dVFr9zg8cOwqLH4q7UEiO6ww== + dependencies: + "@abp/core" "~8.3.0" + sweetalert2 "^11.3.6" + +"@abp/timeago@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.0.tgz#b3b8d6927bf170f77af848bc1925e5ef6835bd55" + integrity sha512-Dd6xaUoF9Bp4F9WJnTsFBqY+Gt++UR7UmLvBZL/dvthkeNCu2I8MUsmshkUUjY0lIXpjZwefUOuyupQrgHXPMg== + dependencies: + "@abp/jquery" "~8.3.0" + timeago "^1.6.7" + +"@abp/toastr@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.0.tgz#e68a2bd8f731e79034594bc2c736f7c66b3df1af" + integrity sha512-aWK/RaX/FmcEKhJLjsw1A0K2c04m2fRJkmo9NwzBCSscy6Msw9IMkqNWLiFDThMU8/qKzq7wq3Vmk/C0IpeAwA== + dependencies: + "@abp/jquery" "~8.3.0" + toastr "^2.1.4" + +"@abp/utils@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.0.tgz#96ae9266ad4d833fd9d723acef7fc85fabf618d9" + integrity sha512-w/XAqza4Z8wBWRoj5uPNKbd1/bE9L/uUWk6EUSBKmljMRryWQBmaPkb1XgvrOMQIbyyF60tUvvipapQLPVh6hw== + dependencies: + just-compare "^2.3.0" + +"@fortawesome/fontawesome-free@^6.5.2": + version "6.6.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224" + integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +bootstrap-datepicker@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" + integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== + dependencies: + jquery ">=3.4.0 <4.0.0" + +bootstrap-daterangepicker@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" + integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== + dependencies: + jquery ">=1.10" + moment "^2.9.0" + +bootstrap@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" + integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== + +datatables.net-bs5@^2.0.8: + version "2.1.6" + resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.6.tgz#863c75472981d2cfad66f3cfd24e3c7da46986d6" + integrity sha512-GLp98kE2lJI6cBgLaCA1he+KhD3pcVJLK4QU8oD3Zb8uHAduX0BA2JPndFZqXJs4CS0L16fel8Xs3+0wGzFxSg== + dependencies: + datatables.net "2.1.6" + jquery ">=1.7" + +datatables.net@2.1.6, datatables.net@^2.0.8: + version "2.1.6" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.6.tgz#563a7fb2ae206a60a83ec0aba011ce7e75a65d1f" + integrity sha512-ziX0Wz91oDJ4o7gQNuGxQiVK91OUu/bRcXyxa6EZtDwLObmaGKpkCNS59QpzrGtIytQIVFtLfF1EDdYid5RVog== + dependencies: + jquery ">=1.7" + +jquery-form@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" + integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== + dependencies: + jquery ">=1.7.2" + +jquery-mousewheel@>=3.0.6: + version "3.1.13" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" + +jquery-validation-unobtrusive@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" + integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== + dependencies: + jquery "^3.6.0" + jquery-validation ">=1.19" + +jquery-validation@>=1.19, jquery-validation@^1.20.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" + integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== + +jquery@>=1.10: + version "3.7.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" + integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== + +jquery@>=1.12.0, jquery@>=1.7, jquery@>=1.7.2: + version "3.3.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" + +"jquery@>=1.5.0 <4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" + integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== + +"jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + +just-compare@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" + integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +luxon@^3.4.4: + version "3.5.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20" + integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ== + +malihu-custom-scrollbar-plugin@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" + integrity sha1-MQzsxeWUFaHCnp37XStuAdZqKe8= + dependencies: + jquery-mousewheel ">=3.0.6" + +moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +moment@^2.9.0: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +select2@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" + integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== + +sweetalert2@^11.3.6: + version "11.7.5" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.7.5.tgz#d905b792cfcb69d5db479f839151ce12d8804a8e" + integrity sha512-RBPKdK8Uf9/bz9r4vy7x6sGqf0MioSXt1po1lAwwcl3AwbjHVTc5S0yud4ZJKU1EhvJFVDrFoqIpHwWERwZJEA== + +timeago@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" + integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== + dependencies: + jquery ">=1.5.0 <4.0" + +toastr@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" + dependencies: + jquery ">=1.12.0" diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/BackendAdminAppMenuContributor.cs b/templates/ms/applications/Company.Project.BackendAdminApp.Host/BackendAdminAppMenuContributor.cs new file mode 100644 index 0000000..97c3185 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/BackendAdminAppMenuContributor.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.UI.Navigation; +using Volo.Abp.Users; + +namespace Company.Project.BackendAdminApp; + +public class BackendAdminAppMenuContributor : IMenuContributor +{ + private readonly IConfiguration _configuration; + + public BackendAdminAppMenuContributor(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name == StandardMenus.User) + { + await ConfigureUserMenuAsync(context); + } + } + + private Task ConfigureUserMenuAsync(MenuConfigurationContext context) + { + var currentUser = context.ServiceProvider.GetRequiredService(); + var identityServerUrl = _configuration["AuthServer:Authority"] ?? ""; + + if (currentUser.IsAuthenticated) + { + context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", "Manage Your Profile", $"{identityServerUrl.EnsureEndsWith('/')}Account/Manage", icon: "fa fa-cog", order: 1000, null, "_blank")); + context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", "Logout", url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000)); + } + + return Task.CompletedTask; + } +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/BrandingProvider.cs b/templates/ms/applications/Company.Project.BackendAdminApp.Host/BrandingProvider.cs new file mode 100644 index 0000000..8a7b0e2 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/BrandingProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace Company.Project.BackendAdminApp; + +public class BrandingProvider : DefaultBrandingProvider, ISingletonDependency +{ + public override string AppName => "Backend Admin App"; +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj index bff00ae..a119820 100644 --- a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.BackendAdminApp diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/AccountController.cs b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/AccountController.cs new file mode 100644 index 0000000..e3f9e1c --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/AccountController.cs @@ -0,0 +1,8 @@ +using Volo.Abp.AspNetCore.Mvc.Authentication; + +namespace Company.Project.BackendAdminApp.Controllers; + +public class AccountController : ChallengeAccountController +{ + +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/HomeController.cs b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..70dfecf --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Company.Project.BackendAdminApp.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("/Identity/Users"); + } +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/TestController.cs b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/TestController.cs new file mode 100644 index 0000000..6ef9c4a --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Controllers/TestController.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Json; + +namespace Company.Project.BackendAdminApp.Controllers; + +public class TestController : AbpController +{ + private readonly IJsonSerializer _jsonSerializer; + private readonly IPermissionChecker _permissionChecker; + + public TestController(IJsonSerializer jsonSerializer, IPermissionChecker permissionChecker) + { + _jsonSerializer = jsonSerializer; + _permissionChecker = permissionChecker; + } + + [HttpGet] + public async Task Index() + { + var newLine = Environment.NewLine + Environment.NewLine; + + return Content( + "Claims: " + User.Claims.Select(c => $"{c.Type} = {c.Value}").JoinAsString(" | ") + newLine + + "CurrentUser: " + _jsonSerializer.Serialize(CurrentUser) + newLine + + "access_token: " + await HttpContext.GetTokenAsync("access_token") + newLine + + "isGranted: AbpIdentity.Users: " + await _permissionChecker.IsGrantedAsync("AbpIdentity.Users") + ); + } +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile new file mode 100644 index 0000000..3d45bc6 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile @@ -0,0 +1,25 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj", "applications/Company.Project.BackendAdminApp.Host/"] +COPY ["modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj", "modules/product/src/ProductManagement.Web/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/applications/Company.Project.BackendAdminApp.Host" +RUN dotnet build "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.BackendAdminApp.Host.dll"] diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile.original b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile.original new file mode 100644 index 0000000..3d45bc6 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Dockerfile.original @@ -0,0 +1,25 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj", "applications/Company.Project.BackendAdminApp.Host/"] +COPY ["modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj", "modules/product/src/ProductManagement.Web/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/applications/Company.Project.BackendAdminApp.Host" +RUN dotnet build "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.BackendAdminApp.Host.dll"] diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/Properties/launchSettings.json b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Properties/launchSettings.json new file mode 100644 index 0000000..6fddbd5 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44354", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.BackendAdminApp.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44354", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/abp.resourcemapping.js b/templates/ms/applications/Company.Project.BackendAdminApp.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.Development.json b/templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.json b/templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.json new file mode 100644 index 0000000..5915bf7 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/appsettings.json @@ -0,0 +1,20 @@ +{ + "AuthServer": { + "Authority": "https://localhost:44399", + "RequireHttpsMetadata": "true", + "ClientId": "backend-admin-app-client", + "ClientSecret": "1q2w3e*" + }, + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44315/" + } + }, + "Redis": { + "Configuration": "localhost:6379" + }, + "Serilog": { + "MinimumLevel": { "Default": "Warning" } + }, + "AllowedHosts": "*" +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/gulpfile.js b/templates/ms/applications/Company.Project.BackendAdminApp.Host/gulpfile.js new file mode 100644 index 0000000..8660b9a --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/gulpfile.js @@ -0,0 +1,9 @@ +"use strict"; + +var gulp = require("gulp"), + path = require('path'), + copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js'); + +exports.default = function(){ + return copyResources(path.resolve('./')); +}; diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/package.json b/templates/ms/applications/Company.Project.BackendAdminApp.Host/package.json new file mode 100644 index 0000000..3415774 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "0.1.0", + "name": "my-project-backendadminapp-host", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" + } +} diff --git a/templates/ms/applications/Company.Project.BackendAdminApp.Host/yarn.lock b/templates/ms/applications/Company.Project.BackendAdminApp.Host/yarn.lock new file mode 100644 index 0000000..bd67af4 --- /dev/null +++ b/templates/ms/applications/Company.Project.BackendAdminApp.Host/yarn.lock @@ -0,0 +1,337 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@abp/aspnetcore.mvc.ui.theme.basic@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-8.3.0.tgz#a2d17eb5da2c3abfad4bcc842cfcda0e58a130a4" + integrity sha512-T2dg7WlvNSrwTCfy5wk4gqiJ/15kIjMGM4wLXIJcMYn60yGY/YeX6Q4A3R/qJzfl4JdgW5rt3GpdKv86y/ADXg== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.0.tgz#5d6bb5181a62770e9cb967980b77e75c115c5ed7" + integrity sha512-o/0eh8jLS+YJiseTKzzioUz0vNnMFzyoz+mkyA4PlO1gqw2JFhzPhTBZ3cuyV9QlxUfEA8dWAkqAUX6vqiHwkw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~8.3.0" + "@abp/bootstrap" "~8.3.0" + "@abp/bootstrap-datepicker" "~8.3.0" + "@abp/bootstrap-daterangepicker" "~8.3.0" + "@abp/datatables.net-bs5" "~8.3.0" + "@abp/font-awesome" "~8.3.0" + "@abp/jquery-form" "~8.3.0" + "@abp/jquery-validation-unobtrusive" "~8.3.0" + "@abp/lodash" "~8.3.0" + "@abp/luxon" "~8.3.0" + "@abp/malihu-custom-scrollbar-plugin" "~8.3.0" + "@abp/moment" "~8.3.0" + "@abp/select2" "~8.3.0" + "@abp/sweetalert2" "~8.3.0" + "@abp/timeago" "~8.3.0" + "@abp/toastr" "~8.3.0" + +"@abp/aspnetcore.mvc.ui@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.0.tgz#d7ba0539bfcc6661a347dea7f952489010b3e816" + integrity sha512-OxgZhLKiXGFYYpNJ5O/IbhinsniiBPv9586e+1Soar0GckCMIIegJxnJb1Bo1O75blrcK2cIU6LqjRT1FXt2Lw== + dependencies: + ansi-colors "^4.1.3" + +"@abp/bootstrap-datepicker@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.0.tgz#8c1bf9efec37b671d8f28b8b1e89c1ac66684267" + integrity sha512-KCwMtm7x+cnKPeNMzhjDJUce0stwu4e57ibmvA6sMf1tmj+yB256O4E2hIDDohiT3vP/zV8HVHX6uATlcmGC9w== + dependencies: + bootstrap-datepicker "^1.10.0" + +"@abp/bootstrap-daterangepicker@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.0.tgz#2b8ed978333502677916f88cbb3e1d1b1c8a3a17" + integrity sha512-uQSfuCQogl4BujdqvtdAoSE+z32ci8FT5+i3gLfpqbgTaxvY/Kv5NxAUH5/1sjnuAE7SMWO+eVvI3V0pXgQohg== + dependencies: + bootstrap-daterangepicker "^3.1.0" + +"@abp/bootstrap@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.0.tgz#96d6ea7e6ac30f6e34e495a4224f56f7b2a1a7a3" + integrity sha512-5AmdTtakmWhZmHrb7ibvvf+KwF9OGadpAe7Kv9mNEE02K2qkp7Xw4r5o/bgVl7YfLC1FA6GZZXrV2s2t0gjHtg== + dependencies: + "@abp/core" "~8.3.0" + bootstrap "^5.3.3" + +"@abp/core@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.0.tgz#3a68f5a9549efcc3e13500e301f2576751b51445" + integrity sha512-zrxnZi4qij/Y4AZWaXuPqs3Dd7gBtU/onX7FkYxLgQDxYBfx+84QAnPRNRFKMWaD/wKbTUB0wA66U3t2aiQX9Q== + dependencies: + "@abp/utils" "~8.3.0" + +"@abp/datatables.net-bs5@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.0.tgz#21822ae4912a561afe9112925185aece03fcd0eb" + integrity sha512-GOGYSSHp3iPUDFRX2Y3C0wkiCOJDuYuK/zUSzQLNpOvBMZO+I/oWBcZM+qkVowIzsoRlAGV9+CVV2B/B05qidA== + dependencies: + "@abp/datatables.net" "~8.3.0" + datatables.net-bs5 "^2.0.8" + +"@abp/datatables.net@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.0.tgz#ff697758ce9309ba8311f23aec921c4722588c8b" + integrity sha512-4dIdv7eN1tVouOUrlF+MIdg8zQpecyH61waqLgy1q5jMZQivrTSFZ7UWMG3WVOAYjw5zSUZHZPbzA+ttnaOPkg== + dependencies: + "@abp/jquery" "~8.3.0" + datatables.net "^2.0.8" + +"@abp/font-awesome@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.0.tgz#9e4e9adc08dfca52c0a07d1608c5e5662675a4c9" + integrity sha512-NRxvM/dzvQC2Cj/F5i07XB/i6IVTmXcO9sOq6TWosWib0wGaPxRbCSjy8QUAYSD1QYaVQ30XMb3XXImaMGyd8A== + dependencies: + "@abp/core" "~8.3.0" + "@fortawesome/fontawesome-free" "^6.5.2" + +"@abp/jquery-form@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.0.tgz#fa2ad2fedbe3d3528ee94cbbd4f94d48f0cb5e4d" + integrity sha512-olP9FmpNVTbOIewsVua0moHVYXw4Sl3chFbvTDLG6vRBohLSjllUXfgY3UEIVWR1PCqnAg+iEJZl9NHB9iOLBg== + dependencies: + "@abp/jquery" "~8.3.0" + jquery-form "^4.3.0" + +"@abp/jquery-validation-unobtrusive@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.0.tgz#0992cdd33170df83c79aa3371038c0b30e451521" + integrity sha512-9hidjq8x8sTnP5O3K2b2x9NpxvPd9WB03ENR6OfvM89kfSmQapSvBZTlCu80YK9NaQJ6MLQRLYOCuc3GHcj3EQ== + dependencies: + "@abp/jquery-validation" "~8.3.0" + jquery-validation-unobtrusive "^4.0.0" + +"@abp/jquery-validation@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.0.tgz#bd6a72c6d86f116abe3b5d2adf3752bdbbcca887" + integrity sha512-6l5BZSa3N0Fou6Se7MfUSnI2dD4SYhZ2V988bgPJQ6p37XBOZ2OAj7LEIf5FSjtUzXjao/6/vqjkPNYreNikig== + dependencies: + "@abp/jquery" "~8.3.0" + jquery-validation "^1.20.1" + +"@abp/jquery@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.0.tgz#9be5ef2f769680226e6a1a981026590caf3b57ef" + integrity sha512-GsFY+n3EtS6B0pAoKd+xMnt5Dzi5bHvIbhLgDgfQfOBzAy3twGRWsPQ3nkuXXm8TppwujMNowU1oiLKPPm0AOA== + dependencies: + "@abp/core" "~8.3.0" + jquery "~3.7.1" + +"@abp/lodash@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.0.tgz#f5a0a496c999886f2d6999067bfac2e1f0c3969c" + integrity sha512-BiAsONbKR/RKG3WjRaMWVmhNe1ELEsykVq+ogG1Rhk3kwPbvze3TS8k2p0Lu/RC41/BmDUmJ5abg1pUMwkRT8w== + dependencies: + "@abp/core" "~8.3.0" + lodash "^4.17.21" + +"@abp/luxon@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.0.tgz#7dd3f756be1605506e26f7ac76b80cc082a12d07" + integrity sha512-8gdI5BtXkVp0sFg89QVDe8AvgQ7Qfq4JCqz2PMrKPSATR3H8GD6BCaEYpRp6CNTCjVrQjGZdzKgUyea1D3dHbw== + dependencies: + "@abp/core" "~8.3.0" + luxon "^3.4.4" + +"@abp/malihu-custom-scrollbar-plugin@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.0.tgz#c88c132c3402bbb02054ca7d446051950f87a817" + integrity sha512-nd/mb6LJa6fMxal8PGcIjIRIoZ/UHCd01WDC9YI2H4wGCGx0CA0JyHso5oc/OEzJhUL8ujO/vYm9uLb7YahPtA== + dependencies: + "@abp/core" "~8.3.0" + malihu-custom-scrollbar-plugin "^3.1.5" + +"@abp/moment@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.0.tgz#8e4f7a523ab76ef9e4cd96a399560bad38d38d1a" + integrity sha512-LywSsKuQ2GN/Btmle6CcTKa811zbvUWdC+RLQA792K9HyBs6LvN0qRRluEQZgplairRgh2pDOg8tdFlUERkv2w== + dependencies: + moment "^2.30.1" + +"@abp/select2@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.0.tgz#ef4742fcd345394767f46180f61c6cabbd0b3867" + integrity sha512-bdLt2+ImxxpiZl4HGbYJpdDROQUT7/Z/+8A+6oJNacq3lNekdvufLYgTMxKru6zTbnd9j3HFKMOTE1eRjb9Xqg== + dependencies: + "@abp/core" "~8.3.0" + select2 "^4.0.13" + +"@abp/sweetalert2@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.0.tgz#a63020d57e44f7940817287d3d9676288bfb85aa" + integrity sha512-ooqPM4Z2v2scnMo5l8ycTmp6t/sW4sCsvIkJ4TyM876WLQJaZxJdOao4RQWuU+dVFr9zg8cOwqLH4q7UEiO6ww== + dependencies: + "@abp/core" "~8.3.0" + sweetalert2 "^11.3.6" + +"@abp/timeago@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.0.tgz#b3b8d6927bf170f77af848bc1925e5ef6835bd55" + integrity sha512-Dd6xaUoF9Bp4F9WJnTsFBqY+Gt++UR7UmLvBZL/dvthkeNCu2I8MUsmshkUUjY0lIXpjZwefUOuyupQrgHXPMg== + dependencies: + "@abp/jquery" "~8.3.0" + timeago "^1.6.7" + +"@abp/toastr@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.0.tgz#e68a2bd8f731e79034594bc2c736f7c66b3df1af" + integrity sha512-aWK/RaX/FmcEKhJLjsw1A0K2c04m2fRJkmo9NwzBCSscy6Msw9IMkqNWLiFDThMU8/qKzq7wq3Vmk/C0IpeAwA== + dependencies: + "@abp/jquery" "~8.3.0" + toastr "^2.1.4" + +"@abp/utils@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.0.tgz#96ae9266ad4d833fd9d723acef7fc85fabf618d9" + integrity sha512-w/XAqza4Z8wBWRoj5uPNKbd1/bE9L/uUWk6EUSBKmljMRryWQBmaPkb1XgvrOMQIbyyF60tUvvipapQLPVh6hw== + dependencies: + just-compare "^2.3.0" + +"@fortawesome/fontawesome-free@^6.5.2": + version "6.6.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224" + integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +bootstrap-datepicker@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" + integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== + dependencies: + jquery ">=3.4.0 <4.0.0" + +bootstrap-daterangepicker@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" + integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== + dependencies: + jquery ">=1.10" + moment "^2.9.0" + +bootstrap@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" + integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== + +datatables.net-bs5@^2.0.8: + version "2.1.6" + resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.6.tgz#863c75472981d2cfad66f3cfd24e3c7da46986d6" + integrity sha512-GLp98kE2lJI6cBgLaCA1he+KhD3pcVJLK4QU8oD3Zb8uHAduX0BA2JPndFZqXJs4CS0L16fel8Xs3+0wGzFxSg== + dependencies: + datatables.net "2.1.6" + jquery ">=1.7" + +datatables.net@2.1.6, datatables.net@^2.0.8: + version "2.1.6" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.6.tgz#563a7fb2ae206a60a83ec0aba011ce7e75a65d1f" + integrity sha512-ziX0Wz91oDJ4o7gQNuGxQiVK91OUu/bRcXyxa6EZtDwLObmaGKpkCNS59QpzrGtIytQIVFtLfF1EDdYid5RVog== + dependencies: + jquery ">=1.7" + +jquery-form@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" + integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== + dependencies: + jquery ">=1.7.2" + +jquery-mousewheel@>=3.0.6: + version "3.1.13" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" + +jquery-validation-unobtrusive@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" + integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== + dependencies: + jquery "^3.6.0" + jquery-validation ">=1.19" + +jquery-validation@>=1.19, jquery-validation@^1.20.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" + integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== + +jquery@>=1.10: + version "3.7.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" + integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== + +jquery@>=1.12.0, jquery@>=1.7, jquery@>=1.7.2: + version "3.3.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" + +"jquery@>=1.5.0 <4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" + integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== + +"jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + +just-compare@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" + integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +luxon@^3.4.4: + version "3.5.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20" + integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ== + +malihu-custom-scrollbar-plugin@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" + integrity sha1-MQzsxeWUFaHCnp37XStuAdZqKe8= + dependencies: + jquery-mousewheel ">=3.0.6" + +moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +moment@^2.9.0: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +select2@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" + integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== + +sweetalert2@^11.3.6: + version "11.7.5" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.7.5.tgz#d905b792cfcb69d5db479f839151ce12d8804a8e" + integrity sha512-RBPKdK8Uf9/bz9r4vy7x6sGqf0MioSXt1po1lAwwcl3AwbjHVTc5S0yud4ZJKU1EhvJFVDrFoqIpHwWERwZJEA== + +timeago@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" + integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== + dependencies: + jquery ">=1.5.0 <4.0" + +toastr@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" + dependencies: + jquery ">=1.12.0" diff --git a/templates/ms/applications/Company.Project.ConsoleClientDemo/ClientDemoService.cs b/templates/ms/applications/Company.Project.ConsoleClientDemo/ClientDemoService.cs new file mode 100644 index 0000000..629eb42 --- /dev/null +++ b/templates/ms/applications/Company.Project.ConsoleClientDemo/ClientDemoService.cs @@ -0,0 +1,146 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using ProductManagement; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Identity; +using Volo.Abp.IdentityModel; +using Volo.Abp.TenantManagement; + +namespace Company.Project.ConsoleClientDemo; + +public class ClientDemoService : ITransientDependency +{ + private readonly IIdentityUserAppService _userAppService; + private readonly ITenantAppService _tenantAppService; + private readonly IProductAppService _productAppService; + private readonly IIdentityModelAuthenticationService _authenticator; + private readonly AbpRemoteServiceOptions _remoteServiceOptions; + + public ClientDemoService( + IIdentityUserAppService userAppService, + IProductAppService productAppService, + IIdentityModelAuthenticationService authenticator, + IOptions remoteServiceOptions, + ITenantAppService tenantAppService) + { + _userAppService = userAppService; + _authenticator = authenticator; + _tenantAppService = tenantAppService; + _remoteServiceOptions = remoteServiceOptions.Value; + _productAppService = productAppService; + } + + public async Task RunAsync() + { + await TestWithHttpClient(); + await TestIdentityService(); + await TestTenantManagementService(); + await TestProductService(); + } + + private async Task TestWithHttpClient() + { + Console.WriteLine(); + Console.WriteLine("*** TestWithHttpClient ************************************"); + + try + { + using (var client = new HttpClient()) + { + await _authenticator.TryAuthenticateAsync(client); + + var url = GetServerUrl() + "Test/Index"; + + var response = await client.GetAsync(url); + + if (!response.IsSuccessStatusCode) + { + Console.WriteLine(response.StatusCode); + } + else + { + var responseContent = await response.Content.ReadAsStringAsync(); + Console.WriteLine(responseContent); + } + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + private async Task TestIdentityService() + { + Console.WriteLine(); + Console.WriteLine("*** TestIdentityService ************************************"); + + try + { + var output = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + Console.WriteLine("Total user count: " + output.TotalCount); + + foreach (var user in output.Items) + { + Console.WriteLine($"- UserName={user.UserName}, Email={user.Email}, Name={user.Name}, Surname={user.Surname}"); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + private async Task TestTenantManagementService() + { + Console.WriteLine(); + Console.WriteLine("*** TestTenantManagementService ************************************"); + + try + { + var output = await _tenantAppService.GetListAsync(new GetTenantsInput()); + + Console.WriteLine("Total tenant count: " + output.TotalCount); + + foreach (var tenant in output.Items) + { + Console.WriteLine($"- Id={tenant.Id}, Name={tenant.Name}"); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + private async Task TestProductService() + { + Console.WriteLine(); + Console.WriteLine("*** TestProductService ************************************"); + + try + { + var output = await _productAppService.GetListAsync(); + + Console.WriteLine("Total product count: " + output.Items.Count); + + foreach (var product in output.Items) + { + Console.WriteLine($"- Code={product.Code}, Name={product.Name}, Price={product.Price}, StockCount={product.StockCount}"); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + private string GetServerUrl() + { + return _remoteServiceOptions.RemoteServices.Default.BaseUrl.EnsureEndsWith('/'); + } +} diff --git a/templates/ms/applications/Company.Project.ConsoleClientDemo/Company.Project.ConsoleClientDemo.csproj b/templates/ms/applications/Company.Project.ConsoleClientDemo/Company.Project.ConsoleClientDemo.csproj new file mode 100644 index 0000000..fa017ca --- /dev/null +++ b/templates/ms/applications/Company.Project.ConsoleClientDemo/Company.Project.ConsoleClientDemo.csproj @@ -0,0 +1,26 @@ + + + net10.0 + Exe + Company.Project.ConsoleClientDemo + + + + + + + + + + + + + + + + + PreserveNewest + Always + + + diff --git a/templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoHostedService.cs b/templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoHostedService.cs new file mode 100644 index 0000000..4f200bc --- /dev/null +++ b/templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoHostedService.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Volo.Abp; + +namespace Company.Project.ConsoleClientDemo; + +public class ConsoleClientDemoHostedService : IHostedService +{ + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = AbpApplicationFactory.Create(options => + { + options.Services.AddLogging(loggingBuilder => + { + loggingBuilder.AddSerilog(dispose: true); + }); + })) + { + application.Initialize(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + application.Shutdown(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; +} diff --git a/templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoModule.cs b/templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoModule.cs new file mode 100644 index 0000000..dc9d291 --- /dev/null +++ b/templates/ms/applications/Company.Project.ConsoleClientDemo/ConsoleClientDemoModule.cs @@ -0,0 +1,20 @@ +using ProductManagement; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.TenantManagement; + +namespace Company.Project.ConsoleClientDemo; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpHttpClientIdentityModelModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(ProductManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule) +)] +public class ConsoleClientDemoModule : AbpModule +{ + +} diff --git a/templates/ms/applications/Company.Project.ConsoleClientDemo/Program.cs b/templates/ms/applications/Company.Project.ConsoleClientDemo/Program.cs new file mode 100644 index 0000000..96154f4 --- /dev/null +++ b/templates/ms/applications/Company.Project.ConsoleClientDemo/Program.cs @@ -0,0 +1,31 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace Company.Project.ConsoleClientDemo; + +internal class Program +{ + static async Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.File("Logs/logs.txt") + .CreateLogger(); + + Log.Information("Starting ConsoleClientDemo..."); + + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/templates/ms/applications/Company.Project.ConsoleClientDemo/appsettings.json b/templates/ms/applications/Company.Project.ConsoleClientDemo/appsettings.json new file mode 100644 index 0000000..2ebfaa8 --- /dev/null +++ b/templates/ms/applications/Company.Project.ConsoleClientDemo/appsettings.json @@ -0,0 +1,17 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44329/" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "client_credentials", + "ClientId": "console-client-demo", + "ClientSecret": "1q2w3e*", + "Authority": "https://localhost:44399", + "RequireHttpsMetadata": "true", + "Scope": "InternalGateway IdentityService ProductService" + } + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/BrandingProvider.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/BrandingProvider.cs new file mode 100644 index 0000000..f758363 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/BrandingProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace Company.Project.PublicWebSite; + +public class BrandingProvider : DefaultBrandingProvider, ISingletonDependency +{ + public override string AppName => "Public Web Site"; +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj b/templates/ms/applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj new file mode 100644 index 0000000..e71b8ba --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj @@ -0,0 +1,22 @@ + + + + net10.0 + Company.Project.PublicWebSite + + + + + + + + + + + + + + + + + diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile b/templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile new file mode 100644 index 0000000..40690f8 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY ["applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj", "applications/Company.Project.PublicWebSite.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/applications/Company.Project.PublicWebSite.Host" +RUN dotnet build "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.PublicWebSite.Host.dll"] diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile.original b/templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile.original new file mode 100644 index 0000000..40690f8 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Dockerfile.original @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY ["applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj", "applications/Company.Project.PublicWebSite.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/applications/Company.Project.PublicWebSite.Host" +RUN dotnet build "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.PublicWebSite.Host.dll"] diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml new file mode 100644 index 0000000..bc1f125 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml @@ -0,0 +1,158 @@ +@page +@using Volo.Abp.Users +@model Company.Project.PublicWebSite.Pages.IndexModel +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@inject IThemeManager ThemeManager +@inject ICurrentUser CurrentUser +@{ + Layout = ThemeManager.CurrentTheme.GetApplicationLayout(); +} +@section styles{ + +} + +
+
+

Public Web Site Application

+

Welcome to our web site...

+

+ This is a simple hero unit, a simple jumbotron-style component + for calling extra attention to featured content or information. +

+

+ + @if (CurrentUser.IsAuthenticated) + { + Logout + } + else + { +

+ +
+ } +

+
+ +
+
+
+
+
What is New?
+
+
+
+
+ +
+
+
+
Asus Transformer Book T300CHI-FH011H
+
+ 1249 +
+
+
+ +
+
+ +
+
+
+
Lego Star Wars - 75059 Sandcrawler UCS
+
+ $999 +
+
+
+ +
+
+ +
+
+
+
Nikon AF-S 50mm f/1.8 G Lens
+
+ $1499 +
+
+
+ +
+
+ +
+
+
+
What is Hot?
+
+
+
+
+
+
+ Aliquam erat volutpat. Praesent nec dapibus neque. Proin hendrerit, magna in faucibus +
+
+
+
+
+
+
+
+
Curabitur consectetur libero lacus, nec facilisis nulla facilisis non.
+
+
+
+
+
+
+
+
Duis et felis nec ipsum auctor .
+
+
+
+
+
+
+
+
Morbi eu dolor pellentesque, porttitor lorem vitae, pulvinar eros.
+
+
+
+
+ +
+
+
+
+
+
Contact Us
+
+
+ +
+ 47322 W Alexander Rd
(867) 322-5566
info@volosoft.com +
+

+ We are developing open source and commercial software development tools. +

+

+ Praesent et posuere dui. + felis. +

+
+ +
+
+
+
diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml.cs new file mode 100644 index 0000000..aec40b5 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Index.cshtml.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace Company.Project.PublicWebSite.Pages; + +public class IndexModel : AbpPageModel +{ + public void OnGet() + { + + } + + public async Task OnPostLoginAsync() + { + await HttpContext.ChallengeAsync("oidc"); + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml new file mode 100644 index 0000000..eb1859a --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml @@ -0,0 +1,55 @@ +@page +@using ProductManagement +@using Volo.Abp.Settings +@model Company.Project.PublicWebSite.Pages.ProductsModel +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@inject IThemeManager ThemeManager +@inject ISettingProvider SettingProvider +@{ + const int columnSize = 3; + Layout = ThemeManager.CurrentTheme.GetApplicationLayout(); +} +@section styles{ + +} +

Our Products

+
+ @for (int i = 0; i < Math.Ceiling(Model.Products.Items.Count / (double)columnSize); i++) + { + + @for (int j = 0; j < columnSize; j++) + { + + @if ((i * columnSize) + j < Model.Products.Items.Count) + { + var product = Model.Products.Items[(i * columnSize) + j]; +
+ @if (!product.ImageName.IsNullOrEmpty()) + { + + } + else + { + + } +
+
+
+
@product.Name
+ @product.Code - Stock count: @product.StockCount +
+
+
+ $@product.Price +
+
+
+ } +
+ } +
+ } +
+ +@* An example to show how to read settings from the client side / UI *@ +

Maximum allowed page size: @await SettingProvider.GetOrNullAsync(ProductManagementSettings.MaxPageSize)

diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml.cs new file mode 100644 index 0000000..982aada --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.cshtml.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using ProductManagement; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace Company.Project.PublicWebSite.Pages; + +public class ProductsModel : AbpPageModel +{ + public ListResultDto Products { get; set; } + + private readonly IPublicProductAppService _productAppService; + + public ProductsModel(IPublicProductAppService productAppService) + { + _productAppService = productAppService; + } + + public async Task OnGetAsync() + { + Products = await _productAppService.GetListAsync(); + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.css b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.css new file mode 100644 index 0000000..295ceba --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/Products.css @@ -0,0 +1,30 @@ +body { + background-color: #f9f9f9; +} + +.product-list-item { + background-color: #fff; + padding: 2em; + border: 1px solid #eee; + border-radius: 3px; + box-shadow: 0 0 10px rgba(0, 0, 0, .05); + margin-bottom: 2em; + transition: all .2s; +} + +.product-list-item:hover { + box-shadow: 0 0 20px rgba(0, 0, 0, .1); + cursor: pointer; +} + +.product-list-item img { + width: 100%; +} + +.product-list-item .text-muted { + opacity: .8 +} + +.product-info-box { + min-height: 80px; +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/_ViewImports.cshtml b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..231948b --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Program.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/Program.cs new file mode 100644 index 0000000..2d969a9 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Program.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; + +namespace Company.Project.PublicWebSite; + +public class Program +{ + public static void Main(string[] args) + { + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build(); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + + try { CreateHostBuilder(args).Build().Run(); } + catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly"); } + finally { Log.CloseAndFlush(); } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac().UseSerilog() + .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Properties/launchSettings.json b/templates/ms/applications/Company.Project.PublicWebSite.Host/Properties/launchSettings.json new file mode 100644 index 0000000..395f32b --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44335", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.PublicWebSite.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44335", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteHostModule.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteHostModule.cs new file mode 100644 index 0000000..1042e98 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteHostModule.cs @@ -0,0 +1,84 @@ +using System; +using Company.Project.Shared; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using ProductManagement; +using Volo.Abp; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Identity.Web; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.UI.Navigation; + +namespace Company.Project.PublicWebSite; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpIdentityWebModule), + typeof(AbpAspNetCoreMvcUiBasicThemeModule), + typeof(ProductManagementHttpApiClientModule) + )] +public class PublicWebSiteHostModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + }); + + Configure(options => + { + options.IsEnabled = ProjectConsts.IsMultiTenancyEnabled; + }); + + Configure(options => + { + options.MenuContributors.Add(new PublicWebSiteMenuContributor()); + }); + + context.Services.AddAuthentication(options => + { + options.DefaultScheme = "Cookies"; + options.DefaultChallengeScheme = "oidc"; + }) + .AddCookie("Cookies", options => + { + options.ExpireTimeSpan = TimeSpan.FromDays(365); + }) + .AddJwtBearer("oidc", options => + { + options.Authority = configuration["AuthServer:Authority"]; + options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); + options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters + { + ValidateAudience = false + }; + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + + if (ProjectConsts.IsMultiTenancyEnabled) + { + app.UseMultiTenancy(); + } + + app.UseAbpRequestLocalization(); + app.UseAuthorization(); + app.UseConfiguredEndpoints(); + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteMenuContributor.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteMenuContributor.cs new file mode 100644 index 0000000..dc55f55 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/PublicWebSiteMenuContributor.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using Volo.Abp.UI.Navigation; + +namespace Company.Project.PublicWebSite; + +public class PublicWebSiteMenuContributor : IMenuContributor +{ + public Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name != StandardMenus.Main) + { + return Task.CompletedTask; + } + + //TODO: Localize menu items + context.Menu.AddItem(new ApplicationMenuItem("App.Home", "Home", "/")); + context.Menu.AddItem(new ApplicationMenuItem("App.Products", "Products", "/Products")); + + return Task.CompletedTask; + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/Startup.cs b/templates/ms/applications/Company.Project.PublicWebSite.Host/Startup.cs new file mode 100644 index 0000000..043f711 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/Startup.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace Company.Project.PublicWebSite; + +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + services.AddApplication(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.InitializeApplication(); + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/abp.resourcemapping.js b/templates/ms/applications/Company.Project.PublicWebSite.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.Development.json b/templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.json b/templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.json new file mode 100644 index 0000000..f0c447f --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/appsettings.json @@ -0,0 +1,19 @@ +{ + "AuthServer": { + "Authority": "https://localhost:44399", + "RequireHttpsMetadata": "true", + "ClientId": "public-website-client", + "ClientSecret": "1q2w3e*" + }, + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44397/" + } + }, + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/gulpfile.js b/templates/ms/applications/Company.Project.PublicWebSite.Host/gulpfile.js new file mode 100644 index 0000000..8660b9a --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/gulpfile.js @@ -0,0 +1,9 @@ +"use strict"; + +var gulp = require("gulp"), + path = require('path'), + copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js'); + +exports.default = function(){ + return copyResources(path.resolve('./')); +}; diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/package.json b/templates/ms/applications/Company.Project.PublicWebSite.Host/package.json new file mode 100644 index 0000000..259b863 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "0.1.0", + "name": "my-project-publicwebsite-host", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" + } +} diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/asus.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/asus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..44de167813487758404baacf71d8f24a277ceeee GIT binary patch literal 33856 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

!G#H&xv6MNi6<~$jodT zlEMryBQL8Y8g-YJv>|PW6-7b@#gVG90%%c!%CHMk=~aLtax(t(Dyl_!?_9*uaoCIA zj+x4!U{}EKDk+Wm(?esa7L{QYJBpB~#)zpFL&K=Ct4{tgN0ooHiv0e)j7&Jan3$hP zG9^U6(jq9drZ})v%3x1N#18188=?AKkibv@dRL(D`Oqho>M(>#4C2zaeYiT2d}m~ zzC9m4pVTNnRc+pc zL|@sjjGl(O%)D;A?w4pF^bSI4=Na9|!5SFbm5_WCO}hMl>+ibx1G5Ez5qik{i<=P~ z3y1n|Z4vJl{)21jGW+=l1_Jk&(m~)@wJ!;NBK%>a1g|61VFAK7ekVj8N0~<@ZG!(& zE>yC&c;k?#?hvW;t$bPM(uYXpa>`@kuT&I0F8)$^vEg9x`me24o#R~*jyAQIM74jo z5dNQPUH?}5A>X*)XzdS(<>nx3v&Iv;#vkEDZg%+mBfNj95_lKdw)T?#4@jDh^-DzQ z1pjhZ+m+T=2(!EpX4n2>7Aw-l*HO*A6w&Gq2<}DfzbaGuM`c+D_|!L2%}YRf;AspcQG{-@qH#IW|sn>%^MxEEYE3uXl~)0X)m=l(>R zbNz+?@W}t+eiBfoc>^-8?D*Tf0;Y$JLAAr|bN%W6u>PYEVR!0OzQp|DqU78KWSa*pR6S}8~$Nm3A{%(yad8kgtSuX&1ERrL>`YsbqbfuPI5q#h7M}M1Yrub%k#vS9AZFY2 z>#s^xh;4oUngD*Q_Zc_DKuUQ({j0PjD?EXZw#mQx|EOMt?|&>L_J1toA4~aTA@cP* z|JV=Z|GfGw|LOiess!G?vuOpP|M{xOlct=}4XBSD e!^ZXZ`d4-QE5FIsy9sXVUlg%KrhK)(AEL literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/beats.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/beats.jpg new file mode 100644 index 0000000000000000000000000000000000000000..08417c235b2097373f7f239d47e0b579efb9bbb6 GIT binary patch literal 14994 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 Dxjr27 literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/lego.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/lego.jpg new file mode 100644 index 0000000000000000000000000000000000000000..63e31e95774b5ac232978c0266c8792c3dfe0225 GIT binary patch literal 96032 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 literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/nikon.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/nikon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6fb605a18830f916369834c1def5669331dbdf GIT binary patch literal 48244 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

    0S5UhTPbFpke+G0%4atTXJPJuJnu8DO!S6 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 literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/noimage.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/noimage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c5133c8c9b98f750b22a44530ba71e378fd0fdd GIT binary patch literal 9672 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

    +CHI~r!+P-at|%Tb*Oh? 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 MEt12Xs{elz0F7-dC;$Ke literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/yarn.lock b/templates/ms/applications/Company.Project.PublicWebSite.Host/yarn.lock new file mode 100644 index 0000000..cce87e1 --- /dev/null +++ b/templates/ms/applications/Company.Project.PublicWebSite.Host/yarn.lock @@ -0,0 +1,422 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@abp/aspnetcore.mvc.ui.theme.basic@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-8.3.0.tgz#a2d17eb5da2c3abfad4bcc842cfcda0e58a130a4" + integrity sha512-T2dg7WlvNSrwTCfy5wk4gqiJ/15kIjMGM4wLXIJcMYn60yGY/YeX6Q4A3R/qJzfl4JdgW5rt3GpdKv86y/ADXg== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.0.tgz#5d6bb5181a62770e9cb967980b77e75c115c5ed7" + integrity sha512-o/0eh8jLS+YJiseTKzzioUz0vNnMFzyoz+mkyA4PlO1gqw2JFhzPhTBZ3cuyV9QlxUfEA8dWAkqAUX6vqiHwkw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~8.3.0" + "@abp/bootstrap" "~8.3.0" + "@abp/bootstrap-datepicker" "~8.3.0" + "@abp/bootstrap-daterangepicker" "~8.3.0" + "@abp/datatables.net-bs5" "~8.3.0" + "@abp/font-awesome" "~8.3.0" + "@abp/jquery-form" "~8.3.0" + "@abp/jquery-validation-unobtrusive" "~8.3.0" + "@abp/lodash" "~8.3.0" + "@abp/luxon" "~8.3.0" + "@abp/malihu-custom-scrollbar-plugin" "~8.3.0" + "@abp/moment" "~8.3.0" + "@abp/select2" "~8.3.0" + "@abp/sweetalert2" "~8.3.0" + "@abp/timeago" "~8.3.0" + "@abp/toastr" "~8.3.0" + +"@abp/aspnetcore.mvc.ui@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.0.tgz#d7ba0539bfcc6661a347dea7f952489010b3e816" + integrity sha512-OxgZhLKiXGFYYpNJ5O/IbhinsniiBPv9586e+1Soar0GckCMIIegJxnJb1Bo1O75blrcK2cIU6LqjRT1FXt2Lw== + dependencies: + ansi-colors "^4.1.3" + +"@abp/blogging@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/blogging/-/blogging-8.3.0.tgz#2559f67b961ce3987a1dd59c138c223e19f36d51" + integrity sha512-z9ntHhxgDYxX31OpGbPVsy9eY3/zLJiCpEtRpvNYKrKAVsS4fZSxfaywvma8owBpYmwyw4uNHVLr4EXpq0oX2Q== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.0" + "@abp/owl.carousel" "~8.3.0" + "@abp/prismjs" "~8.3.0" + "@abp/tui-editor" "~8.3.0" + +"@abp/bootstrap-datepicker@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.0.tgz#8c1bf9efec37b671d8f28b8b1e89c1ac66684267" + integrity sha512-KCwMtm7x+cnKPeNMzhjDJUce0stwu4e57ibmvA6sMf1tmj+yB256O4E2hIDDohiT3vP/zV8HVHX6uATlcmGC9w== + dependencies: + bootstrap-datepicker "^1.10.0" + +"@abp/bootstrap-daterangepicker@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.0.tgz#2b8ed978333502677916f88cbb3e1d1b1c8a3a17" + integrity sha512-uQSfuCQogl4BujdqvtdAoSE+z32ci8FT5+i3gLfpqbgTaxvY/Kv5NxAUH5/1sjnuAE7SMWO+eVvI3V0pXgQohg== + dependencies: + bootstrap-daterangepicker "^3.1.0" + +"@abp/bootstrap@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.0.tgz#96d6ea7e6ac30f6e34e495a4224f56f7b2a1a7a3" + integrity sha512-5AmdTtakmWhZmHrb7ibvvf+KwF9OGadpAe7Kv9mNEE02K2qkp7Xw4r5o/bgVl7YfLC1FA6GZZXrV2s2t0gjHtg== + dependencies: + "@abp/core" "~8.3.0" + bootstrap "^5.3.3" + +"@abp/clipboard@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-8.3.0.tgz#1b171e533f768cf42c8fc0c9c67fac1c636fee8c" + integrity sha512-T0O4OaMxLLYztAxyvEc3onEOpGHB/C8/jDcvJwd7mgpLoi9zXVfHwpnzkx/egfNJMzp49STD6Jc+jACi8Uq+CQ== + dependencies: + "@abp/core" "~8.3.0" + clipboard "^2.0.11" + +"@abp/core@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.0.tgz#3a68f5a9549efcc3e13500e301f2576751b51445" + integrity sha512-zrxnZi4qij/Y4AZWaXuPqs3Dd7gBtU/onX7FkYxLgQDxYBfx+84QAnPRNRFKMWaD/wKbTUB0wA66U3t2aiQX9Q== + dependencies: + "@abp/utils" "~8.3.0" + +"@abp/datatables.net-bs5@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.0.tgz#21822ae4912a561afe9112925185aece03fcd0eb" + integrity sha512-GOGYSSHp3iPUDFRX2Y3C0wkiCOJDuYuK/zUSzQLNpOvBMZO+I/oWBcZM+qkVowIzsoRlAGV9+CVV2B/B05qidA== + dependencies: + "@abp/datatables.net" "~8.3.0" + datatables.net-bs5 "^2.0.8" + +"@abp/datatables.net@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.0.tgz#ff697758ce9309ba8311f23aec921c4722588c8b" + integrity sha512-4dIdv7eN1tVouOUrlF+MIdg8zQpecyH61waqLgy1q5jMZQivrTSFZ7UWMG3WVOAYjw5zSUZHZPbzA+ttnaOPkg== + dependencies: + "@abp/jquery" "~8.3.0" + datatables.net "^2.0.8" + +"@abp/font-awesome@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.0.tgz#9e4e9adc08dfca52c0a07d1608c5e5662675a4c9" + integrity sha512-NRxvM/dzvQC2Cj/F5i07XB/i6IVTmXcO9sOq6TWosWib0wGaPxRbCSjy8QUAYSD1QYaVQ30XMb3XXImaMGyd8A== + dependencies: + "@abp/core" "~8.3.0" + "@fortawesome/fontawesome-free" "^6.5.2" + +"@abp/jquery-form@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.0.tgz#fa2ad2fedbe3d3528ee94cbbd4f94d48f0cb5e4d" + integrity sha512-olP9FmpNVTbOIewsVua0moHVYXw4Sl3chFbvTDLG6vRBohLSjllUXfgY3UEIVWR1PCqnAg+iEJZl9NHB9iOLBg== + dependencies: + "@abp/jquery" "~8.3.0" + jquery-form "^4.3.0" + +"@abp/jquery-validation-unobtrusive@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.0.tgz#0992cdd33170df83c79aa3371038c0b30e451521" + integrity sha512-9hidjq8x8sTnP5O3K2b2x9NpxvPd9WB03ENR6OfvM89kfSmQapSvBZTlCu80YK9NaQJ6MLQRLYOCuc3GHcj3EQ== + dependencies: + "@abp/jquery-validation" "~8.3.0" + jquery-validation-unobtrusive "^4.0.0" + +"@abp/jquery-validation@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.0.tgz#bd6a72c6d86f116abe3b5d2adf3752bdbbcca887" + integrity sha512-6l5BZSa3N0Fou6Se7MfUSnI2dD4SYhZ2V988bgPJQ6p37XBOZ2OAj7LEIf5FSjtUzXjao/6/vqjkPNYreNikig== + dependencies: + "@abp/jquery" "~8.3.0" + jquery-validation "^1.20.1" + +"@abp/jquery@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.0.tgz#9be5ef2f769680226e6a1a981026590caf3b57ef" + integrity sha512-GsFY+n3EtS6B0pAoKd+xMnt5Dzi5bHvIbhLgDgfQfOBzAy3twGRWsPQ3nkuXXm8TppwujMNowU1oiLKPPm0AOA== + dependencies: + "@abp/core" "~8.3.0" + jquery "~3.7.1" + +"@abp/lodash@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.0.tgz#f5a0a496c999886f2d6999067bfac2e1f0c3969c" + integrity sha512-BiAsONbKR/RKG3WjRaMWVmhNe1ELEsykVq+ogG1Rhk3kwPbvze3TS8k2p0Lu/RC41/BmDUmJ5abg1pUMwkRT8w== + dependencies: + "@abp/core" "~8.3.0" + lodash "^4.17.21" + +"@abp/luxon@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.0.tgz#7dd3f756be1605506e26f7ac76b80cc082a12d07" + integrity sha512-8gdI5BtXkVp0sFg89QVDe8AvgQ7Qfq4JCqz2PMrKPSATR3H8GD6BCaEYpRp6CNTCjVrQjGZdzKgUyea1D3dHbw== + dependencies: + "@abp/core" "~8.3.0" + luxon "^3.4.4" + +"@abp/malihu-custom-scrollbar-plugin@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.0.tgz#c88c132c3402bbb02054ca7d446051950f87a817" + integrity sha512-nd/mb6LJa6fMxal8PGcIjIRIoZ/UHCd01WDC9YI2H4wGCGx0CA0JyHso5oc/OEzJhUL8ujO/vYm9uLb7YahPtA== + dependencies: + "@abp/core" "~8.3.0" + malihu-custom-scrollbar-plugin "^3.1.5" + +"@abp/moment@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.0.tgz#8e4f7a523ab76ef9e4cd96a399560bad38d38d1a" + integrity sha512-LywSsKuQ2GN/Btmle6CcTKa811zbvUWdC+RLQA792K9HyBs6LvN0qRRluEQZgplairRgh2pDOg8tdFlUERkv2w== + dependencies: + moment "^2.30.1" + +"@abp/owl.carousel@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/owl.carousel/-/owl.carousel-8.3.0.tgz#4a1128e7eb98511b890fb91ef7658b6d8d3381e7" + integrity sha512-nVBPb00XOInGNUFQgzNEN/ASZGJPl1FTxPXkg6aQQPPAQMz3ZJXByZrvej56zUR550M831XtRNmWoulI+/yVGQ== + dependencies: + "@abp/core" "~8.3.0" + owl.carousel "^2.3.4" + +"@abp/prismjs@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-8.3.0.tgz#0c87c63294d1452ed7152083d2fb6e70aa3aeae6" + integrity sha512-3wpwbqqlGRfQSLcBP+Qb2TKOoVGZVYYwOP6dP3So9ev8J5gFMDEizH9zLwRVHYrrsZZP8/etYnyZ0hn7ewuI5Q== + dependencies: + "@abp/clipboard" "~8.3.0" + "@abp/core" "~8.3.0" + prismjs "^1.29.0" + +"@abp/select2@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.0.tgz#ef4742fcd345394767f46180f61c6cabbd0b3867" + integrity sha512-bdLt2+ImxxpiZl4HGbYJpdDROQUT7/Z/+8A+6oJNacq3lNekdvufLYgTMxKru6zTbnd9j3HFKMOTE1eRjb9Xqg== + dependencies: + "@abp/core" "~8.3.0" + select2 "^4.0.13" + +"@abp/sweetalert2@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.0.tgz#a63020d57e44f7940817287d3d9676288bfb85aa" + integrity sha512-ooqPM4Z2v2scnMo5l8ycTmp6t/sW4sCsvIkJ4TyM876WLQJaZxJdOao4RQWuU+dVFr9zg8cOwqLH4q7UEiO6ww== + dependencies: + "@abp/core" "~8.3.0" + sweetalert2 "^11.3.6" + +"@abp/timeago@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.0.tgz#b3b8d6927bf170f77af848bc1925e5ef6835bd55" + integrity sha512-Dd6xaUoF9Bp4F9WJnTsFBqY+Gt++UR7UmLvBZL/dvthkeNCu2I8MUsmshkUUjY0lIXpjZwefUOuyupQrgHXPMg== + dependencies: + "@abp/jquery" "~8.3.0" + timeago "^1.6.7" + +"@abp/toastr@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.0.tgz#e68a2bd8f731e79034594bc2c736f7c66b3df1af" + integrity sha512-aWK/RaX/FmcEKhJLjsw1A0K2c04m2fRJkmo9NwzBCSscy6Msw9IMkqNWLiFDThMU8/qKzq7wq3Vmk/C0IpeAwA== + dependencies: + "@abp/jquery" "~8.3.0" + toastr "^2.1.4" + +"@abp/tui-editor@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-8.3.0.tgz#188360644140f3173b0347c1ce883612a5eb9e18" + integrity sha512-GNFuKvAlwihuzg91dekGZ5s5aLKySROHbLujanzaco1nfRvWehx+J+oCP0rHzQ3++DpxEXhlz05qW9I1gCEAKA== + dependencies: + "@abp/jquery" "~8.3.0" + "@abp/prismjs" "~8.3.0" + +"@abp/utils@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.0.tgz#96ae9266ad4d833fd9d723acef7fc85fabf618d9" + integrity sha512-w/XAqza4Z8wBWRoj5uPNKbd1/bE9L/uUWk6EUSBKmljMRryWQBmaPkb1XgvrOMQIbyyF60tUvvipapQLPVh6hw== + dependencies: + just-compare "^2.3.0" + +"@fortawesome/fontawesome-free@^6.5.2": + version "6.6.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224" + integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +bootstrap-datepicker@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" + integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== + dependencies: + jquery ">=3.4.0 <4.0.0" + +bootstrap-daterangepicker@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" + integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== + dependencies: + jquery ">=1.10" + moment "^2.9.0" + +bootstrap@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" + integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== + +clipboard@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5" + integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + +datatables.net-bs5@^2.0.8: + version "2.1.6" + resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.6.tgz#863c75472981d2cfad66f3cfd24e3c7da46986d6" + integrity sha512-GLp98kE2lJI6cBgLaCA1he+KhD3pcVJLK4QU8oD3Zb8uHAduX0BA2JPndFZqXJs4CS0L16fel8Xs3+0wGzFxSg== + dependencies: + datatables.net "2.1.6" + jquery ">=1.7" + +datatables.net@2.1.6, datatables.net@^2.0.8: + version "2.1.6" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.6.tgz#563a7fb2ae206a60a83ec0aba011ce7e75a65d1f" + integrity sha512-ziX0Wz91oDJ4o7gQNuGxQiVK91OUu/bRcXyxa6EZtDwLObmaGKpkCNS59QpzrGtIytQIVFtLfF1EDdYid5RVog== + dependencies: + jquery ">=1.7" + +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + +jquery-form@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" + integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== + dependencies: + jquery ">=1.7.2" + +jquery-mousewheel@>=3.0.6: + version "3.1.13" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" + +jquery-validation-unobtrusive@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" + integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== + dependencies: + jquery "^3.6.0" + jquery-validation ">=1.19" + +jquery-validation@>=1.19, jquery-validation@^1.20.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" + integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== + +jquery@>=1.10: + version "3.7.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" + integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== + +jquery@>=1.12.0, jquery@>=1.7, jquery@>=1.7.2, jquery@>=1.8.3: + version "3.3.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" + +"jquery@>=1.5.0 <4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" + integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== + +"jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + +just-compare@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" + integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +luxon@^3.4.4: + version "3.5.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20" + integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ== + +malihu-custom-scrollbar-plugin@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" + integrity sha1-MQzsxeWUFaHCnp37XStuAdZqKe8= + dependencies: + jquery-mousewheel ">=3.0.6" + +moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +moment@^2.9.0: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +owl.carousel@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/owl.carousel/-/owl.carousel-2.3.4.tgz#6c53dc8d24304b790e4f27a1dc4a655e973ccdc9" + dependencies: + jquery ">=1.8.3" + +prismjs@^1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + +select2@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" + integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== + +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + +sweetalert2@^11.3.6: + version "11.7.5" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.7.5.tgz#d905b792cfcb69d5db479f839151ce12d8804a8e" + integrity sha512-RBPKdK8Uf9/bz9r4vy7x6sGqf0MioSXt1po1lAwwcl3AwbjHVTc5S0yud4ZJKU1EhvJFVDrFoqIpHwWERwZJEA== + +timeago@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" + integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== + dependencies: + jquery ">=1.5.0 <4.0" + +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +toastr@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" + dependencies: + jquery ">=1.12.0" diff --git a/templates/ms/docker-compose.infrastructure.override.yml b/templates/ms/docker-compose.infrastructure.override.yml new file mode 100644 index 0000000..897faec --- /dev/null +++ b/templates/ms/docker-compose.infrastructure.override.yml @@ -0,0 +1,19 @@ +version: '3.7' + +services: + + sqlserver: + environment: + - SA_PASSWORD=yourStrong(!)Password + - ACCEPT_EULA=Y + ports: + - "1433:1433" + + rabbitmq: + ports: + - "15672:15672" + - "5672:5672" + + redis: + ports: + - "6379:6379" diff --git a/templates/ms/docker-compose.infrastructure.yml b/templates/ms/docker-compose.infrastructure.yml new file mode 100644 index 0000000..94f29b3 --- /dev/null +++ b/templates/ms/docker-compose.infrastructure.yml @@ -0,0 +1,15 @@ +version: '3.7' + +services: + + sqlserver: + image: mcr.microsoft.com/mssql/server + + rabbitmq: + image: 'rabbitmq:3-management-alpine' + + redis: + image: redis:alpine + +volumes: + dbdata: diff --git a/templates/ms/docker-compose.migrations.yml b/templates/ms/docker-compose.migrations.yml new file mode 100644 index 0000000..1f28634 --- /dev/null +++ b/templates/ms/docker-compose.migrations.yml @@ -0,0 +1,12 @@ +version: '3.7' + +services: + sqlserver: + + migrations: + image: 'Company.Project-migrations:${TAG:-latest}' + build: + context: . + dockerfile: databases/Dockerfile + depends_on: + - sqlserver diff --git a/templates/ms/docker-compose.override.yml b/templates/ms/docker-compose.override.yml new file mode 100644 index 0000000..dae81ef --- /dev/null +++ b/templates/ms/docker-compose.override.yml @@ -0,0 +1,74 @@ +version: '3.7' + +services: + + internal-gateway: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - AuthServer__Authority=http://auth-server:51511 + - ConnectionStrings__Default=Server=sqlserver;Database=Company.Project_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - Redis__Configuration=redis + - ReRoutes__0__DownstreamHostAndPorts__0__Host=identity-service + - ReRoutes__0__DownstreamHostAndPorts__0__Port=80 + - ReRoutes__1__DownstreamHostAndPorts__0__Host=product-service + - ReRoutes__1__DownstreamHostAndPorts__0__Port=80 + - GlobalConfiguration__BaseUrl=http://internal-gateway + ports: + - "80" + + public-web-gateway: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - AuthServer__Authority=http://auth-server:51511 + - ConnectionStrings__Default=Server=sqlserver;Database=Company.Project_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - Redis__Configuration=redis + - ReRoutes__0__DownstreamHostAndPorts__0__Host=product-service + - ReRoutes__0__DownstreamHostAndPorts__0__Port=80 + - GlobalConfiguration__BaseUrl=http://public-web-gateway + ports: + - "80" + + identity-service: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - AuthServer__Authority=http://auth-server:51511 + - ConnectionStrings__Default=Server=sqlserver;Database=Company.Project_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - Redis__Configuration=redis + - RabbitMQ__Connections__Default__HostName=rabbitmq + ports: + - "80" + + product-service: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - AuthServer__Authority=http://auth-server:51511 + - ConnectionStrings__Default=Server=sqlserver;Database=Company.Project_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__ProductManagement=Server=sqlserver;Database=Company.Project_ProductManagement;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - Redis__Configuration=redis + - RabbitMQ__Connections__Default__HostName=rabbitmq + ports: + - "80" + + auth-server: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:51511 + - ConnectionStrings__Default=Server=sqlserver;Database=Company.Project_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - Redis__Configuration=redis + - RabbitMQ__Connections__Default__HostName=rabbitmq + ports: + - 51511:51511 + + backend-admin-app: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - AuthServer__Authority=http://auth-server:51511 + - RemoteServices__Default__BaseUrl=http://internal-gateway/ + - Redis__Configuration=redis + ports: + - "80" diff --git a/templates/ms/docker-compose.yml b/templates/ms/docker-compose.yml new file mode 100644 index 0000000..08c840f --- /dev/null +++ b/templates/ms/docker-compose.yml @@ -0,0 +1,60 @@ +version: '3.7' + +services: + + internal-gateway: + image: 'Company.Project-internal-gateway:${TAG:-latest}' + build: + context: . + dockerfile: gateways/Company.Project.InternalGateway.Host/Dockerfile + depends_on: + - identity-service + - product-service + + public-web-gateway: + image: 'Company.Project-public-web-gateway:${TAG:-latest}' + build: + context: . + dockerfile: gateways/Company.Project.PublicWebGateway.Host/Dockerfile + depends_on: + - product-service + + identity-service: + image: 'Company.Project-identity-service:${TAG:-latest}' + build: + context: . + dockerfile: microservices/Company.Project.IdentityService.Host/Dockerfile + depends_on: + - rabbitmq + - redis + - sqlserver + + product-service: + image: 'Company.Project-product-service:${TAG:-latest}' + build: + context: . + dockerfile: microservices/Company.Project.ProductService.Host/Dockerfile + depends_on: + - sqlserver + - redis + + auth-server: + image: 'Company.Project-auth-server:${TAG:-latest}' + build: + context: . + dockerfile: applications/Company.Project.AuthServer.Host/Dockerfile + depends_on: + - redis + - rabbitmq + - identity-service + + backend-admin-app: + image: 'Company.Project-backend-admin-app:${TAG:-latest}' + build: + context: . + dockerfile: applications/Company.Project.BackendAdminApp.Host/Dockerfile + depends_on: + - internal-gateway + +volumes: + dbdata: diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/BackendAdminAppGatewayHostModule.cs b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/BackendAdminAppGatewayHostModule.cs new file mode 100644 index 0000000..8dfdac0 --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/BackendAdminAppGatewayHostModule.cs @@ -0,0 +1,93 @@ +using System; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Company.Project.Shared; +using ProductManagement; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc.Client; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Identity.Web; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; + +namespace Company.Project.BackendAdminAppGateway; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpHttpClientIdentityModelWebModule), + typeof(AbpIdentityWebModule), + typeof(AbpAspNetCoreMvcClientModule), + typeof(ProductManagementHttpApiModule), + typeof(ProductManagementWebModule) +)] +public class BackendAdminAppGatewayHostModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + Configure(options => + { + options.IsEnabled = ProjectConsts.IsMultiTenancyEnabled; + }); + + context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.Authority = configuration["AuthServer:Authority"]; + options.Audience = configuration["AuthServer:ApiName"]; + options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); + }); + + context.Services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "BackendAdminApp Gateway API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + + context.Services.AddOcelot(configuration); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + app.UseAbpClaimsMap(); + + if (ProjectConsts.IsMultiTenancyEnabled) + { + app.UseMultiTenancy(); + } + + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "BackendAdminApp Gateway API"); + }); + + app.UseAbpRequestLocalization(); + + app.MapWhen( + ctx => ctx.Request.Path.ToString().StartsWith("/api/abp/") || + ctx.Request.Path.ToString().StartsWith("/Abp/") || + ctx.Request.Path.ToString().StartsWith("/api/identity/"), + app2 => + { + app2.UseRouting(); + app2.UseConfiguredEndpoints(); + } + ); + + app.UseOcelot().Wait(); + } +} diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj new file mode 100644 index 0000000..6f9fc9e --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj @@ -0,0 +1,23 @@ + + + + net10.0 + Company.Project.BackendAdminAppGateway + + + + + + + + + + + + + + + + + + diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile new file mode 100644 index 0000000..ebbcd1b --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY ["gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj", "gateways/Company.Project.BackendAdminAppGateway.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/gateways/Company.Project.BackendAdminAppGateway.Host" +RUN dotnet build "Company.Project.BackendAdminAppGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.BackendAdminAppGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.BackendAdminAppGateway.Host.dll"] diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile.original b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile.original new file mode 100644 index 0000000..ebbcd1b --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile.original @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY ["gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj", "gateways/Company.Project.BackendAdminAppGateway.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "gateways/Company.Project.BackendAdminAppGateway.Host/Company.Project.BackendAdminAppGateway.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/gateways/Company.Project.BackendAdminAppGateway.Host" +RUN dotnet build "Company.Project.BackendAdminAppGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.BackendAdminAppGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.BackendAdminAppGateway.Host.dll"] diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Program.cs b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Program.cs new file mode 100644 index 0000000..554b866 --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Program.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Serilog; +using Volo.Abp; + +namespace Company.Project.BackendAdminAppGateway; + +public class Program +{ + public static void Main(string[] args) + { + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build(); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + + try + { + CreateHostBuilder(args).Build().Run(); + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly"); + } + finally + { + Log.CloseAndFlush(); + } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac() + .UseSerilog() + .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); +} diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Properties/launchSettings.json b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Properties/launchSettings.json new file mode 100644 index 0000000..401cf99 --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44315", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.BackendAdminAppGateway.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44315", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Startup.cs b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Startup.cs new file mode 100644 index 0000000..1b016a4 --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/Startup.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Company.Project.BackendAdminAppGateway; + +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + services.AddApplication(); + } + + public void Configure(IApplicationBuilder app, IHostEnvironment env) + { + app.InitializeApplication(); + } +} diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.Development.json b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.json b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.json new file mode 100644 index 0000000..af3828a --- /dev/null +++ b/templates/ms/gateways/Company.Project.BackendAdminAppGateway.Host/appsettings.json @@ -0,0 +1,60 @@ +{ + "AuthServer": { + "Authority": "https://localhost:44399", + "RequireHttpsMetadata": "true", + "ApiName": "BackendAdminAppGateway" + }, + "ConnectionStrings": { + "Default": "Server=(LocalDb)\\MSSQLLocalDB; Database=Company.Project_Identity; Trusted_Connection=True" + }, + "Redis": { + "Configuration": "localhost:6379" + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information" + } + }, + "Routes": [ + { + "DownstreamPathTemplate": "/api/identity/{everything}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44368 + } + ], + "UpstreamPathTemplate": "/api/identity/{everything}", + "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ] + }, + { + "DownstreamPathTemplate": "/api/multi-tenancy/{everything}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44336 + } + ], + "UpstreamPathTemplate": "/api/multi-tenancy/{everything}", + "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ] + }, + { + "DownstreamPathTemplate": "/api/productManagement/{everything}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44344 + } + ], + "UpstreamPathTemplate": "/api/productManagement/{everything}", + "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ] + } + ], + "GlobalConfiguration": { + "BaseUrl": "https://localhost:44315" + }, + "AllowedHosts": "*" +} diff --git a/templates/ms/gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj b/templates/ms/gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj index d1d56a5..87a9faf 100644 --- a/templates/ms/gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj +++ b/templates/ms/gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.InternalGateway diff --git a/templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile b/templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile new file mode 100644 index 0000000..00bffd5 --- /dev/null +++ b/templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj", "gateways/Company.Project.InternalGateway.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/gateways/Company.Project.InternalGateway.Host" +RUN dotnet build "Company.Project.InternalGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.InternalGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.InternalGateway.Host.dll"] diff --git a/templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile.original b/templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile.original new file mode 100644 index 0000000..00bffd5 --- /dev/null +++ b/templates/ms/gateways/Company.Project.InternalGateway.Host/Dockerfile.original @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj", "gateways/Company.Project.InternalGateway.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "gateways/Company.Project.InternalGateway.Host/Company.Project.InternalGateway.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/gateways/Company.Project.InternalGateway.Host" +RUN dotnet build "Company.Project.InternalGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.InternalGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.InternalGateway.Host.dll"] diff --git a/templates/ms/gateways/Company.Project.InternalGateway.Host/Properties/launchSettings.json b/templates/ms/gateways/Company.Project.InternalGateway.Host/Properties/launchSettings.json new file mode 100644 index 0000000..9985eac --- /dev/null +++ b/templates/ms/gateways/Company.Project.InternalGateway.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44329", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.InternalGateway.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44329", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/gateways/Company.Project.InternalGateway.Host/TestController.cs b/templates/ms/gateways/Company.Project.InternalGateway.Host/TestController.cs new file mode 100644 index 0000000..313d178 --- /dev/null +++ b/templates/ms/gateways/Company.Project.InternalGateway.Host/TestController.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Json; + +namespace Company.Project.InternalGateway; + +public class TestController : AbpController +{ + private readonly IJsonSerializer _jsonSerializer; + + public TestController(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + } + + [HttpGet] + public async Task Index() + { + var newLine = Environment.NewLine + Environment.NewLine; + + return Content( + "Claims: " + User.Claims.Select(c => $"{c.Type} = {c.Value}").JoinAsString(" | ") + newLine + + "CurrentUser: " + _jsonSerializer.Serialize(CurrentUser) + newLine + ); + } +} diff --git a/templates/ms/gateways/Company.Project.InternalGateway.Host/appsettings.Development.json b/templates/ms/gateways/Company.Project.InternalGateway.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/gateways/Company.Project.InternalGateway.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj index 4951c8e..dc26b1b 100644 --- a/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj +++ b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.PublicWebGateway diff --git a/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile new file mode 100644 index 0000000..daaa294 --- /dev/null +++ b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj", "gateways/Company.Project.PublicWebGateway.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/gateways/Company.Project.PublicWebGateway.Host" +RUN dotnet build "Company.Project.PublicWebGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.PublicWebGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.PublicWebGateway.Host.dll"] diff --git a/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile.original b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile.original new file mode 100644 index 0000000..daaa294 --- /dev/null +++ b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Dockerfile.original @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj", "gateways/Company.Project.PublicWebGateway.Host/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "gateways/Company.Project.PublicWebGateway.Host/Company.Project.PublicWebGateway.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/gateways/Company.Project.PublicWebGateway.Host" +RUN dotnet build "Company.Project.PublicWebGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.PublicWebGateway.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.PublicWebGateway.Host.dll"] diff --git a/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Properties/launchSettings.json b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Properties/launchSettings.json new file mode 100644 index 0000000..b03c9dd --- /dev/null +++ b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44397", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.PublicWebGateway.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44397", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/gateways/Company.Project.PublicWebGateway.Host/appsettings.Development.json b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/gateways/Company.Project.PublicWebGateway.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/BlogServiceDataSeeder.cs b/templates/ms/microservices/Company.Project.BloggingService.Host/BlogServiceDataSeeder.cs new file mode 100644 index 0000000..4182291 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/BlogServiceDataSeeder.cs @@ -0,0 +1,101 @@ +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; +using Volo.Blogging; +using Volo.Blogging.Blogs; +using Volo.Blogging.Posts; + +namespace Company.Project.BloggingService; + +public class BlogServiceDataSeeder : IDataSeedContributor, ITransientDependency +{ + private readonly IBlogRepository _blogRepository; + private readonly IPostRepository _postRepository; + private readonly IGuidGenerator _guidGenerator; + private readonly IPermissionDataSeeder _permissionDataSeeder; + + public BlogServiceDataSeeder( + IBlogRepository blogRepository, + IGuidGenerator guidGenerator, + IPostRepository postRepository, + IPermissionDataSeeder permissionDataSeeder) + { + _blogRepository = blogRepository; + _guidGenerator = guidGenerator; + _postRepository = postRepository; + _permissionDataSeeder = permissionDataSeeder; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateBlogPostsAsync(); + await GrantAdminPermissionsAsync(); + } + + private async Task GrantAdminPermissionsAsync() + { + await _permissionDataSeeder.SeedAsync( + RolePermissionValueProvider.ProviderName, + "admin", + BloggingPermissions.GetAll() + ); + } + + private async Task CreateBlogPostsAsync() + { + if (await _blogRepository.GetCountAsync() > 0) + { + return; + } + + var abpBlog = await _blogRepository.InsertAsync( + new Blog( + _guidGenerator.Create(), + "ABP", + "abp" + ) + ); + + await _postRepository.InsertAsync( + new Post( + _guidGenerator.Create(), + abpBlog.Id, + "Introduction to ABP vNext", + "/api/blogging/files/www/100d4c0445cbf55f687339ec8e656abb.jpg", + "introduction-to-abp-vnext" + ) + { + Content = @"### Introduction +For a while, we were working to design a new major version of the ASP.NET Boilerplate framework. Now, it's time to share it with the community. We are too excited and we believe that you are too. + +#### Naming +The name of the framework remains same, except we will call it only as ""ABP"" instead of ""ASP.NET Boilerplate"". Because, the ""boilerplate"" word leads to misunderstandings and does not reflect that it is a framework (instead of some boilerplate code). We continue to use the ""ABP"" name since it's the successor of the current ASP.NET Boilerplate framework, except it's a rewrite. + +### How To Start +We have created a startup template. You can just create a new project from https://abp.io/Templates and start your development. For more information, visit [abp.io](https://abp.io). + +### Why A Complete Rewrite? +When we first introduced the ABP framework, it was 2013 (5 years ago)! There was no .Net Core & ASP.NET Core and there was no Angular2+. + +ASP.NET Core introduced many built-in solutions (extension libraries) for dependency injection, logging, caching, localization, configuration and so on. +We wanted to depend on these new extension libraries instead of 3rd-party and custom solutions. + +#### Application Modularity +The first goal is to provide a good infrastructure to develop application modules. We think a module as a set of application features with its own database, its own entities, services, APIs, UI pages, components and so on. + +#### Microservices +We are designing the new ABP framework to be ready to develop microservices and communicate them to each other. + +### Communication / Links +* Official web site: [abp.io](https://abp.io) +* Github: [github.com/abpframework](https://github.com/abpframework) +* Twitter: [@abpframework](https://twitter.com/abpframework)" + } + ); + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/BloggingServiceHostModule.cs b/templates/ms/microservices/Company.Project.BloggingService.Host/BloggingServiceHostModule.cs new file mode 100644 index 0000000..a06edb6 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/BloggingServiceHostModule.cs @@ -0,0 +1,129 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Company.Project.Shared; +using StackExchange.Redis; +using Volo.Abp; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.Autofac; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.EventBus.RabbitMq; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; +using Volo.Abp.Threading; +using Volo.Blogging; + +namespace Company.Project.BloggingService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpEventBusRabbitMqModule), + typeof(AbpEntityFrameworkCoreSqlServerModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(BloggingHttpApiModule), + typeof(BloggingMongoDbModule), + typeof(BloggingApplicationModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule) +)] +public class BloggingServiceHostModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + Configure(options => + { + options.IsEnabled = ProjectConsts.IsMultiTenancyEnabled; + }); + + context.Services.AddAuthentication("Bearer") + .AddJwtBearer(options => + { + options.Authority = configuration["AuthServer:Authority"]; + options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); + options.Audience = configuration["AuthServer:ApiName"]; + }); + + context.Services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Blogging Service API", Version = "v1" }); + options.DocInclusionPredicate((_, _) => true); + options.CustomSchemaIds(type => type.FullName); + }); + + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + }); + + Configure(options => options.UseSqlServer()); + + context.Services.AddStackExchangeRedisCache(options => + { + options.Configuration = configuration["Redis:Configuration"]; + }); + + Configure(options => + { + options.IsEnabledForGetRequests = true; + options.ApplicationName = "BloggingService"; + }); + + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + context.Services.AddDataProtection() + .PersistKeysToStackExchangeRedis(redis, "Company.Project-DataProtection-Keys"); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + + if (ProjectConsts.IsMultiTenancyEnabled) + { + app.UseMultiTenancy(); + } + + app.UseAbpRequestLocalization(); + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Blogging Service API"); + }); + app.UseAuditing(); + app.UseConfiguredEndpoints(); + + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj b/templates/ms/microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj new file mode 100644 index 0000000..1e177fc --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj @@ -0,0 +1,27 @@ + + + net10.0 + Company.Project.BloggingService + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Controllers/HomeController.cs b/templates/ms/microservices/Company.Project.BloggingService.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..90548b8 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Company.Project.BloggingService.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("/swagger"); + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile b/templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile new file mode 100644 index 0000000..046e508 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj", "microservices/Company.Project.BloggingService.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.BloggingService.Host" +RUN dotnet build "Company.Project.BloggingService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.BloggingService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.BloggingService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile.original b/templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile.original new file mode 100644 index 0000000..046e508 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Dockerfile.original @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj", "microservices/Company.Project.BloggingService.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.BloggingService.Host/Company.Project.BloggingService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.BloggingService.Host" +RUN dotnet build "Company.Project.BloggingService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.BloggingService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.BloggingService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Program.cs b/templates/ms/microservices/Company.Project.BloggingService.Host/Program.cs new file mode 100644 index 0000000..c13886e --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Program.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; + +namespace Company.Project.BloggingService; + +public class Program +{ + public static void Main(string[] args) + { + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build(); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + + try { CreateHostBuilder(args).Build().Run(); } + catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly"); } + finally { Log.CloseAndFlush(); } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac().UseSerilog() + .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Properties/launchSettings.json b/templates/ms/microservices/Company.Project.BloggingService.Host/Properties/launchSettings.json new file mode 100644 index 0000000..0c177e9 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44357", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.BloggingService.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44357", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/Startup.cs b/templates/ms/microservices/Company.Project.BloggingService.Host/Startup.cs new file mode 100644 index 0000000..2fe68ef --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/Startup.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Company.Project.BloggingService; + +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + services.AddApplication(); + } + + public void Configure(IApplicationBuilder app, IHostEnvironment env) + { + app.InitializeApplication(); + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.Development.json b/templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.json b/templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.json new file mode 100644 index 0000000..d95aca4 --- /dev/null +++ b/templates/ms/microservices/Company.Project.BloggingService.Host/appsettings.json @@ -0,0 +1,25 @@ +{ + "AuthServer": { + "Authority": "https://localhost:44399", + "RequireHttpsMetadata": "true", + "ApiName": "BloggingService" + }, + "ConnectionStrings": { + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Company.Project_Identity;Trusted_Connection=True", + "Blogging": "mongodb://localhost:27017/Company.Project_Blogging" + }, + "Redis": { + "Configuration": "localhost:6379" + }, + "RabbitMQ": { + "Connections": { + "Default": { "HostName": "localhost" } + }, + "EventBus": { + "ClientName": "Company.Project_BloggingService", + "ExchangeName": "Company.Project" + } + }, + "Serilog": { "MinimumLevel": { "Default": "Information" } }, + "AllowedHosts": "*" +} diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj b/templates/ms/microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj index 5531ef7..4c71907 100644 --- a/templates/ms/microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.IdentityService diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/Controllers/HomeController.cs b/templates/ms/microservices/Company.Project.IdentityService.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..a6abbf5 --- /dev/null +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Company.Project.IdentityService.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("/swagger"); + } +} diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile b/templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile new file mode 100644 index 0000000..ccaef36 --- /dev/null +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj", "microservices/Company.Project.IdentityService.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.IdentityService.Host" +RUN dotnet build "Company.Project.IdentityService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.IdentityService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.IdentityService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile.original b/templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile.original new file mode 100644 index 0000000..ccaef36 --- /dev/null +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/Dockerfile.original @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj", "microservices/Company.Project.IdentityService.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.IdentityService.Host/Company.Project.IdentityService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.IdentityService.Host" +RUN dotnet build "Company.Project.IdentityService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.IdentityService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.IdentityService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/Properties/launchSettings.json b/templates/ms/microservices/Company.Project.IdentityService.Host/Properties/launchSettings.json new file mode 100644 index 0000000..ce26bfa --- /dev/null +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44368", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.IdentityService.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44368", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/Tenants/TenantCreatedDistributedEventHandler.cs b/templates/ms/microservices/Company.Project.IdentityService.Host/Tenants/TenantCreatedDistributedEventHandler.cs new file mode 100644 index 0000000..3663cef --- /dev/null +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/Tenants/TenantCreatedDistributedEventHandler.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TenantManagement; + +namespace Company.Project.IdentityService.Tenants; + +public class TenantCreatedDistributedEventHandler : IDistributedEventHandler>, ITransientDependency +{ + public ILogger Logger { get; set; } + private readonly IDataSeeder _dataSeeder; + private readonly ICurrentTenant _currentTenant; + + public TenantCreatedDistributedEventHandler( + IDataSeeder dataSeeder, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _currentTenant = currentTenant; + Logger = NullLogger.Instance; + } + + public async Task HandleEventAsync(EntityCreatedEto eventData) + { + Logger.LogInformation($"Handled distributed event for a new tenant creation. TenantId: {eventData.Entity.Id}"); + + using (_currentTenant.Change(eventData.Entity.Id, eventData.Entity.Name)) + { + await _dataSeeder.SeedAsync(tenantId: eventData.Entity.Id); + } + } +} diff --git a/templates/ms/microservices/Company.Project.IdentityService.Host/appsettings.Development.json b/templates/ms/microservices/Company.Project.IdentityService.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/microservices/Company.Project.IdentityService.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj b/templates/ms/microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj index 31b3582..f9908a0 100644 --- a/templates/ms/microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj +++ b/templates/ms/microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.ProductService diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/Controllers/HomeController.cs b/templates/ms/microservices/Company.Project.ProductService.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..54e37ee --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Company.Project.ProductService.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("/swagger"); + } +} diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile b/templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile new file mode 100644 index 0000000..1b1e6ea --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile @@ -0,0 +1,26 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj", "microservices/Company.Project.ProductService.Host/"] +COPY ["modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj", "modules/product/src/ProductManagement.EntityFrameworkCore/"] +COPY ["modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj", "modules/product/src/ProductManagement.Domain/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["modules/product/src/ProductManagement.Application/ProductManagement.Application.csproj", "modules/product/src/ProductManagement.Application/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.ProductService.Host" +RUN dotnet build "Company.Project.ProductService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.ProductService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.ProductService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile.original b/templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile.original new file mode 100644 index 0000000..1b1e6ea --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/Dockerfile.original @@ -0,0 +1,26 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj", "microservices/Company.Project.ProductService.Host/"] +COPY ["modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj", "modules/product/src/ProductManagement.EntityFrameworkCore/"] +COPY ["modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj", "modules/product/src/ProductManagement.Domain/"] +COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"] +COPY ["modules/product/src/ProductManagement.Application/ProductManagement.Application.csproj", "modules/product/src/ProductManagement.Application/"] +COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"] +COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.ProductService.Host/Company.Project.ProductService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.ProductService.Host" +RUN dotnet build "Company.Project.ProductService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.ProductService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.ProductService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContext.cs b/templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContext.cs new file mode 100644 index 0000000..41863be --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContext.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; +using ProductManagement.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace Company.Project.ProductService.EntityFrameworkCore; + +public class ProductServiceMigrationDbContext : AbpDbContext +{ + public ProductServiceMigrationDbContext( + DbContextOptions options + ) : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureProductManagement(); + } +} diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContextFactory.cs b/templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContextFactory.cs new file mode 100644 index 0000000..c224a05 --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/EntityFrameworkCore/ProductServiceMigrationDbContextFactory.cs @@ -0,0 +1,28 @@ +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace Company.Project.ProductService.EntityFrameworkCore; + +public class ProductServiceMigrationDbContextFactory : IDesignTimeDbContextFactory +{ + public ProductServiceMigrationDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseSqlServer(configuration.GetConnectionString("ProductManagement")); + + return new ProductServiceMigrationDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/ProductServiceDataSeeder.cs b/templates/ms/microservices/Company.Project.ProductService.Host/ProductServiceDataSeeder.cs new file mode 100644 index 0000000..33c2e09 --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/ProductServiceDataSeeder.cs @@ -0,0 +1,47 @@ +using System; +using System.Threading.Tasks; +using ProductManagement; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Uow; + +namespace Company.Project.ProductService; + +public class ProductServiceDataSeeder : IDataSeedContributor, ITransientDependency +{ + private readonly ProductManager _productManager; + private readonly IRepository _productRepository; + + public ProductServiceDataSeeder( + IRepository productRepository, + ProductManager productManager) + { + _productRepository = productRepository; + _productManager = productManager; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await AddProductsAsync(); + } + + private async Task AddProductsAsync() + { + if (await _productRepository.GetCountAsync() > 0) + { + return; + } + + await _productManager.CreateAsync("ABP04918", "Lego Star Wars - 75059 Sandcrawler UCS", 999, 42, "lego.jpg"); + await _productManager.CreateAsync("ABP23849", "Nikon AF-S 50mm f/1.8 G Lens", 1499, 56, "nikon.jpg"); + await _productManager.CreateAsync("ABP82731", "Beats Solo3 Wireless On-Ear Headphone", 97, 20, "beats.jpg"); + await _productManager.CreateAsync("ABP12322", "Rampage Sn-Rw2 Gamer Headphone", 654, 42, "rampage.jpg"); + await _productManager.CreateAsync("ABP00291", "Asus Transformer Book T300CHI-FH011H", 1249, 3, "asus.jpg"); + await _productManager.CreateAsync("ABP02918", "OKI C332DN Dublex + Network A4 Laser Printer", 215, 6, "oki.jpg"); + await _productManager.CreateAsync("ABP11121", "Bluecat Rd810 Mini Led", 449, 13, "bluecat.jpg"); + await _productManager.CreateAsync("ABP44432", "Sunny 55\" TV 4K Ultra HD Curved Smart Led TV", 2249, 1, "sunny.jpg"); + await _productManager.CreateAsync("ABP37182", "Sony Playstation 4 Slim 500 GB (PAL)", 699, 120, "playstation.jpg"); + } +} diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/Properties/launchSettings.json b/templates/ms/microservices/Company.Project.ProductService.Host/Properties/launchSettings.json new file mode 100644 index 0000000..6dc2b15 --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44344", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.ProductService.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44344", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/microservices/Company.Project.ProductService.Host/appsettings.Development.json b/templates/ms/microservices/Company.Project.ProductService.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/microservices/Company.Project.ProductService.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj new file mode 100644 index 0000000..2893f69 --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj @@ -0,0 +1,26 @@ + + + net10.0 + Company.Project.TenantManagementService + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Controllers/HomeController.cs b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..2927d91 --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Company.Project.TenantManagementService.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("/swagger"); + } +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile new file mode 100644 index 0000000..0f25fcb --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj", "microservices/Company.Project.TenantManagementService.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.TenantManagementService.Host" +RUN dotnet build "Company.Project.TenantManagementService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.TenantManagementService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.TenantManagementService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile.original b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile.original new file mode 100644 index 0000000..0f25fcb --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Dockerfile.original @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY ["microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj", "microservices/Company.Project.TenantManagementService.Host/"] +COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"] +RUN dotnet restore "microservices/Company.Project.TenantManagementService.Host/Company.Project.TenantManagementService.Host.csproj" -nowarn:msb3202,msb3277,nu1503 +COPY . . +WORKDIR "/src/microservices/Company.Project.TenantManagementService.Host" +RUN dotnet build "Company.Project.TenantManagementService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Company.Project.TenantManagementService.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Company.Project.TenantManagementService.Host.dll"] diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Program.cs b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Program.cs new file mode 100644 index 0000000..94ae355 --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Program.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; + +namespace Company.Project.TenantManagementService; + +public class Program +{ + public static void Main(string[] args) + { + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build(); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + + try { CreateHostBuilder(args).Build().Run(); } + catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly"); } + finally { Log.CloseAndFlush(); } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseAutofac().UseSerilog() + .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Properties/launchSettings.json b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Properties/launchSettings.json new file mode 100644 index 0000000..0ac008a --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44336", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Company.Project.TenantManagementService.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44336", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/Startup.cs b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Startup.cs new file mode 100644 index 0000000..29eccf2 --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/Startup.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Company.Project.TenantManagementService; + +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + services.AddApplication(); + } + + public void Configure(IApplicationBuilder app, IHostEnvironment env) + { + app.InitializeApplication(); + } +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/TenantManagementServiceHostModule.cs b/templates/ms/microservices/Company.Project.TenantManagementService.Host/TenantManagementServiceHostModule.cs new file mode 100644 index 0000000..c8642e6 --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/TenantManagementServiceHostModule.cs @@ -0,0 +1,120 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Company.Project.Shared; +using StackExchange.Redis; +using Volo.Abp; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Auditing; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.Autofac; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.EventBus.RabbitMq; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace Company.Project.TenantManagementService; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpEventBusRabbitMqModule), + typeof(AbpEntityFrameworkCoreSqlServerModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule), + typeof(AbpTenantManagementApplicationModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpIdentityEntityFrameworkCoreModule) +)] +public class TenantManagementServiceHostModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + Configure(options => + { + options.IsEnabled = ProjectConsts.IsMultiTenancyEnabled; + }); + + context.Services.AddAuthentication("Bearer") + .AddJwtBearer(options => + { + options.Authority = configuration["AuthServer:Authority"]; + options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); + options.Audience = configuration["AuthServer:ApiName"]; + }); + + context.Services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Tenant Management Service API", Version = "v1" }); + options.DocInclusionPredicate((_, _) => true); + options.CustomSchemaIds(type => type.FullName); + }); + + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + }); + + Configure(options => + { + options.AutoEventSelectors.Add(); + }); + + Configure(options => options.UseSqlServer()); + + context.Services.AddStackExchangeRedisCache(options => + { + options.Configuration = configuration["Redis:Configuration"]; + }); + + Configure(options => + { + options.IsEnabledForGetRequests = true; + options.ApplicationName = "TenantManagementService"; + }); + + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + context.Services.AddDataProtection() + .PersistKeysToStackExchangeRedis(redis, "Company.Project-DataProtection-Keys"); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + + if (ProjectConsts.IsMultiTenancyEnabled) + { + app.UseMultiTenancy(); + } + + app.UseAbpRequestLocalization(); + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Tenant Management Service API"); + }); + app.UseAuditing(); + app.UseConfiguredEndpoints(); + } +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.Development.json b/templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.json b/templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.json new file mode 100644 index 0000000..c01cdab --- /dev/null +++ b/templates/ms/microservices/Company.Project.TenantManagementService.Host/appsettings.json @@ -0,0 +1,24 @@ +{ + "AuthServer": { + "Authority": "https://localhost:44399", + "RequireHttpsMetadata": "true", + "ApiName": "TenantManagementService" + }, + "ConnectionStrings": { + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Company.Project_Identity;Trusted_Connection=True" + }, + "Redis": { + "Configuration": "localhost:6379" + }, + "RabbitMQ": { + "Connections": { + "Default": { "HostName": "localhost" } + }, + "EventBus": { + "ClientName": "Company.Project_TenantManagementService", + "ExchangeName": "Company.Project" + } + }, + "Serilog": { "MinimumLevel": { "Default": "Warning" } }, + "AllowedHosts": "*" +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/CreateProductDto.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/CreateProductDto.cs new file mode 100644 index 0000000..002e70a --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/CreateProductDto.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace ProductManagement; + +public class CreateProductDto +{ + [Required] + [StringLength(ProductConsts.MaxCodeLength)] + public string Code { get; set; } = string.Empty; + + [Required] + [StringLength(ProductConsts.MaxNameLength)] + public string Name { get; set; } = string.Empty; + + [StringLength(ProductConsts.MaxImageNameLength)] + public string? ImageName { get; set; } + + public float Price { get; set; } + + public int StockCount { get; set; } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IProductAppService.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IProductAppService.cs index 2946918..3affea8 100644 --- a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IProductAppService.cs +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IProductAppService.cs @@ -1,17 +1,21 @@ using System; +using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; namespace ProductManagement; -public interface IProductAppService : - ICrudAppService +public interface IProductAppService : IApplicationService { -} + Task> GetListPagedAsync(PagedAndSortedResultRequestDto input); -public class CreateUpdateProductDto -{ - public string Name { get; set; } = string.Empty; - public decimal Price { get; set; } - public int StockCount { get; set; } + Task> GetListAsync(); + + Task GetAsync(Guid id); + + Task CreateAsync(CreateProductDto input); + + Task UpdateAsync(Guid id, UpdateProductDto input); + + Task DeleteAsync(Guid id); } diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IPublicProductAppService.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IPublicProductAppService.cs new file mode 100644 index 0000000..b4f099e --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/IPublicProductAppService.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace ProductManagement; + +public interface IPublicProductAppService : IApplicationService +{ + Task> GetListAsync(); +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/cs.json b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/cs.json new file mode 100644 index 0000000..f2be0cf --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/cs.json @@ -0,0 +1,10 @@ +{ + "culture": "cs", + "texts": { + "Permission:ProductManagement": "Správa produktů", + "Permission:Products": "Produkty", + "Permission:Edit": "Upravit", + "Permission:Delete": "Smazat", + "Permission:Create": "Vytvořit" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/en.json b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/en.json new file mode 100644 index 0000000..5fe25ac --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/en.json @@ -0,0 +1,10 @@ +{ + "culture": "en", + "texts": { + "Permission:ProductManagement": "Product Management", + "Permission:Products": "Products", + "Permission:Edit": "Edit", + "Permission:Delete": "Delete", + "Permission:Create": "Create" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/pl-PL.json b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/pl-PL.json new file mode 100644 index 0000000..c3172c1 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/pl-PL.json @@ -0,0 +1,10 @@ +{ + "culture": "pl-PL", + "texts": { + "Permission:ProductManagement": "Zarządzanie produktami", + "Permission:Products": "Produkty", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:Create": "Utwórz" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/tr.json b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/tr.json new file mode 100644 index 0000000..51700bb --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/tr.json @@ -0,0 +1,10 @@ +{ + "culture": "tr", + "texts": { + "Permission:ProductManagement": "Ürün Yönetimi", + "Permission:Products": "Ürünler", + "Permission:Edit": "Güncelle", + "Permission:Delete": "Sil", + "Permission:Create": "Oluştur" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/vi.json b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000..97cca61 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/Localization/ApplicationContracts/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permission:ProductManagement": "Quản lý sản phẩm", + "Permission:Products": "Sản phẩm", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:Create": "Tạo" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductDto.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductDto.cs index 1d84427..eecf566 100644 --- a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductDto.cs +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductDto.cs @@ -3,9 +3,11 @@ using Volo.Abp.Application.Dtos; namespace ProductManagement; -public class ProductDto : FullAuditedEntityDto +public class ProductDto : AuditedEntityDto { + public string Code { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; - public decimal Price { get; set; } + public string? ImageName { get; set; } + public float Price { get; set; } public int StockCount { get; set; } } diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj index 5753226..7b5ada2 100644 --- a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj @@ -1,5 +1,5 @@ - netstandard2.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementApplicationContractsModule.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementApplicationContractsModule.cs index 9cacb01..95f3554 100644 --- a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementApplicationContractsModule.cs +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementApplicationContractsModule.cs @@ -1,6 +1,10 @@ +using Volo.Abp.Application; using Volo.Abp.Modularity; namespace ProductManagement; -[DependsOn(typeof(ProductManagementDomainSharedModule))] +[DependsOn( + typeof(ProductManagementDomainSharedModule), + typeof(AbpDddApplicationContractsModule) +)] public class ProductManagementApplicationContractsModule : AbpModule { } diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissionDefinitionProvider.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissionDefinitionProvider.cs new file mode 100644 index 0000000..e05cbbc --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissionDefinitionProvider.cs @@ -0,0 +1,23 @@ +using ProductManagement.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace ProductManagement; + +public class ProductManagementPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var productManagementGroup = context.AddGroup(ProductManagementPermissions.GroupName, L("Permission:ProductManagement")); + + var products = productManagementGroup.AddPermission(ProductManagementPermissions.Products.Default, L("Permission:Products")); + products.AddChild(ProductManagementPermissions.Products.Update, L("Permission:Edit")); + products.AddChild(ProductManagementPermissions.Products.Delete, L("Permission:Delete")); + products.AddChild(ProductManagementPermissions.Products.Create, L("Permission:Create")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissions.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissions.cs new file mode 100644 index 0000000..1e1a50f --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementPermissions.cs @@ -0,0 +1,21 @@ +using Volo.Abp.Reflection; + +namespace ProductManagement; + +public class ProductManagementPermissions +{ + public const string GroupName = "ProductManagement"; + + public static class Products + { + public const string Default = GroupName + ".Product"; + public const string Delete = Default + ".Delete"; + public const string Update = Default + ".Update"; + public const string Create = Default + ".Create"; + } + + public static string[] GetAll() + { + return ReflectionHelper.GetPublicConstantsRecursively(typeof(ProductManagementPermissions)); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettingDefinitionProvider.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettingDefinitionProvider.cs new file mode 100644 index 0000000..1bdb0c5 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettingDefinitionProvider.cs @@ -0,0 +1,17 @@ +using Volo.Abp.Settings; + +namespace ProductManagement; + +public class ProductManagementSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + context.Add( + new SettingDefinition( + ProductManagementSettings.MaxPageSize, + "100", + isVisibleToClients: true + ) + ); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettings.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettings.cs new file mode 100644 index 0000000..7d809c0 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/ProductManagementSettings.cs @@ -0,0 +1,11 @@ +namespace ProductManagement; + +public static class ProductManagementSettings +{ + public const string GroupName = "ProductManagement"; + + ///

    + /// Maximum allowed page size for paged list requests. + /// + public const string MaxPageSize = GroupName + ".MaxPageSize"; +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application.Contracts/UpdateProductDto.cs b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/UpdateProductDto.cs new file mode 100644 index 0000000..8355c5e --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application.Contracts/UpdateProductDto.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; + +namespace ProductManagement; + +public class UpdateProductDto +{ + [Required] + [StringLength(ProductConsts.MaxNameLength)] + public string Name { get; set; } = string.Empty; + + [StringLength(ProductConsts.MaxImageNameLength)] + public string? ImageName { get; set; } + + public float Price { get; set; } + + public int StockCount { get; set; } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application/ProductAppService.cs b/templates/ms/modules/product/src/ProductManagement.Application/ProductAppService.cs index d28a2ea..607dfee 100644 --- a/templates/ms/modules/product/src/ProductManagement.Application/ProductAppService.cs +++ b/templates/ms/modules/product/src/ProductManagement.Application/ProductAppService.cs @@ -1,14 +1,97 @@ using System; +using System.Collections.Generic; +using System.Linq.Dynamic.Core; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.EntityFrameworkCore; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; namespace ProductManagement; -public class ProductAppService : - CrudAppService, - IProductAppService +[Authorize(ProductManagementPermissions.Products.Default)] +public class ProductAppService : ApplicationService, IProductAppService { - public ProductAppService(IRepository repository) - : base(repository) { } + private readonly ProductManager _productManager; + private readonly IRepository _productRepository; + + public ProductAppService(ProductManager productManager, IRepository productRepository) + { + _productManager = productManager; + _productRepository = productRepository; + } + + public async Task> GetListPagedAsync(PagedAndSortedResultRequestDto input) + { + await NormalizeMaxResultCountAsync(input); + + var queryable = await _productRepository.GetQueryableAsync(); + var products = await queryable + .OrderBy(input.Sorting ?? "Name") + .Skip(input.SkipCount) + .Take(input.MaxResultCount) + .ToListAsync(); + + var totalCount = await _productRepository.GetCountAsync(); + var dtos = ObjectMapper.Map, List>(products); + + return new PagedResultDto(totalCount, dtos); + } + + public async Task> GetListAsync() + { + var products = await _productRepository.GetListAsync(); + var productList = ObjectMapper.Map, List>(products); + return new ListResultDto(productList); + } + + public async Task GetAsync(Guid id) + { + var product = await _productRepository.GetAsync(id); + return ObjectMapper.Map(product); + } + + [Authorize(ProductManagementPermissions.Products.Create)] + public async Task CreateAsync(CreateProductDto input) + { + var product = await _productManager.CreateAsync( + input.Code, + input.Name, + input.Price, + input.StockCount, + input.ImageName + ); + + return ObjectMapper.Map(product); + } + + [Authorize(ProductManagementPermissions.Products.Update)] + public async Task UpdateAsync(Guid id, UpdateProductDto input) + { + var product = await _productRepository.GetAsync(id); + + product.SetName(input.Name); + product.SetPrice(input.Price); + product.SetStockCount(input.StockCount); + product.SetImageName(input.ImageName); + + return ObjectMapper.Map(product); + } + + [Authorize(ProductManagementPermissions.Products.Delete)] + public async Task DeleteAsync(Guid id) + { + await _productRepository.DeleteAsync(id); + } + + private async Task NormalizeMaxResultCountAsync(PagedAndSortedResultRequestDto input) + { + var maxPageSize = (await SettingProvider.GetOrNullAsync(ProductManagementSettings.MaxPageSize))?.To(); + if (maxPageSize.HasValue && input.MaxResultCount > maxPageSize.Value) + { + input.MaxResultCount = maxPageSize.Value; + } + } } diff --git a/templates/ms/modules/product/src/ProductManagement.Application/ProductManagement.Application.csproj b/templates/ms/modules/product/src/ProductManagement.Application/ProductManagement.Application.csproj index c0500ae..f8013a9 100644 --- a/templates/ms/modules/product/src/ProductManagement.Application/ProductManagement.Application.csproj +++ b/templates/ms/modules/product/src/ProductManagement.Application/ProductManagement.Application.csproj @@ -1,5 +1,5 @@ - net8.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.Application/ProductManagementApplicationAutoMapperProfile.cs b/templates/ms/modules/product/src/ProductManagement.Application/ProductManagementApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..19a3dc0 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application/ProductManagementApplicationAutoMapperProfile.cs @@ -0,0 +1,11 @@ +using AutoMapper; + +namespace ProductManagement; + +public class ProductManagementApplicationAutoMapperProfile : Profile +{ + public ProductManagementApplicationAutoMapperProfile() + { + CreateMap(); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Application/PublicProductAppService.cs b/templates/ms/modules/product/src/ProductManagement.Application/PublicProductAppService.cs new file mode 100644 index 0000000..72524de --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Application/PublicProductAppService.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace ProductManagement; + +public class PublicProductAppService : ApplicationService, IPublicProductAppService +{ + private readonly IRepository _productRepository; + + public PublicProductAppService(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task> GetListAsync() + { + return new ListResultDto( + ObjectMapper.Map, List>( + await _productRepository.GetListAsync() + ) + ); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/Localization/ProductManagementResource.cs b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/Localization/ProductManagementResource.cs new file mode 100644 index 0000000..74e8bef --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/Localization/ProductManagementResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace ProductManagement.Localization; + +[LocalizationResourceName("ProductManagement")] +public class ProductManagementResource +{ + +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductConsts.cs b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductConsts.cs new file mode 100644 index 0000000..036dafe --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductConsts.cs @@ -0,0 +1,8 @@ +namespace ProductManagement; + +public static class ProductConsts +{ + public const int MaxCodeLength = 32; + public const int MaxNameLength = 256; + public const int MaxImageNameLength = 128; +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj index 08dafea..88cd8d6 100644 --- a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj +++ b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj @@ -1,5 +1,5 @@ - netstandard2.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainErrorCodes.cs b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainErrorCodes.cs new file mode 100644 index 0000000..10fe826 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainErrorCodes.cs @@ -0,0 +1,6 @@ +namespace ProductManagement; + +public static class ProductManagementDomainErrorCodes +{ + //Add your business exception error codes here... +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainSharedModule.cs b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainSharedModule.cs index 19fe49b..73aecb2 100644 --- a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainSharedModule.cs +++ b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductManagementDomainSharedModule.cs @@ -1,7 +1,17 @@ -using Volo.Abp.Modularity; +using ProductManagement.Localization; using Volo.Abp.Localization; +using Volo.Abp.Modularity; namespace ProductManagement; [DependsOn(typeof(AbpLocalizationModule))] -public class ProductManagementDomainSharedModule : AbpModule { } +public class ProductManagementDomainSharedModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Resources.Add("en"); + }); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductStockCountChangedEto.cs b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductStockCountChangedEto.cs new file mode 100644 index 0000000..0feec7e --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain.Shared/ProductStockCountChangedEto.cs @@ -0,0 +1,25 @@ +using System; +using Volo.Abp.Domain.Entities.Events.Distributed; + +namespace ProductManagement; + +[Serializable] +public class ProductStockCountChangedEto : EtoBase +{ + public Guid Id { get; } + + public int OldCount { get; set; } + + public int CurrentCount { get; set; } + + private ProductStockCountChangedEto() + { + } + + public ProductStockCountChangedEto(Guid id, int oldCount, int currentCount) + { + Id = id; + OldCount = oldCount; + CurrentCount = currentCount; + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/cs.json b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/cs.json new file mode 100644 index 0000000..b74a907 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/cs.json @@ -0,0 +1,5 @@ +{ + "culture": "cs", + "texts": { + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/en.json b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/en.json new file mode 100644 index 0000000..2dd7120 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/en.json @@ -0,0 +1,6 @@ +{ + "culture": "en", + "texts": { + + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/pl-PL.json b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/pl-PL.json new file mode 100644 index 0000000..b61f16b --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/pl-PL.json @@ -0,0 +1,6 @@ +{ + "culture": "pl-PL", + "texts": { + + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi new file mode 100644 index 0000000..ce9950d --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi @@ -0,0 +1 @@ +{"culture":"vi","texts":{}} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi.json b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi.json new file mode 100644 index 0000000..70fc26c --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/Localization/Domain/vi.json @@ -0,0 +1,5 @@ +{ + "culture": "vi", + "texts": { + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/Product.cs b/templates/ms/modules/product/src/ProductManagement.Domain/Product.cs index efb9009..fef23ed 100644 --- a/templates/ms/modules/product/src/ProductManagement.Domain/Product.cs +++ b/templates/ms/modules/product/src/ProductManagement.Domain/Product.cs @@ -1,11 +1,120 @@ using System; +using JetBrains.Annotations; +using Volo.Abp; using Volo.Abp.Domain.Entities.Auditing; namespace ProductManagement; -public class Product : FullAuditedAggregateRoot +public class Product : AuditedAggregateRoot { - public string Name { get; set; } = string.Empty; - public decimal Price { get; set; } - public int StockCount { get; set; } + [NotNull] + public string Code { get; private set; } + + [NotNull] + public string Name { get; private set; } + + public float Price { get; private set; } + + public int StockCount { get; private set; } + + public string? ImageName { get; private set; } + + private Product() + { + } + + internal Product( + Guid id, + [NotNull] string code, + [NotNull] string name, + float price = 0.0f, + int stockCount = 0, + string? imageName = null) + { + Check.NotNullOrWhiteSpace(code, nameof(code)); + + if (code.Length >= ProductConsts.MaxCodeLength) + { + throw new ArgumentException($"Product code can not be longer than {ProductConsts.MaxCodeLength}"); + } + + Id = id; + Code = code; + SetName(Check.NotNullOrWhiteSpace(name, nameof(name))); + SetPrice(price); + SetImageName(imageName); + SetStockCountInternal(stockCount, triggerEvent: false); + } + + public Product SetName([NotNull] string name) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + + if (name.Length >= ProductConsts.MaxNameLength) + { + throw new ArgumentException($"Product name can not be longer than {ProductConsts.MaxNameLength}"); + } + + Name = name; + return this; + } + + public Product SetImageName([CanBeNull] string? imageName) + { + if (imageName == null) + { + return this; + } + + if (imageName.Length >= ProductConsts.MaxImageNameLength) + { + throw new ArgumentException($"Product image name can not be longer than {ProductConsts.MaxImageNameLength}"); + } + + ImageName = imageName; + return this; + } + + public Product SetPrice(float price) + { + if (price < 0.0f) + { + throw new ArgumentException($"{nameof(price)} can not be less than 0.0!"); + } + + Price = price; + return this; + } + + public Product SetStockCount(int stockCount) + { + return SetStockCountInternal(stockCount); + } + + private Product SetStockCountInternal(int stockCount, bool triggerEvent = true) + { + if (StockCount < 0) + { + throw new ArgumentException($"{nameof(stockCount)} can not be less than 0!"); + } + + if (StockCount == stockCount) + { + return this; + } + + if (triggerEvent) + { + AddDistributedEvent( + new ProductStockCountChangedEto( + Id, + StockCount, + stockCount + ) + ); + } + + StockCount = stockCount; + return this; + } } diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/ProductCodeAlreadyExistsException.cs b/templates/ms/modules/product/src/ProductManagement.Domain/ProductCodeAlreadyExistsException.cs new file mode 100644 index 0000000..68c6e55 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/ProductCodeAlreadyExistsException.cs @@ -0,0 +1,12 @@ +using Volo.Abp; + +namespace ProductManagement; + +public class ProductCodeAlreadyExistsException : BusinessException +{ + public ProductCodeAlreadyExistsException(string productCode) + : base("PM:000001", $"A product with code {productCode} has already exists!") + { + + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj b/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj index 42c1096..a6acaf2 100644 --- a/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj +++ b/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj @@ -1,5 +1,5 @@ - net8.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagementConsts.cs b/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagementConsts.cs new file mode 100644 index 0000000..f2876ab --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/ProductManagementConsts.cs @@ -0,0 +1,8 @@ +namespace ProductManagement; + +public static class ProductManagementConsts +{ + public const string DefaultDbTablePrefix = "Pm"; + + public const string? DefaultDbSchema = null; +} diff --git a/templates/ms/modules/product/src/ProductManagement.Domain/ProductManager.cs b/templates/ms/modules/product/src/ProductManagement.Domain/ProductManager.cs new file mode 100644 index 0000000..a9a0bd2 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Domain/ProductManager.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Domain.Services; + +namespace ProductManagement; + +public class ProductManager : DomainService +{ + private readonly IRepository _productRepository; + + public ProductManager(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task CreateAsync( + [NotNull] string code, + [NotNull] string name, + float price = 0.0f, + int stockCount = 0, + string? imageName = null) + { + var existingProduct = await _productRepository.FirstOrDefaultAsync(p => p.Code == code); + if (existingProduct != null) + { + throw new ProductCodeAlreadyExistsException(code); + } + + return await _productRepository.InsertAsync( + new Product( + GuidGenerator.Create(), + code, + name, + price, + stockCount, + imageName + ) + ); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/IProductManagementDbContext.cs b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/IProductManagementDbContext.cs new file mode 100644 index 0000000..5b0d506 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/IProductManagementDbContext.cs @@ -0,0 +1,11 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace ProductManagement.EntityFrameworkCore; + +[ConnectionStringName("ProductManagement")] +public interface IProductManagementDbContext : IEfCoreDbContext +{ + DbSet Products { get; } +} diff --git a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj index 882cba9..e3e491c 100644 --- a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj +++ b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagement.EntityFrameworkCore.csproj @@ -1,5 +1,5 @@ - net8.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContext.cs b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContext.cs index 09b7362..9262aa0 100644 --- a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContext.cs +++ b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContext.cs @@ -1,9 +1,10 @@ using Microsoft.EntityFrameworkCore; +using ProductManagement.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; namespace ProductManagement.EntityFrameworkCore; -public class ProductManagementDbContext : AbpDbContext +public class ProductManagementDbContext : AbpDbContext, IProductManagementDbContext { public DbSet Products { get; set; } @@ -13,10 +14,6 @@ public class ProductManagementDbContext : AbpDbContext(b => - { - b.ToTable("PmProducts"); - b.Property(x => x.Name).IsRequired().HasMaxLength(128); - }); + builder.ConfigureProductManagement(); } } diff --git a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContextModelCreatingExtensions.cs b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContextModelCreatingExtensions.cs new file mode 100644 index 0000000..5198c6f --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementDbContextModelCreatingExtensions.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace ProductManagement.EntityFrameworkCore; + +public static class ProductManagementDbContextModelCreatingExtensions +{ + public static void ConfigureProductManagement( + this ModelBuilder builder, + Action? optionsAction = null) + { + Check.NotNull(builder, nameof(builder)); + + var options = new ProductManagementModelBuilderConfigurationOptions(); + + optionsAction?.Invoke(options); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "Products", options.Schema); + + b.ConfigureConcurrencyStamp(); + b.ConfigureExtraProperties(); + b.ConfigureAudited(); + + b.Property(x => x.Code).IsRequired().HasMaxLength(ProductConsts.MaxCodeLength); + b.Property(x => x.Name).IsRequired().HasMaxLength(ProductConsts.MaxNameLength); + b.Property(x => x.ImageName).HasMaxLength(ProductConsts.MaxImageNameLength); + + b.HasIndex(q => q.Code); + b.HasIndex(q => q.Name); + }); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementModelBuilderConfigurationOptions.cs b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementModelBuilderConfigurationOptions.cs new file mode 100644 index 0000000..c610ed1 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.EntityFrameworkCore/ProductManagementModelBuilderConfigurationOptions.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace ProductManagement.EntityFrameworkCore; + +public class ProductManagementModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions +{ + public ProductManagementModelBuilderConfigurationOptions( + [NotNull] string tablePrefix = ProductManagementConsts.DefaultDbTablePrefix, + [CanBeNull] string? schema = ProductManagementConsts.DefaultDbSchema) + : base(tablePrefix, schema) + { + + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj b/templates/ms/modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj index 8b1194b..9f5ce79 100644 --- a/templates/ms/modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj +++ b/templates/ms/modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj @@ -1,5 +1,5 @@ - net8.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj b/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj index 507f48e..43222f2 100644 --- a/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj +++ b/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj @@ -1,5 +1,5 @@ - net8.0 + net10.0 diff --git a/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagementHttpApiModule.cs b/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagementHttpApiModule.cs index 07c1060..6eeb49a 100644 --- a/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagementHttpApiModule.cs +++ b/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductManagementHttpApiModule.cs @@ -1,6 +1,10 @@ +using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; namespace ProductManagement; -[DependsOn(typeof(ProductManagementApplicationContractsModule))] +[DependsOn( + typeof(ProductManagementApplicationContractsModule), + typeof(AbpAspNetCoreMvcModule) +)] public class ProductManagementHttpApiModule : AbpModule { } diff --git a/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductsController.cs b/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductsController.cs new file mode 100644 index 0000000..65c1375 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.HttpApi/ProductsController.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace ProductManagement; + +[RemoteService] +[Area("productManagement")] +[Route("api/productManagement/products")] +public class ProductsController : AbpController, IProductAppService +{ + private readonly IProductAppService _productAppService; + + public ProductsController(IProductAppService productAppService) + { + _productAppService = productAppService; + } + + [HttpGet] + [Route("")] + public Task> GetListPagedAsync(PagedAndSortedResultRequestDto input) + { + return _productAppService.GetListPagedAsync(input); + } + + [HttpGet] + [Route("all")] + public Task> GetListAsync() + { + return _productAppService.GetListAsync(); + } + + [HttpGet] + [Route("{id}")] + public Task GetAsync(Guid id) + { + return _productAppService.GetAsync(id); + } + + [HttpPost] + public Task CreateAsync(CreateProductDto input) + { + return _productAppService.CreateAsync(input); + } + + [HttpPut] + [Route("{id}")] + public Task UpdateAsync(Guid id, UpdateProductDto input) + { + return _productAppService.UpdateAsync(id, input); + } + + [HttpDelete] + [Route("{id}")] + public Task DeleteAsync(Guid id) + { + return _productAppService.DeleteAsync(id); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.HttpApi/PublicProductsController.cs b/templates/ms/modules/product/src/ProductManagement.HttpApi/PublicProductsController.cs new file mode 100644 index 0000000..0773ca5 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.HttpApi/PublicProductsController.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace ProductManagement; + +[RemoteService] +[Area("productManagement")] +[Route("api/productManagement/public/products")] +public class PublicProductsController : AbpController, IPublicProductAppService +{ + private readonly IPublicProductAppService _publicProductAppService; + + public PublicProductsController(IPublicProductAppService publicProductAppService) + { + _publicProductAppService = publicProductAppService; + } + + [HttpGet] + public Task> GetListAsync() + { + return _publicProductAppService.GetListAsync(); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json new file mode 100644 index 0000000..6c5fdde --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json @@ -0,0 +1,16 @@ +{ + "culture": "cs", + "texts": { + "Menu:ProductManagement": "Správa produktů", + "Menu:Products": "Produkty", + "ProductManagement": "Správa produktů", + "CreateANewProduct": "Vytvořit nový produkt", + "Products": "Produkty", + "StockCount": "Skladem", + "Code": "Kód", + "Name": "Název", + "Price": "Cena", + "ImageName": "Název obrázku", + "ProductDeletionWarningMessage": "Opravdu chcete smazat tento produkt?" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json new file mode 100644 index 0000000..0b63f9b --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json @@ -0,0 +1,16 @@ +{ + "culture": "en", + "texts": { + "Menu:ProductManagement": "Product Management", + "Menu:Products": "Products", + "ProductManagement": "Product Management", + "CreateANewProduct": "Create A New Product", + "Products": "Products", + "StockCount": "Stock Count", + "Code": "Code", + "Name": "Name", + "Price": "Price", + "ImageName": "Image Name", + "ProductDeletionWarningMessage": "Are you sure you want to delete this product?" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl-PL.json b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl-PL.json new file mode 100644 index 0000000..ae12f23 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl-PL.json @@ -0,0 +1,16 @@ +{ + "culture": "pl-PL", + "texts": { + "Menu:ProductManagement": "Zarządzanie produktami", + "Menu:Products": "Produkty", + "ProductManagement": "Zarządzanie produktami", + "CreateANewProduct": "Utwórz nowy produkt", + "Products": "Produkty", + "StockCount": "Ilość na magazynie", + "Code": "Kod", + "Name": "Nazwa", + "Price": "Cena", + "ImageName": "Nazwa obrazka", + "ProductDeletionWarningMessage": "Czy jesteś pewien, że chcesz usunąć ten produkt?" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/tr.json b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/tr.json new file mode 100644 index 0000000..f3c3548 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/tr.json @@ -0,0 +1,16 @@ +{ + "culture": "tr", + "texts": { + "Menu:ProductManagement": "Ürün Yönetimi", + "Menu:Products": "Ürünler", + "ProductManagement": "Ürün Yönetimi", + "CreateANewProduct": "Yeni Bir Ürün Oluştur", + "Products": "Ürünler", + "StockCount": "Stok Sayısı", + "Code": "Kod", + "Name": "İsim", + "Price": "Fiyat", + "ImageName": "Fotoğraf İsmi", + "ProductDeletionWarningMessage": "Bu ürünü silmek istediğinize emin misiniz?" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json new file mode 100644 index 0000000..6b51506 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json @@ -0,0 +1,16 @@ +{ + "culture": "vi", + "texts": { + "Menu:ProductManagement": "Quản lý sản phẩm", + "Menu:Products": "Sản phẩm", + "ProductManagement": "Quản lý sản phẩm", + "CreateANewProduct": "Tạo một sản phẩm mới", + "Products": "Sản phẩm", + "StockCount": "Số chứng khoán", + "Code": "Mã", + "Name": "Tên", + "Price": "Giá", + "ImageName": "Tên ảnh", + "ProductDeletionWarningMessage": "Bạn có chắc chắn muốn xóa sản phẩm này?" + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml new file mode 100644 index 0000000..da038e5 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml @@ -0,0 +1,20 @@ +@page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Microsoft.AspNetCore.Mvc.Localization +@using ProductManagement.Localization +@model ProductManagement.Pages.ProductManagement.Products.CreateModel +@inject IHtmlLocalizer L +@{ + Layout = null; +} + + + + + + + + + + + diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml.cs b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml.cs new file mode 100644 index 0000000..19f3a35 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Create.cshtml.cs @@ -0,0 +1,46 @@ +using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace ProductManagement.Pages.ProductManagement.Products; + +public class CreateModel : AbpPageModel +{ + private readonly IProductAppService _productAppService; + + [BindProperty] + public ProductCreateViewModel Product { get; set; } = new ProductCreateViewModel(); + + public CreateModel(IProductAppService productAppService) + { + _productAppService = productAppService; + } + + public async Task OnPostAsync() + { + var createProductDto = ObjectMapper.Map(Product); + + await _productAppService.CreateAsync(createProductDto); + + return NoContent(); + } + + public class ProductCreateViewModel + { + [Required] + [StringLength(ProductConsts.MaxCodeLength)] + public string Code { get; set; } = string.Empty; + + [Required] + [StringLength(ProductConsts.MaxNameLength)] + public string Name { get; set; } = string.Empty; + + [StringLength(ProductConsts.MaxImageNameLength)] + public string? ImageName { get; set; } + + public float Price { get; set; } + + public int StockCount { get; set; } + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml new file mode 100644 index 0000000..4bc9f65 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml @@ -0,0 +1,20 @@ +@page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Microsoft.AspNetCore.Mvc.Localization +@using ProductManagement.Localization +@model ProductManagement.Pages.ProductManagement.Products.EditModel +@inject IHtmlLocalizer L +@{ + Layout = null; +} + + + + + + + + + + + diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml.cs b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml.cs new file mode 100644 index 0000000..b364a5b --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Edit.cshtml.cs @@ -0,0 +1,55 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace ProductManagement.Pages.ProductManagement.Products; + +public class EditModel : AbpPageModel +{ + private readonly IProductAppService _productAppService; + + [BindProperty] + public ProductEditViewModel Product { get; set; } = new ProductEditViewModel(); + + public EditModel(IProductAppService productAppService) + { + _productAppService = productAppService; + } + + public async Task OnGetAsync(Guid productId) + { + var productDto = await _productAppService.GetAsync(productId); + Product = ObjectMapper.Map(productDto); + return Page(); + } + + public async Task OnPostAsync() + { + await _productAppService.UpdateAsync(Product.Id, new UpdateProductDto() + { + Name = Product.Name, + Price = Product.Price, + StockCount = Product.StockCount + }); + } + + public class ProductEditViewModel + { + [HiddenInput] + [Required] + public Guid Id { get; set; } + + [Required] + [StringLength(ProductConsts.MaxNameLength)] + public string Name { get; set; } = string.Empty; + + [StringLength(ProductConsts.MaxImageNameLength)] + public string? ImageName { get; set; } + + public float Price { get; set; } + + public int StockCount { get; set; } + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml new file mode 100644 index 0000000..4827eb4 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml @@ -0,0 +1,47 @@ +@page +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Mvc.Localization +@using ProductManagement +@using ProductManagement.Localization +@model ProductManagement.Pages.ProductManagement.Products.IndexModel +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@inject IThemeManager ThemeManager +@inject IAuthorizationService Authorization +@inject IHtmlLocalizer L +@{ + ViewBag.PageTitle = "Products"; + Layout = ThemeManager.CurrentTheme.GetApplicationLayout(); +} + +@section scripts { + +} + + + + + +

    @L["Products"]

    +
    + + @if (await Authorization.IsGrantedAsync(ProductManagementPermissions.Products.Create)) + { + + } + +
    +
    + + + + + @L["Actions"] + @L["Code"] + @L["Name"] + @L["Price"] + @L["StockCount"] + + + + +
    diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml.cs b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml.cs new file mode 100644 index 0000000..0a5c157 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/Index.cshtml.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace ProductManagement.Pages.ProductManagement.Products; + +public class IndexModel : AbpPageModel +{ + public async Task OnGetAsync() + { + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/index.js b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/index.js new file mode 100644 index 0000000..dfcec4a --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/Products/index.js @@ -0,0 +1,76 @@ +$(function () { + + var l = abp.localization.getResource('ProductManagement'); + var _createModal = new abp.ModalManager(abp.appPath + 'ProductManagement/Products/Create'); + var _editModal = new abp.ModalManager(abp.appPath + 'ProductManagement/Products/Edit'); + + var _dataTable = $('#ProductsTable').DataTable(abp.libs.datatables.normalizeConfiguration({ + processing: true, + serverSide: true, + paging: true, + searching: false, + autoWidth: false, + scrollCollapse: true, + order: [[1, "desc"]], + ajax: abp.libs.datatables.createAjax(productManagement.products.getListPaged), + columnDefs: [ + { + rowAction: { + items: + [ + { + text: l('Edit'), + visible: abp.auth.isGranted('ProductManagement.Product.Update'), + action: function (data) { + _editModal.open({ + productId: data.record.id + }); + } + }, + { + text: l('Delete'), + visible: abp.auth.isGranted('ProductManagement.Product.Delete'), + confirmMessage: function (data) { return l('ProductDeletionWarningMessage'); }, + action: function (data) { + productManagement.products + .delete(data.record.id) + .then(function () { + _dataTable.ajax.reload(); + }); + } + } + ] + } + }, + { + target: 1, + data: "code" + }, + { + target: 2, + data: "name" + }, + { + target: 3, + data: "price" + }, + { + target: 4, + data: "stockCount" + } + ] + })); + + $("#CreateNewProductButtonId").click(function () { + _createModal.open(); + }); + + _createModal.onClose(function () { + _dataTable.ajax.reload(); + }); + + _editModal.onResult(function () { + _dataTable.ajax.reload(); + }); + +}); diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/_ViewImports.cshtml b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/_ViewImports.cshtml new file mode 100644 index 0000000..231948b --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Pages/ProductManagement/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling diff --git a/templates/ms/modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj index e459720..7514e24 100644 --- a/templates/ms/modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj +++ b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Library diff --git a/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementMenuContributor.cs b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementMenuContributor.cs new file mode 100644 index 0000000..3dc9de9 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementMenuContributor.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using ProductManagement.Localization; +using Volo.Abp.UI.Navigation; + +namespace ProductManagement; + +public class ProductManagementMenuContributor : IMenuContributor +{ + public async Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name == StandardMenus.Main) + { + await ConfigureMainMenu(context); + } + } + + private async Task ConfigureMainMenu(MenuConfigurationContext context) + { + var l = context.GetLocalizer(); + + var rootMenuItem = new ApplicationMenuItem("ProductManagement", l["Menu:ProductManagement"]); + + if (await context.IsGrantedAsync(ProductManagementPermissions.Products.Default)) + { + rootMenuItem.AddItem(new ApplicationMenuItem("Products", l["Menu:Products"], "/ProductManagement/Products")); + } + + context.Menu.AddItem(rootMenuItem); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebAutoMapperProfile.cs b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebAutoMapperProfile.cs new file mode 100644 index 0000000..e7e58d1 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; +using ProductManagement.Pages.ProductManagement.Products; + +namespace ProductManagement; + +public class ProductManagementWebAutoMapperProfile : Profile +{ + public ProductManagementWebAutoMapperProfile() + { + CreateMap(); + CreateMap(); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebModule.cs b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebModule.cs index 4e39dbc..ea25cc8 100644 --- a/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebModule.cs +++ b/templates/ms/modules/product/src/ProductManagement.Web/ProductManagementWebModule.cs @@ -1,6 +1,59 @@ +using Localization.Resources.AbpUi; +using Microsoft.Extensions.DependencyInjection; +using ProductManagement.Localization; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AutoMapper; +using Volo.Abp.Localization; using Volo.Abp.Modularity; +using Volo.Abp.UI.Navigation; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; namespace ProductManagement; -[DependsOn(typeof(ProductManagementHttpApiModule))] -public class ProductManagementWebModule : AbpModule { } +[DependsOn( + typeof(ProductManagementHttpApiModule), + typeof(AbpAspNetCoreMvcUiThemeSharedModule), + typeof(AbpAutoMapperModule) +)] +public class ProductManagementWebModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.PreConfigure(options => + { + options.AddAssemblyResource(typeof(ProductManagementResource), typeof(ProductManagementWebModule).Assembly); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.MenuContributors.Add(new ProductManagementMenuContributor()); + }); + + Configure(options => + { + options.FileSets.AddEmbedded("ProductManagement"); + }); + + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpValidationResource), + typeof(AbpUiResource) + ).AddVirtualJson("/Localization/Resources/ProductManagement"); + }); + + Configure(options => + { + options.AddProfile(validate: true); + }); + } +} diff --git a/templates/ms/modules/product/src/ProductManagement.Web/Properties/launchSettings.json b/templates/ms/modules/product/src/ProductManagement.Web/Properties/launchSettings.json new file mode 100644 index 0000000..2dea481 --- /dev/null +++ b/templates/ms/modules/product/src/ProductManagement.Web/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44301", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "ProductManagement.Web": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44301", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement.Application.Tests.csproj b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement.Application.Tests.csproj new file mode 100644 index 0000000..623a2ed --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement.Application.Tests.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + + + + + + + + + + + + + diff --git a/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductAppService_Tests.cs b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductAppService_Tests.cs new file mode 100644 index 0000000..38ee7ee --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductAppService_Tests.cs @@ -0,0 +1,99 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Repositories; +using Xunit; + +namespace ProductManagement +{ + public class ProductAppService_Tests : ProductManagementApplicationTestBase + { + private readonly IProductAppService _productAppService; + private readonly IRepository _productRepository; + private readonly ProductManagementTestData _testData; + + public ProductAppService_Tests() + { + _productAppService = GetRequiredService(); + _productRepository = GetRequiredService>(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetListPagedAsync() + { + var result = await _productAppService.GetListPagedAsync(new PagedAndSortedResultRequestDto()); + + result.Items.Count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task GetListAsync() + { + var result = await _productAppService.GetListAsync(); + + result.Items.Count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task GetAsync() + { + var product = (await _productRepository.GetListAsync()).FirstOrDefault(); + + var result = await _productAppService.GetAsync(product.Id); + + result.ShouldNotBeNull(); + result.Name.ShouldBe(_testData.ProductName1); + result.Code.ShouldBe(_testData.ProductCode1); + result.Price.ShouldBe(_testData.ProductPrice1); + result.StockCount.ShouldBe(_testData.ProductStockCount1); + } + + [Fact] + public async Task CreateAsync() + { + var result = await _productAppService.CreateAsync(new CreateProductDto() + { + Code = "Code", + Name = "Name", + Price = 15, + StockCount = 14 + }); + + result.ShouldNotBeNull(); + } + + [Fact] + public async Task UpdateAsync() + { + var product = (await _productRepository.GetListAsync()).FirstOrDefault(); + + var result = await _productAppService.UpdateAsync(product.Id, new UpdateProductDto() + { + Name = nameof(Product.Name), + Price = 15, + StockCount = 14 + }); + + result.ShouldNotBeNull(); + result.Name.ShouldBe(nameof(Product.Name)); + result.Price.ShouldBe(15); + result.StockCount.ShouldBe(14); + } + + [Fact] + public async Task DeleteAsync() + { + var product = (await _productRepository.GetListAsync()).LastOrDefault(); + + await _productAppService.DeleteAsync(product.Id); + + var result = await _productRepository.FindAsync(product.Id); + + result.ShouldBeNull(); + } + + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestBase.cs b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestBase.cs new file mode 100644 index 0000000..0c03433 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestBase.cs @@ -0,0 +1,24 @@ +using System; +using ProductManagement.EntityFrameworkCore; + +namespace ProductManagement +{ + public abstract class ProductManagementApplicationTestBase : ProductManagementTestBase + { + protected virtual void UsingDbContext(Action action) + { + using (var dbContext = GetRequiredService()) + { + action.Invoke(dbContext); + } + } + + protected virtual T UsingDbContext(Func action) + { + using (var dbContext = GetRequiredService()) + { + return action.Invoke(dbContext); + } + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestModule.cs b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestModule.cs new file mode 100644 index 0000000..a9a27bb --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Application.Tests/ProductManagement/ProductManagementApplicationTestModule.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace ProductManagement +{ + [DependsOn( + typeof(ProductManagementApplicationModule), + typeof(ProductManagementDomainTestModule) + )] + public class ProductManagementApplicationTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAlwaysAllowAuthorization(); + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement.Domain.Tests.csproj b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement.Domain.Tests.csproj new file mode 100644 index 0000000..fddd960 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement.Domain.Tests.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + + + + + + + + + diff --git a/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestBase.cs b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestBase.cs new file mode 100644 index 0000000..e949c76 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestBase.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Uow; + +namespace ProductManagement +{ + public abstract class ProductManagementDomainTestBase : ProductManagementTestBase + { + #region WithUnitOfWork + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } + + #endregion + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestModule.cs b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestModule.cs new file mode 100644 index 0000000..d14fb49 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManagementDomainTestModule.cs @@ -0,0 +1,13 @@ +using ProductManagement.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace ProductManagement +{ + [DependsOn( + typeof(ProductManagementEntityFrameworkCoreTestModule) + )] + public class ProductManagementDomainTestModule : AbpModule + { + + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManager_Tests.cs b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManager_Tests.cs new file mode 100644 index 0000000..b59eb9c --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.Domain.Tests/ProductManagement/ProductManager_Tests.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace ProductManagement +{ + public class ProductManager_Tests : ProductManagementDomainTestBase + { + private readonly ProductManager _productManager; + + public ProductManager_Tests() + { + _productManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Create_A_Valid_Product() + { + //Act + var product = await WithUnitOfWorkAsync( + async () => + { + return await _productManager.CreateAsync("P000837212", "My Product 837212", stockCount: 42); + } + ); + + //Assert + product.Code.ShouldBe("P000837212"); + product.Name.ShouldBe("My Product 837212"); + product.Price.ShouldBe(0.0f); + product.StockCount.ShouldBe(42); + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement.EntityFrameworkCore.Tests.csproj b/templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..3886598 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,16 @@ + + + + net10.0 + + + + + + + + + + + + diff --git a/templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement/EntityFrameworkCore/ProductManagementEntityFrameworkCoreTestModule.cs b/templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement/EntityFrameworkCore/ProductManagementEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..7730478 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.EntityFrameworkCore.Tests/ProductManagement/EntityFrameworkCore/ProductManagementEntityFrameworkCoreTestModule.cs @@ -0,0 +1,43 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.Modularity; + +namespace ProductManagement.EntityFrameworkCore +{ + [DependsOn( + typeof(ProductManagementTestBaseModule), + typeof(ProductManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] + public class ProductManagementEntityFrameworkCoreTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var sqliteConnection = CreateDatabaseAndGetConnection(); + + Configure(options => + { + options.Configure(abpDbContextConfigurationContext => + { + abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection); + }); + }); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + + new ProductManagementDbContext( + new DbContextOptionsBuilder().UseSqlite(connection).Options + ).GetService().CreateTables(); + + return connection; + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement.TestBase.csproj b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement.TestBase.csproj new file mode 100644 index 0000000..9b9d145 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement.TestBase.csproj @@ -0,0 +1,24 @@ + + + + net10.0 + + + + + + + + + + + + + + + + + + + + diff --git a/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBase.cs b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBase.cs new file mode 100644 index 0000000..fb976ca --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBase.cs @@ -0,0 +1,15 @@ +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Testing; + +namespace ProductManagement +{ + public abstract class ProductManagementTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBaseModule.cs b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBaseModule.cs new file mode 100644 index 0000000..169acad --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestBaseModule.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; + +namespace ProductManagement +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(ProductManagementDomainModule) + )] + public class ProductManagementTestBaseModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAlwaysAllowAuthorization(); + + Configure(options => + { + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + scope.ServiceProvider + .GetRequiredService() + .Build(); + } + } + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestData.cs b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestData.cs new file mode 100644 index 0000000..f0de5ec --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestData.cs @@ -0,0 +1,23 @@ +using Volo.Abp.DependencyInjection; + +namespace ProductManagement +{ + public class ProductManagementTestData : ISingletonDependency + { + public string ProductCode1 { get; } = "ProductCode1"; + + public string ProductName1 { get; } = "ProductName1"; + + public float ProductPrice1 { get; } = 20; + + public int ProductStockCount1 { get; } = 100; + + public string ProductCode2 { get; } = "ProductCode2"; + + public string ProductName2 { get; } = "ProductName2"; + + public float ProductPrice2 { get; } = 30; + + public int ProductStockCount2 { get; } = 110; + } +} diff --git a/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestDataBuilder.cs b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestDataBuilder.cs new file mode 100644 index 0000000..71f04e1 --- /dev/null +++ b/templates/ms/modules/product/test/ProductManagement.TestBase/ProductManagement/ProductManagementTestDataBuilder.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; +using Volo.Abp.Uow; + +namespace ProductManagement +{ + public class ProductManagementTestDataBuilder : ITransientDependency + { + private ProductManagementTestData _testData; + private readonly ProductManager _productManager; + + public ProductManagementTestDataBuilder( + ProductManagementTestData testData, + ProductManager productManager) + { + _testData = testData; + _productManager = productManager; + } + + public void Build() + { + AsyncHelper.RunSync(BuildAsync); + } + + [UnitOfWork] + public virtual async Task BuildAsync() + { + await _productManager.CreateAsync(_testData.ProductCode1, _testData.ProductName1, _testData.ProductPrice1, _testData.ProductStockCount1); + await _productManager.CreateAsync(_testData.ProductCode2, _testData.ProductName2, _testData.ProductPrice2, _testData.ProductStockCount2); + } + } +} diff --git a/templates/ms/shared/Company.Project.Shared/Company.Project.Shared.csproj b/templates/ms/shared/Company.Project.Shared/Company.Project.Shared.csproj index 95e3d2c..6135b36 100644 --- a/templates/ms/shared/Company.Project.Shared/Company.Project.Shared.csproj +++ b/templates/ms/shared/Company.Project.Shared/Company.Project.Shared.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 Company.Project.Shared diff --git a/test/Hua.Cli.Tests/Hua.Cli.Tests.csproj b/test/Hua.Cli.Tests/Hua.Cli.Tests.csproj index 9f63164..bd2b7a6 100644 --- a/test/Hua.Cli.Tests/Hua.Cli.Tests.csproj +++ b/test/Hua.Cli.Tests/Hua.Cli.Tests.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable false

    =|uTTJGY!sKidOy8X?Rkm+}!R; zA^UYZGmI3_Na@6_P2=16V|Q6F8u_Q>oCe1DVlA##FWD((MG98UK028k9*~wiR`T%5 znY4SEXXp>VvPyun+{VH(jp|$6HI?vj^)`vjQ(13fuXn+WIhii^Ze94CaW4abx}%l3 zv%{-R_gx{nx9;QQa#aR4px4t)B8rnMKFlPp#oOo0Z0zGm|Ib&TE(rX!sl@SOuEfB; zIv$*}mtWEKTK6|;{awK*;GF)_7WF|5W-Nz$7h6(j-kTab)IV%K7x>7w)37D{ zRl~Vjg#Vf9hJN0Azj__xb?eYOjCcQf^VI8hw*A;HfP0x|>=@x?4(=;I<~6qk^RrAc zI~~J+6tLwf9O^Oo^1`cNp?2Ctz^DmtCF`~{n5b+XuRkK7Zp|SaD-*yxwt`}Rms{S< z_QUMX>+S`bM)W{rPNsbh&hFcEZRUB2(Rbo!I&0o+xFo2X_0L)*+9sppF^Od%Ga4lU zkj(kM1}*nuulWUO-L}6@OLX^YWzXS+1Do*lhMg%IL-B|X(^ITr6tm#g&B|NcAma1T zuhpcF4OUW6f;%R~6>f4RJfEnB$WFv(hovN~Nu@a&q8y+~AB>6)fC3 z=tdXNe`7YMW(+18r;f`OT(q#OeBEvbzo(J_?VM3fNznQ$mGBisIL9WHP?JF4t}Yj% zhj6>?+YA6?ezPel_J--k#TOdI%+wCN?67GT(_=5pGQph>S>4LUr54%0mPRW+jE}&>95?g_(=ZB z+q^&Bti*Eadp<(w=v~LR)pG+ak7XuH&2OwGx^jB>n=shfpPOwMDQfIl&2RSC&bBt_ zvy71L%;FQ|YvJ2*UgeC-gtCfrST1S0id?%VRk>MFj)WgQw>(!lMIQO=5F*DZSZ30mu3F*^=!*PncQ+i~>y zBe3|0SA6mCFKx@tu?!wd0er1->u!XuooKwb_ZTwBOy~e~bWACdeS!z^P1&mGgNP`y zIS~H=YVgFp&A%yYog>2#doeD-HWW)$3qzlZZ50xU;xYV|ygh+-K)o-Yl5h;LWLwJ@ zsGT#0I(5TygtvfdkyBMS6^uL%Y_Y_yj@yYiyuRLUAd+5{so;o?IF(ZT7s6HuYVY1} zzuD|epStKJ5gAFR@K_~EYei-fU*Yz>t23$${tngBi4>Qyyz>}!`MuV;_<`e|fq~x1 z*xaq4D_^E?_?49P`!`3JCgXgH%pb=Ma8AZ4y?q)cX-?}S*}wgM>#TIIQqwt~n@qeC z14bB>Rx@5r@4=3sd}vlw=m^w3dxc|7Rm+2Lc63c4TLj8DXAadGPbRb|)_ps((>!7# zqVrs@@d>(g`-`1Ow!k3FKxFnJMtVyZoifI}UN-j?GwyUuiO$mfx}&AGR%@6?++vg0 zl=*YdVb>KH!NO^S!Z6{0C;@}0Wf{}87L*SgaOe)T6ivg{A?BRW9)yo$`Ii`$GiNVO z!rWZoacPMfFrUSsvce!s1Dp3gERUoeBAm6nzStw0Sx<0ughlY-HN+$v)^eJneXPVz zMYg>!xD$9H>ybfRBu5c0>1Lzk&a&&Zz1-6@3X6BYTebB26mT0icye!jc3v5tSHVks zn0h+WhIROX>~Rpx7Ie#}+WchAn43N`aJ?fSnmu#8r?}6beUpRljf%Y(B69mK zXo~603zL=)aS83w{_RHXUmW9fl%yi0s}l$j@bR%1@rPY53QcXFTX=5K1xFiXZ5FRt z*KLtCUbrFCeBRmTi7iey@oGeFy~vE?U`5|omy$UaeCIB337O2M#9WDx6;3zY{#v%f z^JS21s@J)+QZhE;E%&vCIhVf1)2VCU20ttxiS1|vcy1S%_w;F2?YOdl zKk=x)2PHd^p@eYodCfKGw|p+9t7y7^(8bGSHRpS*1fmITYLr_oP&x&Jw`&fRONb`) zHIA@UVup=P*NP}L~a?+N2bNm;Kc`Mw~3_rm4CUYVp>}%9kE9bot_IZOWbB;UF z>G5~HRg>F?va;h^F^-NxvHpSTjy}B8qLLX5SRHr*!Z2=x_QK@n=3Y-*cWZmImBeO@ z=d3{4$JzYoHHy;WS*VBD$8kkQ_qbtO#lPmh$@wKV5@dNECZ?_S1y521KT?Xd-x>7g z;2hu~Ev3-pwM*-1!}C2Oq4>%jMBXMlnpg5#)Ooa{U*o|_L`|2!t?RA4`fMd9#j!^> zBMn`bqUqdUaSw-L^WR;gj=bKm!K|PD&PpieNPqmL4_TbS41Pk}4T@tUwhR7@>qSxTrYAYEo7JZRjlIJ#+7$x7@r zjntxR^aqD+50!D(x_FzcAEqZXCh>v|RVAGfqj_Cn^Sc1Qfr-YObQjaHJF}W1tpUeT zL)6hM^)o-xuq-2qrsbD1YrO4BHU-gKh5r3UAC}(tHhtm}oLoVy6y^@rb88EIw;KMe zS%1G}f9WVa;^X&tnn}>o#MJw6wbegqqLGL9VPoPSuIhw^fbp18G5P5B^ z@y)Z1@c~A1QhtLlmv3hbV2SA2#&ZEL&P86uq8L2&%mUptb?a;L2|rfSOpDtGL?g_a zF&gbZE*?bRe_NS3_0%$7Bwb72r9)f&-lVyrfPVi~tbuUEC?@>tr;TX>fm|6pors6^ zPXZ5f@I?PNn3Ec?2g`vd8A#NG3#CM;U0!=pbQ! z>Y{W2u#TfOzzXOGSknn(z!UyT6CTfCBV(eARXsR4rVSNRD*gzpXJ{nYI$`05aC8oi zVNFWKYej{x?2mHVvb?S-?ZZ;BY}dk+A0F(=Vt8$9+J-e$#MQ_LRL~o)Y4f0@WhWT_omw_~34wGVZvn_R`HX!>EPxVCF8sDJOYSo=hG)_0~6^H2HTsjm)ig`iEljxRL<0Z8Q1|fU?Z@PeXZwf*FtRgYRTSEE|OCK@k04pn4Kh=|ACiQkn)Y>G4PKtD$|28wd&(JE^Yd zP6Sl<1pm)ifiK8vAJ|tW;`)0vezgEHCmlt^camtoGWHa##tVu^>4HWx(@t+HDyu`l z?EeCz{ z%n)mQ^5=&EzYy)c%Q0u8$HDQ7I`X}gdFV359NoWp|IG@F?SFdlM=B8u-y;Z9VsIY# zB||cJE)vK!h&U|>yMWL(5q3#@*l@7i*f;WYvAl17)YfOd>#3Wc?D>Z*;8goD2rftQ zJE!{U3%2`4i2u3R-TxQA=TLjTp_^cfI#{taS4e sgK|cG5;_pn4Ffo8Dz*u?-VtBGPgMQ`t^PBe_m2cJ5MJIVp54#?1s7~FV*mgE literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/oki.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/oki.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6fefeec6e312d8baf88ca0a51217e42f36a2b39e GIT binary patch literal 15514 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 literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/playstation.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/playstation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..880832401aa9153eb759d338f4d9bbf51dc601dd GIT binary patch literal 12477 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 F{TBdKa8LjM literal 0 HcmV?d00001 diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/rampage.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/rampage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e49660df170acdceee2a5c4167a09dbdd2baf95b GIT binary patch literal 29142 zcmbTe1yEe!nl{)t!3j=d!QI_SZ~_E(cc*cJLvRZO_u%f*xVyVs;~FHmEqCtB)W2JE z@9ymBs;{d1J9W<6?|J=sy5E-Gwg4Eik}{G2C@25`>iq?HTLpXpz{A49!@UV#YI4b`tZIjg8_hofrf>Jg+_pfgNB8Jdq4es9}^D#6Wd2IB_jkZa!^1VA~yTy z-!00Ys7qNRbMhYR<9B< zEc`80*U`%pP5Q5O`Kb3nYA>)OucL(b-XRrtLN(bwMM<1&5JfbA`-`!_)C zfOVVrn3{8Y!o~FT0Nf3cskcnSE3(`-js3Mzfe?gHwV_2|vJ_@@NBSwQL9hp3=H=%_ zvR0DXc zOVSU{`H|RM<(5rwUyZg_m-QVLNskXVhOQNm-LNVo2)OUIMdr<%JX~Xq&Op62vfqdL zyCU2iy<+;D2}TcSYO*Q zvmMh4`~_R+eBkKP2#zB56@orM|0t*vZ?#EGS&^pX7KnZhc>^darvY^YJksStW&~%y zE>ZA6OZn8j#*MC3dX8mLszb2&5>VaKu0(%6=7Z>GlbkjzFIn)Ja>B19iJw+V?8(DO zUhJv~6X!?>?*;sKmv%}Lqx(QM-%HK$P(_9|^q&grTV|zpHxcU0ofs z9l6ckwqS`)x*8Ei+GA`ZpiJEWvT9o}cX?3|pnNU&9EBxXQ8`)5qTVA#T7;c(jB z*LFMDLhvJ_9DH_oVUK2p4@lr%SERMV6Jim1p{6u8$PtsJSi{1*zV=#{brGdOa#6*D zlqS_G<=7tEnat__MCscaR4le`S(6cz!8&%5yxq@Q!t-|=IeHWMp<#0|MT;GpoQ$0O zf4eZU2pyymHAvC9jD2kSthjz=Z&6$4Q3R2o*3OGZvVtjkq8jH}%=z=cEIXDOiZ!lT zM**#spZJU^hR;ly$p~1>X}=GKaQPaRrqP;u(Pf;hycWFyieDocE`D_#KaUvoJ8LF| zexMZQ_tD{ew~Qy?efd+jAIx@lTa*KjVaCa#682RC)oa2%wJnI@yLwfluCWUi&(wH) z^_TN=VCNWeLSHI)EhQA^p8En517Lr~>=+a9U5L=}%3NpPtT(&C?P+Qv@x1X z@^8{X@SsD}5*vq&E*ztQ>j?oJDN2-H)~>~9!QpVSo7prpmy0`IV_!n^Yo@G2c&ush1p%iX&tbcg{Z1ND&2|mgmpk>K)i5Xy$u>$W z<6>{DOZ6i1NiH~5>N4aK9!$K82Paq9Q?x!WY~u1rh2EV?0;oo=K;wGSF+wW4mO!T5 zQK!4`WhoNO#z?{<(-|N)-5bE=>4^{CIs#Xy%F-FpS)mUY{PBPD@IQ$z+pyqzOB9S^ zf9!@0n1{v9!m4;gKN(iLugbP^O2WQvR8MOPgb|zba@Tc@HcrX19ZVTYWs=wX8pvxD zt1R=B}nfE~5S0g#7mSSpA za@%Uv{Z#&Eel^>SqnicEs#cg}PN8p`s{+~2?>x@;OznxUvCGaV+rMzryk(7svfxSm z7cV8OtlB=87bl0J7f?;KgC&Mv)LdZ+-T*{o-?m-d+$LPiayJen<~5l$x>+s7JIa6hfok`OmP6zMO%kzxamL`KJGClu{Z)|UmgI{8 zG;{?DFiSqlnk9dOFjYmTq07bEcT(c61*DF zFfp-ZKk4oAkY+%Gt^Eo5*rT6ND%#1*_KUbr^ z^q}ef_H`W^oEYUTpI2pSKQb4zgIRhtQLC#ZjpbEm5TNA{q(Q8r2_2(M(f#AIdO2-& zpB<_igXW7Pm~ik0kX6(X3T3;mkb>ZaY&eovW*^TBaC_X?)E{#SuV53?q123HQ3apH z^B^~z@xYQ8k67>MCPHvcE?V*M?Wy+FjqqAaHqHPiz-FM+>b0IxA_oaD&CwF{l`uz9 zo;j0f(Ag%GoS&@y|7&z)G!WSz5iANA*HWVp&kzo|p}&qcP5=uNbJ^KO$Ka^#; z7QBnc!KbwZL@T^&;$J(Gh+ck1;yR6iL#zi4lz37pcKuM4c$AslU@8{n?>}tIu?Hiw zWjIlHvZ~ferjwRd$5wCdHy&)&bmqkd8>jJmucnktE@U6)6ved+%)SBAq-Zdk#7Yly z088{uy;F>snBth2P?#9+i;9N&>{QoLX@RX$jOnW!-Xy^_(nx(gf37+I?>tG6-Jcgc zy8B4T1YOE8DbdFkUf!^&bAGg-TGV9-O*FQLGgVQqzFdQqvtrpxC)Z@kzVpDfkVV{A zYR|+4TTmbb;;CsZ+jfE+H||$X zE_5Pg(x=$N+E(%~t^fE&m>9SfmnQ&wro=)oE%y-2OBls@J1X0;gy@Ry(%pwQ6{f_3}d*1+N=8sE&ZOfl= zryA-$cx)zm+mrJo5Ce&C`v6b21&SLn@Vt;2B~HShkV5WZto}${=2A@fh)bJZkKlUxyf*gAto<48N4|CdT{-?Lt%#Jp48KN*ws&Wc1p9DYK zYj$OZ7+uA#xEeNnDFfO~S-%1D6~hf0E)fhHWfGG3G02zXjOgiT-jEN0-uOLm@pK0(C5Ng^;uS`&2! zPH%hYLL>2O_JOM1_PsKP)qI#4Ep0>r06w^n1qiGdeO^p#1l=LQLl>QTbTJd`gL#%=&n=+w6E z4Uj8IZc@?DdgYQtJtDMX_XgN4=}6*)N>pu-$89Z_9e9oA8u%qJ4X|C#Fmm_(RPahh zcKSm!45>f;!p(%2a|)Mhh7*r{C$oVR$48u0=z1UJxjl{k6VX>A_f&$F!B-7q4}y%& z6UJ~kB_#^Iuo=J5QoLqnAn#MOuZ_YB9s5wgXZR3(J_@azo$EJK(!;K-m66!?&M zaJ-an=8u&Vmy?w4TKx&#zF!>i|E&f1u|!s9zUG$9Y{;dVXwpj&oF9435LDM;STUZO zl-r`uM_uwB)cj=t>F~jgufI~SZ3?b*hng-- z#mEIqT|;)M1Y+g9v13DajnijU-9lh}VrKhI5;@}lXQ+eozFQ@wl&ZHnoEVp6M#nAF zU|7jx6*8}GR}~+G5;tw66i*1%lxjD8S}KTq;grWSClPH9FH8g%)2eO1s2Vq$_dNkO z8=;N5@A}2Y#^!563Xy$%B7!I4Q#p9Cc@@%1!?^d%!?=yH4d!B?Den z^)IIzYV}c7d~T8{vivaiH$dOHz0mNyr9rN`EHr=HrXFdj0=+ev)H=e#<+%%SfF2`U ze8oQ%FM+&_Y;9%?+7AAPUqD)|P$tZjv&!H!uE(A`rB@5KzSaBRQNtYSWn`Kp})u9tILTUuEV zo3*{fqZfDs?3d__&Pl7eEH5(63xuFJqkA4w11hy1|DrV%I3U){xxOeB64)a{Y6w9( zzFCL-uUU<01v#^GUlIXO@AsNzrp6<-kxZLvH4<6jO@oImRbukM%^5j1K%K%6kc=+0k;l zG{18~?@5dUM2!6h;yk#p~f~&$9ji_Ak^dv| zNA`%~@xzi-pznmZ_p{Maj}Va1(UdzjxT>HdlQ~=@I|=#9iHtuq(rzWiqQ+m5${oOW zw+HNdRR~1w6AIG9;P6Iek;~~6thrNO(;@a$qa)MOnVY7(DD}~!#{R;~rOq6mIDf{q zQqhz9@^ysQ!?@5Nw--h+m+dvPL!capHKEuR%Yr)P54D8(f=kO5^#v!T4y`DwR0Bv# zSFp)Zt3%W1ad|N88ntQ+@rUJmT7{wjn;N@}02SDY_?yI#3)`T_Z>bheT z^+4J)dj7B*yvEgr*Lxa=$QzdRn<1Pjyut%rV3J#AleyWJj$RQ;_pcM?Udz0j!$v96 z<$${&9zj&*mXff2!X61`0?kXC`XtB0vd&}KB~f!yI3X0K;FNe#(49=Yty)SQoulpRvMn!m2`kGu|CSZ#m9E^q8)w5%9|kY=Z3ei)3iMcW2obEqspf- zX1jFNnHd?lTGpm-rDR4{RPoY-Kp2aa+vCa*i+Rq7PU?Kzkc&B1UR~#ots8Y$T(4Lj zmWw-hgON#tt0oSNf~;>456*_}lX3Yh#ABmRJ$$KWe)r$z4e@O!m@yPXMGvDdQx3Cy858Z*+&N2{r=j&Aw^8at}f_S zok@dOz|J#%rl7=*pSk7yYuS9UrjFbnmi7 zl$Y+*{!g)eJi;AKS1#wgxC+jBOr8+B-_z6ewzKn%yHx~V`o8MWsrJi7EcocBEZ58> zrP5IfQQBX6HA!d=9gnPxe8(piGM(;5cK2EX;GI{nOc1zc+W>n9+s?F|14qHm%&ZST_b}SR>yGPLk44q-}HVyPU6r15ILbld&IM3LNIy z##g6OBtDD!BkS2%t)`)k!0(9b{*p@peV3}Ah0IR})LbiM|JGPx!K{-fMOL6RwGtQx z>fN6Q70N<33q*?g?f|Z=oX=f4Ug(!WII%y}r)DN*T*;D1k6iQHzV{KQ)cwF;W98@9 zGBM?Dzt`oQdzI!cns!M!p~rWD6s}fewj5419~^EfY)8nR1Gy4fo~4_1Tk!wwII_|F zs{$hsrm~O5(bnY>@7HOindP4XVY8RiUnV_9ey9>&_tL-%)G4P%kucSLlx{UG3mFw1 zzAfNd^MWNQ5N<=5U=MtiCDp?k!aW%XpQ@;ZR!IZVpztBSni|WZ{YH?-oZqW$V>bI) zThvhGPRku*na=wknInH*RYC@4KXW^-UKgBmn`?Qr?NTRH9-Vvc+{~nt#ZgBLghV)y zhgr(MD8EA(wfCtISWpZaIl04wEJd7+UIf_`Uc1F92b^tIzi>W25 ziQ_;@dRYtRo?OHf^|ac9vhNy4F0aQbKf~w9ExP4guQnYX6`PH_jKw`=pSGU$;(#zttFp37Yhl!d+ z<;l3!j~uHP*3?y?^+Ls(gUjWD@Vg2s9COe}p#@;J<9Ki{sDww!)6}-@b}zYU*74%v z?`%^f&X=X5je}v1tm|gbT9uBX4FEf!53Tc}Xpjy;*^4qROE=ZP5{!B(I*nq-qXMMm zZf_~c88|z0)jnHEt%yr&80c-uB>IDgMp&|;LVT-G)(caSgN8J~{UAO}s1O=*TuQJP zYZ18dSc)L-S)T*3no1|Pa-lk*Now=$I zjk#7is$O{NQ>4i{!Hzpi$@f%*%_?Z`m`ih^S=BV3<5VVj`jhDNu0As_UaLi26_Clm zKs=wOBMTd|)wdti)xV7j+S&vQxyW~(A8Rv9iJn_8hK5yh2x1sj=HVzK$R6m8eQHHx z{(SdPHqJ#tHn5Rcl_s#UhH#|@?OxNNrzcnwRFF+T_Fg`Nk_o5hEC%O{9Czc3dsC_S z+ydn`L+&0(jAVQ`%!2=3NiGwx?CMJc5@1rZSuNY-xfU$DgOEP+td%I1Uv+nT6$CNbq^sjqoC z&$g9zPh{ve?wXCho>{gGs1Bt(GB@FGfSL7xJ1X-FCQUtoon9-eT{39`_od?lEGJ*T zh%#KevpRp8GA}Pz{Y&I*75Sk%cZakKk?`)G?KJ~fOaRbO5jh-i)X-dvj||q9_WRJ0 zPVDJD5^11g?~x`YY;g4(gciSud&sw1#Nb;@9SX{HBP4-5c@>B4PXO$fThnUO7|AFg+(wi=ypo zST`J&0GDj?-Uy z?4y`f>D;>pUh=h$o9h(!Zogs7)QkDrMcr4l9hLbEeh~?8);TkIK!!Ef83qeubRo>s znM5xDJ2vvJTZWK=bIFU!OGDx_uT=%vxsl^#(HZEC@`}7~&{3iTcN6oyRW3i&PyhUY zMi%x7!C~JiwjUjXKn5%0+5+k+!Z&+tZydjnLN5hmj|e`d-*@vT(Nh$~`kr21-OG5D zva`PkE@aY+f_P(wTU#GEqL{dYUT}I66CRxYpv6=H1tz#+lI!?eA39{edE*mvCV*W6 zt(Q5AD}Zs&DEq*<>s$4K#&hDu*k4I|5aG!kVFr>k9|fzn&RWx185NHF%n7e`cfN`J zb{mQQHP{MO{Uwub8xO0RxaAM-eK z=CAs-b@c32fsj-y%#o5YD;7MlB=ZK~SL*8C)O!U~r2BhdPvCYE_C-JRE37lU=2dMq z{QxyYqZ*=G;sQ{iqwNPn6z$P@#+rk~mT%NB!e)JJ*!ILLNZF;z()R;%2XnRx} zOtpQ`mAsbA8}Yu7y^3r5DA$-Ej_Ai3iYlB6{qNbTJi-FCdOOLW1(7IVV} zLH~`rEJVDv{R)^lEclAlP{|HJbcc`GYY)9E{fiqvg=pz|?ogu)6Xc1*WF~ z>;3LI=eOr-@|C8K35w$1eRQz1=gS)HI>B-aNym6EQ$ll-#kk{3wF!qxOZ2rE**|EWtp14BP~X!v zXY_;0?=z~#;+UKA9SzypZ)W{225I7O1;55FC5rjd1h?U-G*o2fzbs-I3ky7B*t`5| zk^(K4#*7s3C2qUI)DC3ZV2{xRX?E}SMlpG%H9IE2Cxunsjz*|U@`TCh(nM~(!Yy`{gXY7<9U*@^}5bgUuVxZfJL-bW9yv?;dHZpv__+*%)Lvc4&tGU5>&%toP2*>c0owyq#M~c#G=Gaw^}CABW>$a8iTXr2ii?cdu=MLi|omW z`SG3~h{Tb(vJMRK#6A4BHh_U)Cu}`ypWD8J5ntvks`tGTYaJQU(Yh?PWP+6?8Qci?*er2Ea_K6Oy41`p}`!g9b76QT=o5}wZ$!^-Y2@Ha-D4|4W zrr{;IoxRkZK8PXVGdOWCURzbE+HVozF`^+F)l9-)7A%_U+Gl%w)U!ixIPLH@C#Y#- zz%K0t$yh|x#(%+{2FLYmcXs_*hhHC0$^W+Zcuf?|!ghhoOT54*E!d*%1hMM@RCnTL z^1+qvl@+Jpc35Qcmme_h$d?yf9Wa?*`Xip$F(U{~8HCTpOW#<_fagvN)7iGyDCS(7 zTYmKsx{$<;EH2i@u&>*0xbggXv znA^Wd=069SxC4Q%VuFtij<^f!zDQ&zN&aH1kxk&^lIWlh&2!p|s|Nk@rX6JnXcR_8 ztbra7@ODG^qP#}VMUc;jP5JgYCfBg$=FW!JDk^srr;qYMa^bhYJ275f?nQT|Ru>(H zt_-Dw=0;hXz#W|rCPcy~sqUK3P};R|SHp5x$1pHMXk?ZE0WY9+T^0QM1i8RLErIfk@S%$++v-SvU=Sm50|RpG6O+hCf&6bULppe)}JYC zqKCin1KR`M@|pF{gM!$gMl^2zoye4j^7Jm2kF|rL58NHugh>u7YFw3>)4im4c|YJ! z8k6{$5L9TA4*QbZg2MP0n}vMo2^~>>Pc$JDeE@Fs0lnx)4VtXYS@727x67{GumV** zsm&W{%VHBuqtZQ-V3%But1}!1_DxbHld5OA!>=x}{({6$5iGdwGpiUx}iq zW(HNljT5R3@e>ccBYDv~mgX5y>tuAa%NN$T4IGfnM%UsP-AHK#`nU#`4Koz3& zGpCM3z7bM%Wv0vXTk_I7)%Yclq@h@Ie~y-3FnBs*mV74UzZPG_>7<;t$CVw?BhN4N z^qhxUn*#rmz@)@bC^YF=rO*<*r36)Es&Ekag4f7XO;25YH*em|(i`Q)B|SK!f=@fV zQ0S;V>b9?V=W5P*W8M4a%n0O>PxvAtx^v|8L`gX2uirp%rB1 zZAY#%{{ZFo>1!7Qd2|zpxbXe){;U4z?>QDrFF9Q(Sk0g@vWGBj$wndU``x4%H|d$f zJtJ5Hd4ZTnpZoM}K>|4;)twDZKD8R*nz&zi7JH~IAd*k33UXgym}$a=wHjPvsTO7y z_fCTZx-WTakR;oaKXPh~(VV__ap2I{M!8V5mv_i!K{YXc8$UnGpqw+Qxv63BMh5}4 zA{3)2Ml&DHwOthbk18JgBXZh~1=`BT?@mfJ6Wdg4>HuB$^L!8qU<WL*+2jj4n}&wVjP z?Ast7=TZz-)nHL=V6o8OT5dE_wk}RDD?gJ?Q?v1MyP?gvvt>zLIB)>;O3eB<36yAO zITHvGuEPghrahAvb2#nsz;lKOJ1+D>EZ+<&$$kiyPZtjq00r6b$zLg;tKo3SsJOTCErCZCfF5eoMdE7(u1qKGw==pbrOc(n3v z9i?iHbXDc3KZg!JZ}(qWnAUEQFD-VN1W_K_y9$^2W+w9Mp4jB+^_=`fH^cSts?1cA zcpslEbxAkR1=-L$os*-M!$+Kj3@r4J%pSYF0nlV<&dk6MiRxro9N)hu>*U?2q^fD5 zKh#6iuh|kz>WS^!Bh2~wxFC6l{lv=V<(;^r$PAGdKm5=;tt&71)b`h4mzi^LfFXZo(-d<) zDvT&xDN{IuUoeZl9<J2dGm%FGYB2(HZJU*%{y>ZVa7rMn&ZvS9z`w z!E%+LnUUgs(PgU#YyNWn6u#Kha2ix&pG>TQu6BQyZSLs|k~SiyD6$J3*D<|p6=}YE zXLXswzX9B+{ltk6d=E9K?!7YG6vpdo<^1=p30GG9ROfJ5>!qiMd&|5kLIdw(v#W=J z@D3wN^K27M3#<OR0?w|+;hpH6ah!yXVM)UR$VrxUcBLmQzJ+Q^wmyqsr=aCoGdIaa?KdD0S$MZYD+dP1zWovmsuJ$ zTr6}gf5L;cW-;CjZ7GAG)}Y~$k5k(Fb;xOMt6fd0hEve^AMS6uR#%T4)*!Aj2t~@Y zgn?NiB`Fl7ov3v&R&iK%YoeE2;uq9 z0zr>-ZC@fKH^soaermRu3)UuC?9)Rv;zJ<3k)@q1p7((k)Q@Vi~deIA4l#?19%tE-{T4qi;v z16)z4mQXpG07huU>Hp-4{6C-wq)%d%99YBs^iP7pqnpx2Ade8Z+kC@@Mm@IFWAdVY z8}DVpNv$V^#w}Of?wuELoYWD*G?`RR^8~K`kY{EDV<}FW##-{-qb4e*%a{NuT4*=? za2`wQ*Ok~ieFS2h@`7+`c4jepEpU66+IQmQ3?9N|;}Q9iG_lh%T64C};K4f!{YHAF zC|d8jig=aADx=;|Dg6;@uBKK|*z<~SARgn-l_63FNXUlHjED zP^fLSE8%6hRP*Lw(tY2}7g-9@sENC*SKR=EzqCX+5aJI2SR&L${};Um`=j(bS)skV z!jdxH78-GZDYI?@?w1t`xL?z@vDIqlM*1BDU~y_#@VV?n%PmPp>oUcXU33&KI=|aK zIdAasWfMy!d;?T8S7ymAPu%bgHn9g@r?!2s95C|{MrS!KH90~vL`&>#7VySx8~~ww zYX?WxEK}QdTFu5E#I0t&0pN_2LL$-2(+XPyE!cL&6lMzsH#~t)4BQkNRH~Cn8tK1o z-Dax~1OG(tw@H00dQ2@zP^#Y?rO_ZcA=!aZIi@@=XkS=`6y&5G#Jg0_Y#e{g>3H#^ z4e5C#3s^nIX0|-YO;bf9$^0mxZs?I|j~t<5%&VqapICnoL6^s0|70t6RD)c}?jEVi z*F-TlsZJh5TwrJ?&q9M$l+xvU^o$l6Bk^}mv-FhT%IY9ST7O@tm9Mg)LnIexc7xQ& zc91P}SVIwI3h(2-489}TQ^oX;y=NBqBrV4XL`$<2PT6Bn53yY(H}|~r!H*6q<*lEd z9_`45R#S>lb)l_pB3wc%_Z+ZHh07Lqf###o%{Vd;p|@5JYS&Vvf;@9u(g@74UF?#$!Qqt5j^Oq%7$3E| z!<)D_fW0}cF%AeOc-vGEdYv-aEhf!UvD-D#U&7KF9qL#v^bExsV|+611I_+k%ANz_ zg)YL!qAHhpoVu=a-o8c@v=c)GaWV$}proX=WlGEh`b9`t4~Lb0v~XNeF0JZtTay7Y?jsl_m`C zOYQf~P_&0NZVcvraGPBhCla0aEN=gk8y1bAy0D;w*)YDZD!+YP5a4IVRq^+val|Uw zN1O;SrKhoV$zOz>_ruyWi+i=%k+ig_Z|i}m+m|{rZq7|BHux`etH|D?@#;fj&C#jD zBV|0*$l?@|<`3*?@%21Q%X?(HA#MrHuzzykzll*sN5^=ry>ory-Jqu=dFJP?XSwNA3|AQ(VwB_ASRPwRqV`Kwty-HU2g7D+pm)1PADa<)ww+#y zVCM>MtVwt$B`vHsXs;5MzYi3hGZ33$*5OdD3D7Y?l%0m+UhXvQrbl?Oi~6Abp*4|E%(yTf_uUi^cO z-i#>@gJRN19YoG0+rgne=Y9Q+!3A_(%1(?3`LcPHJZOG6c8672S)MiK z_f~T>RmEa@qgqwT?}9v2<(@?_*YD|iD@Xp)=jkjPHr{j@MQl!0Ol0<~%r+*H1E=qa zKPD-5LCm0eSS}|~Gf;4hjSLv!=bdUy+*(X#PX@w8sL-gFqSYh~cX=Ax-kvY!=_%*fKOz>X&+<|m zzl`-b<=CnK&onMQuuK(l+Cpi|rKec~>;l818s` z+vZV{OB4-bwU3e~gMGqRC^Y?dmukE+;H6tlVVQ0nHFY*ywHSORJ_z9GCKZ0%L4DJ? ziK@m~9jKW8JI1fvM?VIuU-fpWEvQas?X-H#5C3NiEt!c)ei1ak2e3|*5S8cLGpA@m zGb3@{G!;ho=@Nl(zBa0I#y|-VaWydNwBidgSBNtQ56k^51;3vG=R30>Z1P~*|o$qpH?o~WH^5b z?b4DWQgy5*)`njno;Tvl=Hyma9aQ9vU(tWs{JU=Qkp8i>6l8nDE)qWQ4l3uMjglx4 z+{*k=SC%2J)Fj-w(DG5sDTv|G#p8=>T&t=q172itP$s4!Bfis$jk@`S3+|c_6hT%a_99MEjv^>9yFu< z??2_=Yp?kl>17I=rLBEly?kdlSj&H=jQ@c+84*O-cf@K-UxwLNXp5aNooW_0DCr+4 zX*yVa+Vn#{-1vsEs310Vu6fYB-d*@D)@U#9Oc;o2M#k;lKdLFm>zWwyd|hPXV>Otj&KkWBUCUMX;gH`qs?mBi}e zE(klZ*6*FhaLFxfnq|Klk5Wg!jkUW*((!$yxRi}=lK4xmpjZ;AMXYm`9Fs|U9gaSW z_MIY~Bm6i~#S~**U(~>%)M*RGr=qAOe^+hYrW#W#BhJ7% zy6zlnKTbW$S|~d^Gma5UlF`8tpx2*a6&a<BaGrf64Wt9!o}<3`L0O!{=qo#d|?v7MqFxjU~XOt7ApAK%R!7RTk`Mx z>>irvIL%o$@fOA9MHQx?fd`_43$}{&3Adz&pSZh&ZIb!@G+7_IO&wg*uE(-0Ak|Ur zA>lPgHIIuI+eza0<{TwB_;E(6FjTE~qc^PV6HfEU_6NCMowIVf7 z$!ViKmW+JR)B|?D;}U_n+Z9PslbJ&o>(E66*`VW#*-nHN%jCV3VHvTK+>N`cG5cpa z0CUuP<8uw;-YVI8%9oQIK635+?NU)1b$#H3!0z`OKpL+hi6Ux;wXYWkdF2iPT6aJz zaAnOv*|j!jkb_vA(ln~Mrt1P`WneXC@XU2lF4z{z7?x)BMF^0pa{)pt9V#iU6;x()g7DC0%mM7!*h3K@`w~`kbcOy za(c>=tQ)t<5^G^J;8u$$pAP?e);5883P7Y*f&7v>Vn!z>5h#n|n*O?up71KqAN!}a ze`yPC#n-wq^L?}zJJApS_51@-H$}!Gk9x~m*Hqlh8-R)`%A_yOC$3LV5LRc=E41!6 zw`zT@P{sDo_~~1{DL;ul`7c_SOjK13;X?2$e|%nk>RMlV(3-Hs9Zd0-&)VqR=;8b| zzXTjGroH2=O}AP2f9ST*n+TrJnzl3u-`Qt}_bkRQgLXGs4%3@l!-?L~c?oS1+Jz}J zc6au7_u6j&SW?kAxd_QoAju#C+ZJCXQTI~GzxoZQ28YL8D&<7;Ol%A~aj{Z3V(j*X!VJ6fH@%<XukGR8A=_h2d4b%sv)%ajoKTC|&02lRb9+R2a%g0l3_Jep^o~B9 zUD0x#S^KXi_!qsQq!YX$0y@ZgDssIy=8muDA03X*MOQn@Cb2=>Eh@0~%*Q9!f9Byk z`i?jCbQovA%@ZIhF^q=t{J}MA)mt}-uK>q$=KM)A6FZ+f6=FwbZdEQtJPNt2qjtuD zy(4+fJ4$HTpSr#`r==(#`I;gI03@-^UK-J^cD>UmimDa?kjYh8PaF zOY`GuXUDqkH`X)Ixvsr`VF!$J>#_Vby+jD_WiXD8Mk!=QmnjyR~T5tth<_?TxARo}i z6d(2~oSsOo%A`oBnU>kX*#_&6U*O+UmXd0cmpK^Y58E{&Txuw-B*Y)c)@-WG$dy+E zAu#3kh0;FSkJ58cvyUYXuv}|W3tm?CLzG}0oj9+RwZMdz=&pH1*VtkhXWz#xYZ)Ro zt-e5)#Zo24ATMaU2XA$?`0BGuzK%bIXls!T&$wKnGcAp^gyvYDh_HWQvJV^iNHq#< zRWC0Q&xq_SoA1%Q){0|I(=aGq#pBo!3C$9QX12+Q%6SCUxxtzwR)duNCkPL|;)d{u zJKL}~P2_%5pb5>s=y+Y~q~GTu0#aOQ_{&6_ZA_I-3y*7zN@*9ra>TZ*+_r3LGx7P4 zxep8KudADCQ)bt6$ug#mIlrlWro`h0&wsUG={F^?VHuC&mHWh|#MMP060?@Zm-YP9 z7Nv&ML*Jm+%7d6nDN1BGN^jAvCDUKkZn(UpDyz*RNUZ=a=NG7e+hy%qp^%5)y@?WeH}ifKF?V zCCRKni6rJjGfzlyACW=Lm6pTgwSG#9$VhpK(GrL&AKe9S`RYlh0( zf`*jud*<3)ha=KWl#>k7<54DW^eA+Uq3i!^(OvOI&qn+cwdv$z6yfoia~@rDa)Xe&?b2=MqE8yEa*J zd8`k{k-ROcAQgCyMYF|g>k`^b@dE_HkqUSRXx0! zO$r8^YTpKzS4%N}*HxKR)u^F>c&3gDl7`(b&0_wq!p@hb>c|W}O6DADx@oY}$yJ?RFWZ<1hy)io2siq;d3QP{earP%woZ`X1)TOLt zc_CLccR+1%k1>yxF!CBdTGkOneGhM>$f8)|#^(N0QtMAsJIX8eFvi?``p`f>st8&B zhKD}r;s|p-4^9R~wN#LMM|*^YHHv3<9~eG79R>3XdFRhVI|HNkh3`0SqXZ{Q#!Lvj z-A+tocb!k=#d}@>g~Uz6hq1ZxLV_xVXB4wc@5{i#3sg^|;U5U7L2trAYSabcoR2W( z$7@X!Op&N~3%7ZB=m9;>s&mhwUKbQ?>5#|KU0Bb|&=5+fc6w@!P5*1d?)3a%*++?c z>X64bFBW@i>T(%flnPHR);~;-?S@4Mg5p099HLrV&06{T*5LIzW>Gr6$8n;Sw@@O6 zs_|p+_U_=HvC;tseU}GY11aIwA%IqgXoxDn9W7?4BWi@TqfizXuQ5NTaP9I*pCbbT zPAiU+q2G#ne}jplG&9i&4Txl*_0432`wlZEXfz8yE#~=BFOj19p5&432h+RHENIm| zkyIZSydNB807t*RO-G(fB+qF4(n?mo<;__TYeeVtu}8f8Yd9itNs1QLm|{RUD83PL z&=@chh8xUDje*Mzkpst^N=!-z*K0y81%af+&UsqO#Lb^YX*4xL(~O(Z&GtR_@Kc^D!WcZA4jFcvgZFv65B93<7Hf9*N}inpW}S&K~JqH~GkVMj~RPx@1b zONJgu$e!Zu!FYPIvPKaq7QMyn>^rFXJw13 z{a$qfARq7Iw;r`$ReWrTmd(@Pn_MrG<`>k4)Wm*0tDDhN1(I~d{Z2zzVHOLoV+zwQ zqB$-T5PA7oy$XWRggnwdFZ7-Z_oi4!dR3deEj+p-DdZej#it)d8e}CV+$c8FFRp5;{#$hOf*y2fR4y?W{B9}j?_n;N{)ZX-qXPR2gzUO`+0;i(}hbItTn1rv#QLg zB&|_G=z|Pp(cfxsBUh1?UuKJBMqytsoqMNIlXbY+f2x&}HjSUwrp!1n z5v~%hIvvIs>xU{sqv<9hF=j2MQHCs{U8<0${7~lKiCuFuuO?Mj9~(<367X%E-y8aI z;elUtkwc&IPnZ4T5qlcLhSfT>*{;(cm{&>JC4-*jFt{eHj$c8e=jTINQAnK zVRMr=%A=K|H4kj!g={O;z@Rq7Eyb6{xIQx5TQDki0JDwePOnm{!; zQpDsTc-y85C&f3Qv}Zw$72hS??8Z=1+sm8&B9M#mBXsEN&KHdOV>0otfW1k8<$2w6 zX1JLO*OB8O-=w@yvxfa^({U7`hwwRe(bV4p>5g|C-^%Xpy50 zxnEwKe@G6i+c5jYEVA_4d#Py8qIv3IS;=}dN|Cn_?18wnfR+r1^_vv0_tXC5kZ@|k zSh>`zo1BBRjOV0!S$o=+y`@!8`@Qt3^wNw?drZ54(#jJlE)YK(C+X7=>_he>g`Q4W zeg*8&gd@uxCNO_7)+1tq(3sfg|AEi`l^a-E>{ek_>Q~`1vnfE39AzK{PN&G=!-fuzu=0ll~Lt=1$J zBzwy9I0xF^TkeZmv2EHOZ)UOzvTtvGGDr{+Kdwvg&?Gkr=9%1H=T=%+6u-D*9!wCA zD7fk9ZTay9cwJ_k_NK~{^6pd7@JtV4rF20vrlK+n0DyTiXlY}lR1EIlsUQe2G(XXR=en&SEqo%xswj@LC#;p8^Dc8gfMr@2QLDb6pbr?1zkLqC zqB#EXv7)di7rNsk9`AXTAY2hI&gdG?0- zfMDfPG4AClLffQYQ0(o}seQ>?{y|D;_Ueuu{`$M^Qx-Rifktq@tjxj%f7?0H1?n<} zG=d;J>FybH=1^nxv&(+PGLqdK_!}&M5Srs(t0S9BD#rO|=8k1e5-he}Zm z6Ppablj7}G<-Bc%C|y@)^vX1y=qFAIAXio0p^;}0^BZhl)hD`iPWD19-33W>UW5Gy zSDnw=Xq?Jgh5Gh|Zd5n)w!`hv;*eKcP-BU)s59Gpnp6#!c)i*C!;&baiL;+{TQYbE z^YbDrDuN5Lk}c6(M<$5g{8`+|pPr$5V6!t^l)U^#OeM^iiA19brlhic)l$%DFd{MO z`gz^sz+b>f|v;u|zHOAz>olJdA&~&UpTtQBE*MVCggBcbVgPNk=)L)dn zH(zX-r$^3KOq8=sho>Yy&7RNsX~JI7|C=c#yB!WumPk%Ghrcvmr@luEjwAdqw#}Ss z)(q=96lf%V^vq|ssV80TWOU6Sa~IC41q#dN*8ti?$wxab+8*u5&~?-yd_!y}R92~t zQ3Y)aTHijQx|Sk3m%guX>euMtvj7$w(bf$1LoD_fG=L$s1V2$n&9BAN!>J#+T#h2t z<{wJQ0~mO)(0+A6U^ad9?xYetWX%1B)c}P}P}T^vzEO8d98wZyVtBAl#+cGx;bmRk zkq0~05wmN;NM7ho3$K3~v zdEep5`f}5*vydYDT~6OLOq}s9@nsbPH&cNql>-L?!IQ2u4-c*%0l zU((iArBZR(vr{d4(!5+5hC0f_bmXLt(4R+2?3<@p(fB&~K@IzW0Tl z;gE%`YTax9({V@)42iQ+R55m2H0p>V3lD_Px}O)Ell#{1fI`Htd(;eEGVH1mvNXXb z;0Er#)2D@PO8*`a6Y$^gFAI4!;teJn7fH?OE`C}>kyy@z0=N!;2c(w`5|)p4(6!Hb zk+^`H)1*HvB>{n(1)fT))vm2~u^C1Ddw{3RxO5sOPETt`6Xu;(%Y|0gQ-mj1a=H*o z7fcoug_ytVhm=$sFCVefwC=+GEa3(Iu_nXhuqX{y9NRY>NlsDe1=C~@5K1Z>uKPQV zc&*3tDIZni4x+M^yy0~C>(5qQWF2@3SPyA{zCFSjX&TKB zWf{0wX)zESmpH+y4eR5I*))TSBoU3=mG;%n2n;J62wuLGc4AoQTH^vC$X-3g{3x-v zHwh>~u(Lh(JOecv@-{=7B={ys?gzPRiW{sQgy1C{&nc_WrPCJ=39m`x6|`?BM6xA5 zR@$JV0P5zGyxjGd2}b|#8klTs#LI=f2d|y_>HXAwYGfM=VbFLd4QI%EK?xS%Ip`J; zawMYm0qDs;nt51&?+xy_EHgbF#uT?+9@8bA`lvtrdG<=bOup^C>Q!f-o8DN=oKXnT zPcJSPw{FZLsB}V-p#a*8M&OsbV(h>-U(ZyL)E6pnp`T#`l+?+W7=EK;eq2=YJ<+A^ zxjd}n@CdHmuS{(Lx!a+$yAm=`B?~vLIIM1Ico95hDJ4`YL}kc?S?PNT%z0O+Wsy}pt=K=fYQTfyE78L822ST$*k zpUmV852Z{5vb5JWwy^4g0+14JB3JQT85!fy_ctST%5q)g6$}(?#qT&wr~wOnogka( zLXV5)PyM#1bRj)QGE~*}PG(bC(xf)^V0-WP={ZI0I{B|dFcV%gnHc8^Kp4lq=_|Y; zy=2I|clE~J$iHL!xYp~cYux=LHmCuQ0fb%+jkbJsOciYRYhlFP&a0`Da9X9vfjNGU z-R7J+5LL+Vj{>zGLsU+F(&oOybPiBug=#?l8+0FVwp>sYGaZYdNtWiw02MX8y=fAn zeHQ1~Y0?8%Ep)Be-hWy9)oc9{htWVVWpG>J)_2TxP7~Sl2obovy*bVUH)Sa^Uf!}F z@~W&N9Y%8CS9b2_Ibod1Bv*XTMeOmp`Um6az;-J#=DJ;-97}HW!wV9`(?kB#;8$+H zMSfG$Vvy6y8Ozi3icmDH%n!d4-LESHT|B4*elRbWS*ml4rw zs#=`f$;8w@sH0R)AS0}82)@qt)6%F4y^&X@rIUYmVreDe8P}dMOhpXM zmNRryH|Xadms9JbB&kxLxnsBA*aN;(*dZEnH)08sVn!G#VC}QS-Xy=m<_wywi`&rI zZN2lQY39mPj@r`deSeId3OVZ!#fLsBaoXlfo|9yklZ4H4k zpwe;hT5^u@u+4tfbTMsZUn1#=PjWCntR)35ns^5+Ua#$nRkvBxs)K4!V_h{a{PA(T zD|O<()G=OaZ~&WSD1rjWWaUF9o>+);`s@mM=VjjkMvnsW9?FBR5|ffBFEMkGu)oXG zrTTWxTZdacy*BC3a&chhmq~zf!Z$((cGBG&)=7KCEPDm++M^JhwZ%D!gG3wCG^rcI z80!y0Td_Z+#LCO1)JQohoX5Ka0!oYD&u%ERQO+4D6cT49Cv>a5fuj@|Vl*4TUeNo5VtBq9$0PltdrD_%)*uT3do(q454~ath3}cvG z9yY72WnTMkXiRa)8!Wk0&)a0NX+=i!Qx%}@$slI`erw#RGPeIPHwJx_arqI9P2uR5 z3UjZFULALgz0#|RfM^f{GqzhA<}iA7NZ{mPGm-YBLkD|!$Z$RwY(KTC9l*-PUo~*C zD6Tc+szYDj|HmcA4QJR*R(NhdCwh4>p`Q4OR7E>l%=+${(3sb)S|eLN1&aiUS|&nr=;`n6?hpIhKa z8Jd;M@J?+s-`p+p^QkeJ#~M{0uLrL8tMLj0((#WW9ue zm7=Gi!P7MEttW8NNzqylmxs7h_#5}x*Up?TB^rNVb6>(sISr$!6K-#he7(;79$N+v znd;YLVih&=g-*Mqd_r&jl(O)&*Pl7Wx;RXG6gG_^87UmxJP2ylgx~H12+@=RnSML-yfXD{yJim#!Og}{5w>uora_}7iHqS!3! z>qT}MI}IM{&WUOK0w2C`FA;jv1U4J$6Gbj;ktSY?z*ILAutDNTQgFU%uBEFRkRtot zcSRv)&AoJuLL@81$j~Eqx>L>4cAZP0RLyJ)ywg@|^;$jfI$Xp9 zh?jz2d>@FKQ=;>DgNS#yg}#(wny*0sK@2a6MFO2I=p66H@!HaHwU9uSkU>nqHrHe^ zT`rc19HHn8iYb_(OKb@*%s(lojHxm~p%eaIHKtdw@66}BN9S!)@9$*F6(lt$8G@91g8w4KVf9z z*M?cZUZ$d$HrkT3gD+5cqtMgH&=WW*k;t49=M~orm5k1iQ~Hyq69LHN>DAI_MU#p( zps>8Qu^KHAIayc8nuvv{*;2qP{mi%@eErZVpA+ukNX1CdGJ*^J{)XF^!m=ng&u{L18Ua4VHYuiau8K4x7Sv zf9*I)qj~IU8oqyBwhehbLvB`$oNTGc~vd1LmihX-!%b@Wkb@imzjnx>3 z`DN}^x&$qAYt!?qcvY56LT)q>T5|j?MMaa978{jy`1YL!Y*!9VLhS?hk=q6;?r+cMd{)4!g1pQX8~c||lW z3eNh+*OwKI@0$x-OlzB;K^O>1+=pKOEXD)yXPOXhNI3~6?^9fkNTW$-ec~BbiHB3q zsx8jkB=Ij+iLE)W1*l*~QJXyy<#*U|c`f2z5kw?jzX#e1ogYBg4G*?5<52}PVnO(C zAW7fJlWB0ier?&;!(gCHdrLriOD;S|UtQnnyYE?u}P`vpR^NxyPBZkT2?(=sTsUaGm0p{Srcsy%FT^b zJs5H-$%PGM+{nVRONrJi?A!n%X0t`~7me})KxW!sV)`vUn4iG3g}nip#^u#(rsHCl zdhXX6L0wV7cz-41OzijIIT#@Pn9Vh#-N9C6ppwLMqC-lbR~9$yzQMwqPYXcHXYmlnpI6Ec4; zG?hWJZ@)jTE(7BBS4Un-LZUn{lnDxiZm8GMj)`UwOYI)Qrk>-B@P^Kp4v1{-pC4#7 zL!;l{rjAosTRWE6tPv6{+uzWY{QivYs_I5-{qrTh{2VXa%LUB5{ZmAHA{~6}A@Bm3 zN3QvA<0G%WBoWuWQe6w~&E&rljlxRE?9R;(Y$4B5Zy2mzs?eNBMa}V7Lw9frU#r?M zBPW=7TC{3j>skEEYBgXZhB>dr*I8%jwDFMb`VW$UMgl&OySByk%#1GnYk=bIQl+iA zS8dCuTEFL%d@sMT=$aCo`s4Zt)N35H!uT1*p3_UpoYQqQLIYKxR}i!K8pQf#%J@B? zBH~Uqhwxk;z6>$v_U5A8KH60vhqEI$q1=Y*(0)m-m~$iI=g=rV{b%%JrzQ51bgge(`tDg{){#AVGB(OCn#CyXT{j6WYCM*pAsN%IUAwk7Lc+#K1PnbnHd^Zka-f^rY~95;Cdq%>l*^D z?)>3K2ks5;EdFWY0TL_S ze~x-VUJ`(0IUGQ?B8>>OdUhQ@>hXA_E_`-PN_#C?PR>Q*?+nXrQ|&)nf=LY>4HiIps&C-xLdZpXVo`4U!HG*w>aEml z&P$nG!`dxv!JOE3!i(|;eN-AnVv8M*968PvUj~HvVZE!8)25O{25OQp(sz7&}j@EBI^&F1Po&qco?d2 zN>d`p9bYyQ2CCO;EZy?+(9^RpY4946@I9(;48oZhZsR2vTo%8a;D7N;>PgNO9+>(o zqV(t-?h=U9NDf*VXGoPT%VG-JO{ku3)lmH!nMu-s?%=Z~l-1DVW20&*doj@X*!68F z0gHW*TeHBg@UUJ3;^hn>r=~%T<$$6P$WdJBk!@HTjuagu*TdK5b@-DksOH`;Qm?#o zJ)y_mnw9Z^X|rD(Usa1<%=JxS;nDSBkqH5sX}{2?F3KqE*w1_K>C~-8?6@`hlNMse z%%>J6(3+xht2Q*@@b+wlX64riVC6>5@0l1?h#@^b&(5Qf-07ZN>&opj%uFQo{La7k zz1Bn+*5i{bQ>rgKgWnGz5Blx{lxH5OuXVi^EH1M4_vPe-j@>Jmo@9>9)o;Xt%iX;` z+H2PAPZ~^9Ml3zJh}b8)-m0xKZ1)2hr!Y=*csC+J@zcS_@xjiW8v1PW=@0*w z?9k+7w>w4(z4h>ymExRpvGIl46H~-}*(R5DT5IsU5oWTnynTnqd}Xo3=E6>aAH>`d zr{k{N9;5HJ^eU5Ce-MGg6NFK4XlB;ATX#;XItlr?@E!8w`-A|%FF`!`v2;Cu*Ke^z zOk-cyUAU~bb!(eUEgLb&@Yr{(-f#$<P&N58H-VzU%yoVnVLROi&opJL# z{&tM?$9@Enl;bg0_quG|^I&t`{aIJt+DfXVr*=Ig>Qk6uz;_V~YEO92B4sl$V_Kyv zl+fb;hr%rN2S+7aRehJ9mT0-19m>e7eGzcDB1P?IY1m7A>v|s4xAMpOG()ick)7l2 zrv1bz$L%5Bf1WP0pmb2#tzad)$UUt{nFaB)j+}<4q;nTg8D&$ZTxZC|amdKB@Msi& z3l&4Y%Tl2Ru^!lz7QtWHZE#M$DFag}LnT8?^PZ^Ayzktnz~3v#?vHB^_A`(-B{Kd# zV{${@oi+9Xgc)@rzvDpo3L7Si8I(?>Mv-^tPV{>hTi$XBwxRKog8vSl1ZsSF|#!bvrj8A*XT^#6@a&s;9I`5SX?eUvU8;R z_aJzfKMDDvfX;4sNaap3oyY!r-4FP`$5@kiy$?AH2ab}^^_YO0ux_Tpgx1-y;Z(p3 zw{*K+uFyGNVmI}QSE_^OY#MG*eT~a6b@HahFW-21o%K`wf`vi=jf zV_=ketSRp!YPve3b@!WWd_wh`-yN-&23Q4R#un$oHCM`zgu4@GN6f6_^BDWz7gN{{Osd;b-@#6IN(qO_pH8ZvVMkX z2V>JcRl!&~MjfqUG0&n&r{}lTDe`^gdrhR>D33SVEA{FqrWOK`@SFmX(8E++WgSNi z@o7?coA!CrJbF=)xW!u(KNG`uZg)pU&bp`Hcb8-hWPc}yE$hpzCl)O?92N(6(MROT zAO1I9i??r)wSTRX^s%xrTI`T=##Bqr_y5^1-nDsf3J%)NP5v`d9G|RhGDlYChM7Ic z`a?NVr^XBKPoE%Wk@(jMDW*Fdy$=T*HI<~+A`%MeFX+2ene%f=hW^0K z@?Zs}UR%t%FdP`Vc9@}Q7;J;GlF9mMp2$fsOkNwTRbaH}dd>?dm&LKBThx;vb4Ybisq-we4_b?~(I?&+#Z2Hq%xmitB z)*dy}_H2t^5*`8`Bu;lu)dUHOzd_hvqdNAK#Nw4DXb#BSO6*fDBxrPT<{_WW3T?yb zw7W}j2sYxgKmktEcvUyeCyrfJ?a9C-{sFe{)vWt2k;?4Mo-13lse=aM=4401or<>S zgHrZ=R73p{1^M&8`UhptS~e(cxh+I(2}lf?NOY@kK7KKsWJu3|F%cD>(d9Le1GF-H z$%>1=DT;}iGgv>E961^6H8Owfsv2tz;}1j6i%dxR;UTp0`yRgYG(Y^m0zdzi`XNI{ z2#2Pcxx~zKz6~Qooz)!(rdyGHdAer7CtPHMe+ST;vccBJyWAGO-g_OsVoF>&M)%?j zfk|u_5;m|+};?$eunWs54y@EiwJScE1^=2ue1y{~Y< z7ph{v4BjO5%ES9W@@;IO3C_A?B3Wmohaop`h$`o0YQSYOK|(>y)^)V3;Yi`}H8A}n zq`WrFOAW5BxbP-4!;N2p+AkUO#YU;Z`9)*LS;Xin$_G;q0Y-)!jsG|B&O@S*L&XNxGn4G z2Gh>iu>Q#CpCrEQq{K*c+@_UWi6wCyOf=_|oy@xXvPWY4Z?~Pv_wpL8WYt&1Y??&t zrZ8RK3PrK)q$9gIwx<+d$i8B2QmfNE{=c*iB~)!Bl)b$L>g@b}_PpHQ-&xAJVPE03 zyDq4ai*rA$2fr^8!ZOUqj^HtQ5T)OQ4AwWU*+J}OEK~T`Bq-|=nln3l7g`YI~?it-Q%x&_77Ej9(gxXUql`x$q>$ zCr90FlLn0!lMl`|P&`bAn_y_soJF{ow$6&JzPCn_ll%sOr2AM4=j07$t1Vat*)T2S zkrDb?f6e#EJ9!Y@fvSUPb+}}mELYiLO;JqNh!xZ^H*4rPm`oAEmeYVUMPBq@gya9` z2d8JXQVT6bxF+sy-Z2s1aSD`4Zp}2tzO&zxxbHcQ-WpbO)>u>KZYs*A9=jKuwy@vE zP^B~GlZ5>VJ7D-EZ|k1r6_&t$*b?iVFAIL>aWEcdTTN_Ol{yKb%dI-`u$=6^_7Huw zDk*6Tb6XFAh>A zhOGEJOxn^AgNElARSrRc?fZu(b&;TM)sE{fDb)7G%Rk0b*+U(ss-}txU}SnSaq4Jn z2n0DDX&@*{N2yiSr$#*LLK|+U{@RvMJ+r$hyfcWX$@-L1m6nWMwrFCK1uh?0OG<