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 0000000..fdae8cb Binary files /dev/null and b/templates/ms/applications/Company.Project.AuthServer.Host/wwwroot/images/anonymous-user.png differ 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 0000000..44de167 Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/asus.jpg differ 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 0000000..08417c2 Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/beats.jpg differ diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/bluecat.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/bluecat.jpg new file mode 100644 index 0000000..794a734 Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/bluecat.jpg differ 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 0000000..63e31e9 Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/lego.jpg differ 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 0000000..eb6fb60 Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/nikon.jpg differ 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 0000000..4c5133c Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/noimage.jpg differ 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 0000000..6fefeec Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/oki.jpg differ 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 0000000..8808324 Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/playstation.jpg differ 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 0000000..e49660d Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/rampage.jpg differ diff --git a/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/sunny.jpg b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/sunny.jpg new file mode 100644 index 0000000..8efff5a Binary files /dev/null and b/templates/ms/applications/Company.Project.PublicWebSite.Host/wwwroot/product-images/sunny.jpg differ 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