Browse Source

Merge pull request #1067 from feijie999/dev

完善单体服务的支持
pull/1070/head
yx lin 2 years ago
committed by GitHub
parent
commit
b89febe9a4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      README.en.md
  2. 13
      README.md
  3. 3833
      aspnet-core/LINGYUN.MicroService.SingleProject.sln
  4. 2
      aspnet-core/framework/cli/LINGYUN.Abp.Cli/LINGYUN/Abp/Cli/Commands/CreateCommand.cs
  5. 41
      aspnet-core/framework/cli/LINGYUN.Abp.Cli/LINGYUN/Abp/Cli/Commands/LocalFileCreateProjectService.cs
  6. 3
      aspnet-core/framework/cli/LINGYUN.Abp.Cli/Properties/launchSettings.json
  7. 7
      aspnet-core/framework/cli/LINGYUN.Abp.Cli/README.zh-Hans.md
  8. 33
      aspnet-core/framework/cloud-aliyun/README.md
  9. 42
      aspnet-core/framework/cloud-tencent/README.md
  10. 59
      aspnet-core/framework/common/README.md
  11. 5
      aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/LY.MicroService.Applications.Single.DbMigrator.csproj
  12. 6
      aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/SingleDbMigratorModule.cs
  13. 228
      aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/appsettings.SqlServer.json
  14. 3
      aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/appsettings.json
  15. 5828
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/Migrations/20241218145610_AddNewMigration_20241218_225542.Designer.cs
  16. 183
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/Migrations/20241218145610_AddNewMigration_20241218_225542.cs
  17. 289
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/Migrations/SingleMigrationsDbContextModelSnapshot.cs
  18. 16
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer.csproj
  19. 59
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/README.en.md
  20. 59
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/README.md
  21. 35
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/SingleMigrationsDbContextFactory.cs
  22. 26
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/SingleMigrationsEntityFrameworkCoreSqlServerModule.cs
  23. 200
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/SingleDbMigrationService.cs
  24. 5
      aspnet-core/migrations/Migrate.ps1
  25. 5
      aspnet-core/migrations/MigrateEn.ps1
  26. 263
      aspnet-core/services/Directory.Packages.props
  27. 12
      aspnet-core/services/LY.AIO.Applications.Single/.config/dotnet-tools.json
  28. 2
      aspnet-core/services/LY.AIO.Applications.Single/.gitignore
  29. 89
      aspnet-core/services/LY.AIO.Applications.Single/Authentication/AbpCookieAuthenticationHandler.cs
  30. 38
      aspnet-core/services/LY.AIO.Applications.Single/BackgroundJobs/NotificationPublishJob.cs
  31. 22
      aspnet-core/services/LY.AIO.Applications.Single/BackgroundJobs/NotificationPublishJobArgs.cs
  32. 11
      aspnet-core/services/LY.AIO.Applications.Single/Controllers/HomeController.cs
  33. 70
      aspnet-core/services/LY.AIO.Applications.Single/Controllers/SettingMergeController.cs
  34. 45
      aspnet-core/services/LY.AIO.Applications.Single/Controllers/UserSettingMergeController.cs
  35. 19
      aspnet-core/services/LY.AIO.Applications.Single/Dockerfile
  36. 59
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/ChatMessageEventHandler.cs
  37. 470
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/NotificationEventHandler.cs
  38. 53
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/TenantSynchronizer.cs
  39. 30
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/UserCreateEventHandler.cs
  40. 112
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/WebhooksEventHandler.cs
  41. 58
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Local/UserCreateJoinIMEventHandler.cs
  42. 69
      aspnet-core/services/LY.AIO.Applications.Single/EventBus/Local/UserCreateSendWelcomeEventHandler.cs
  43. 19
      aspnet-core/services/LY.AIO.Applications.Single/IdentityResources/CustomIdentityResources.cs
  44. 272
      aspnet-core/services/LY.AIO.Applications.Single/LY.AIO.Applications.Single.csproj
  45. 935
      aspnet-core/services/LY.AIO.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs
  46. 394
      aspnet-core/services/LY.AIO.Applications.Single/MicroServiceApplicationsSingleModule.cs
  47. 67
      aspnet-core/services/LY.AIO.Applications.Single/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs
  48. 10
      aspnet-core/services/LY.AIO.Applications.Single/MultiTenancy/ITenantConfigurationCache.cs
  49. 59
      aspnet-core/services/LY.AIO.Applications.Single/MultiTenancy/TenantConfigurationCache.cs
  50. 19
      aspnet-core/services/LY.AIO.Applications.Single/MultiTenancy/TenantConfigurationCacheItem.cs
  51. 103
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml
  52. 28
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js
  53. 17
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirm.cshtml
  54. 72
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirm.cshtml.cs
  55. 13
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirmConfirmation.cshtml
  56. 22
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirmConfirmation.cshtml.cs
  57. 26
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendCode.cshtml
  58. 125
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendCode.cshtml.cs
  59. 16
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendEmailConfirm.cshtml
  60. 73
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendEmailConfirm.cshtml.cs
  61. 63
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/TwoFactorSupportedLoginModel.cs
  62. 4
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/UseRecoveryCode.cshtml
  63. 11
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/UseRecoveryCode.cshtml.cs
  64. 26
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyAuthenticatorCode.cshtml
  65. 59
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyAuthenticatorCode.cshtml.cs
  66. 29
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyCode.cshtml
  67. 90
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyCode.cshtml.cs
  68. 36
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Index.cshtml
  69. 11
      aspnet-core/services/LY.AIO.Applications.Single/Pages/Index.cshtml.cs
  70. 4
      aspnet-core/services/LY.AIO.Applications.Single/Pages/_ViewImports.cshtml
  71. 82
      aspnet-core/services/LY.AIO.Applications.Single/Program.cs
  72. 30
      aspnet-core/services/LY.AIO.Applications.Single/Properties/launchSettings.json
  73. 35
      aspnet-core/services/LY.AIO.Applications.Single/TenantHeaderParamter.cs
  74. 21
      aspnet-core/services/LY.AIO.Applications.Single/WeChat/Official/Messages/TextMessageReplyContributor.cs
  75. 21
      aspnet-core/services/LY.AIO.Applications.Single/WeChat/Official/Messages/UserSubscribeEventContributor.cs
  76. 24
      aspnet-core/services/LY.AIO.Applications.Single/WeChat/Work/Messages/TextMessageReplyContributor.cs
  77. 249
      aspnet-core/services/LY.AIO.Applications.Single/appsettings.Development.json
  78. 89
      aspnet-core/services/LY.AIO.Applications.Single/appsettings.json
  79. 10
      aspnet-core/services/LY.AIO.Applications.Single/gulpfile.js
  80. 30
      aspnet-core/templates/aio/PackageName.CompanyName.ProjectName.AIO.csproj
  81. 115
      aspnet-core/templates/aio/content/.template.config/template.json
  82. 0
      aspnet-core/templates/aio/content/.template.config/template.zh-Hans.json
  83. 26
      aspnet-core/templates/aio/content/Directory.Build.props
  84. 537
      aspnet-core/templates/aio/content/Directory.Packages.props
  85. 0
      aspnet-core/templates/aio/content/NuGet.Config
  86. 135
      aspnet-core/templates/aio/content/README.md
  87. 135
      aspnet-core/templates/aio/content/README.zh-CN.md
  88. 74
      aspnet-core/templates/aio/content/common.props
  89. 0
      aspnet-core/templates/aio/content/configureawait.props
  90. 12
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/.config/dotnet-tools.json
  91. 2
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/.gitignore
  92. 89
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Authentication/AbpCookieAuthenticationHandler.cs
  93. 38
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/BackgroundJobs/NotificationPublishJob.cs
  94. 22
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/BackgroundJobs/NotificationPublishJobArgs.cs
  95. 11
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Controllers/HomeController.cs
  96. 70
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Controllers/SettingMergeController.cs
  97. 45
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Controllers/UserSettingMergeController.cs
  98. 19
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Dockerfile
  99. 59
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/EventBus/Distributed/ChatMessageEventHandler.cs
  100. 470
      aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/EventBus/Distributed/NotificationEventHandler.cs

13
README.en.md

@ -10,6 +10,19 @@ This is a [vue-vben-admin](https://github.com/anncwb/vue-vben-admin) -based Abp
[![Build](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml/badge.svg)](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml) [![Build](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml/badge.svg)](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml)
## Deployment Options
### Monolithic Service Deployment
If you don't need a microservices architecture, you can choose the monolithic service deployment option. Monolithic services are characterized by simple deployment and easy maintenance.
- [Monolithic Service Startup Guide](./docs/startup-aio-readme.en.md)
- [单体服务启动说明](./docs/startup-aio-readme.md)
### Microservices Deployment
If you need higher scalability and a more flexible service architecture, you can choose the microservices deployment option.
## Quick Start ## Quick Start
### 0、Configurate hosts ### 0、Configurate hosts

13
README.md

@ -1,4 +1,3 @@
[English](./README.en.md) | 简体中文 [English](./README.en.md) | 简体中文
[更新说明](./RELEASE.md) 更新说明 [更新说明](./RELEASE.md) 更新说明
@ -11,6 +10,18 @@
[![Build](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml/badge.svg)](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml) [![Build](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml/badge.svg)](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml)
## 部署方案
### 单体服务部署
如果您不需要微服务架构,可以选择单体服务部署方案。单体服务具有部署简单、维护方便的特点。
- [单体服务启动说明](./docs/startup-aio-readme.md)
- [Monolithic Service Startup Guide](./docs/startup-aio-readme.en.md)
### 微服务部署
如果您需要更高的可扩展性和更灵活的服务架构,可以选择微服务部署方案。
## 快速搭建微服务启动项目 ## 快速搭建微服务启动项目

3833
aspnet-core/LINGYUN.MicroService.SingleProject.sln

File diff suppressed because it is too large

2
aspnet-core/framework/cli/LINGYUN.Abp.Cli/LINGYUN/Abp/Cli/Commands/CreateCommand.cs

@ -196,7 +196,7 @@ namespace LINGYUN.Abp.Cli.Commands
sb.AppendLine("Options:"); sb.AppendLine("Options:");
sb.AppendLine(""); sb.AppendLine("");
sb.AppendLine("-pk|--package <package-name> (default: app)"); sb.AppendLine("-pk|--package <package-name> (default: app)");
sb.AppendLine("-t|--template <template-name> (default: lam)"); sb.AppendLine("-t|--template <template-name> (default: lam), optional:lam、laa");
sb.AppendLine("-d|--database-provider <database-provider> (if supported by the template)"); sb.AppendLine("-d|--database-provider <database-provider> (if supported by the template)");
sb.AppendLine("-o|--output-folder <output-folder> (default: current folder)"); sb.AppendLine("-o|--output-folder <output-folder> (default: current folder)");
sb.AppendLine("-v|--version <version> (default: latest version)"); sb.AppendLine("-v|--version <version> (default: latest version)");

41
aspnet-core/framework/cli/LINGYUN.Abp.Cli/LINGYUN/Abp/Cli/Commands/LocalFileCreateProjectService.cs

@ -87,7 +87,7 @@ namespace LINGYUN.Abp.Cli.Commands
projectFiles, projectFiles,
createArgs.PackageName, createArgs.PackageName,
createArgs.SolutionName.CompanyName, createArgs.SolutionName.CompanyName,
createArgs.DatabaseManagementSystem); dbm);
Logger.LogInformation("Rewrite appsettings.json."); Logger.LogInformation("Rewrite appsettings.json.");
await TryReplaceAppSettingsWithProjectFile( await TryReplaceAppSettingsWithProjectFile(
@ -96,6 +96,13 @@ namespace LINGYUN.Abp.Cli.Commands
createArgs.SolutionName.CompanyName, createArgs.SolutionName.CompanyName,
createArgs.SolutionName.ProjectName, createArgs.SolutionName.ProjectName,
createArgs.ConnectionString); createArgs.ConnectionString);
// Logger.LogInformation("Rewrite scripts.");
// await TryReplaceScriptProjectFile(
// projectFiles,
// createArgs.PackageName,
// createArgs.SolutionName.CompanyName,
// dbm);
Logger.LogInformation("Rewrite application url."); Logger.LogInformation("Rewrite application url.");
await TryReplaceApplicationUrlWithProjectFile( await TryReplaceApplicationUrlWithProjectFile(
@ -112,7 +119,8 @@ namespace LINGYUN.Abp.Cli.Commands
await TryReplacePackageAndCompanyNameWithProjectFolder( await TryReplacePackageAndCompanyNameWithProjectFolder(
projectFiles, projectFiles,
createArgs.PackageName, createArgs.PackageName,
createArgs.SolutionName.CompanyName); createArgs.SolutionName.CompanyName,
dbm);
Logger.LogInformation($"'{createArgs.SolutionName.ProjectName}' has been successfully created to '{createArgs.OutputFolder}'"); Logger.LogInformation($"'{createArgs.SolutionName.ProjectName}' has been successfully created to '{createArgs.OutputFolder}'");
} }
@ -203,32 +211,53 @@ namespace LINGYUN.Abp.Cli.Commands
await ReplaceFileTextAsync(projectFile, defaultConnectionString, connectionString); await ReplaceFileTextAsync(projectFile, defaultConnectionString, connectionString);
} }
} }
//
// protected async virtual Task TryReplaceScriptProjectFile(
// List<FindFile> projectFiles,
// string packageName,
// string companyName,
// string dbm = "MySQL")
// {
// var canReplaceFiles = projectFiles.Where(f => !f.IsFolder && f.Name.EndsWith(".bat", StringComparison.OrdinalIgnoreCase) ||
// f.Name.EndsWith(".sh", StringComparison.OrdinalIgnoreCase) ||
// f.Name.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase));
// foreach (var projectFile in canReplaceFiles)
// {
// await ReplaceFileTextAsync(projectFile, "PackageName", packageName);
// await ReplaceFileTextAsync(projectFile, "CompanyName", companyName);
//
// await ReplaceFileTextAsync(projectFile, "DatabaseManagementName", dbm);
// }
// }
protected async virtual Task TryReplacePackageAndCompanyNameWithProjectFile( protected async virtual Task TryReplacePackageAndCompanyNameWithProjectFile(
List<FindFile> projectFiles, List<FindFile> projectFiles,
string packageName, string packageName,
string companyName, string companyName,
DatabaseManagementSystem database = DatabaseManagementSystem.NotSpecified) string dbm = "MySQL")
{ {
var canReplaceFiles = projectFiles.Where(f => !f.IsFolder && !f.Name.Contains("appsettings")); var canReplaceFiles = projectFiles.Where(f => !f.IsFolder && !f.Name.Contains("appsettings"));
foreach (var projectFile in canReplaceFiles) foreach (var projectFile in canReplaceFiles)
{ {
await ReplaceFileTextAsync(projectFile, "PackageName", packageName); await ReplaceFileTextAsync(projectFile, "PackageName", packageName);
await ReplaceFileTextAsync(projectFile, "CompanyName", companyName); await ReplaceFileTextAsync(projectFile, "CompanyName", companyName);
await ReplaceFileTextAsync(projectFile, "DatabaseManagementName", dbm);
} }
} }
protected virtual Task TryReplacePackageAndCompanyNameWithProjectFolder( protected virtual Task TryReplacePackageAndCompanyNameWithProjectFolder(
List<FindFile> projectFiles, List<FindFile> projectFiles,
string packageName, string packageName,
string companyName) string companyName,
string dbm = "MySQL")
{ {
var canReplaceFiles = projectFiles var canReplaceFiles = projectFiles
.OrderByDescending(f => f.Depth) .OrderByDescending(f => f.Depth)
.OrderByDescending(f => !f.IsFolder); .OrderByDescending(f => !f.IsFolder);
foreach (var projectFile in canReplaceFiles) foreach (var projectFile in canReplaceFiles)
{ {
var replaceFileName = projectFile.Name.Replace("PackageName", packageName).Replace("CompanyName", companyName); var replaceFileName = projectFile.Name.Replace("PackageName", packageName).Replace("CompanyName", companyName).Replace("DatabaseManagementName", dbm);
if (File.Exists(projectFile.Name)) if (File.Exists(projectFile.Name))
{ {
@ -238,7 +267,7 @@ namespace LINGYUN.Abp.Cli.Commands
} }
var canReplacePaths = projectFiles var canReplacePaths = projectFiles
.Where(projectFile => projectFile.Name.Contains("PackageName") || projectFile.Name.Contains("CompanyName")) .Where(projectFile => projectFile.Name.Contains("PackageName") || projectFile.Name.Contains("CompanyName") || projectFile.Name.Contains("DatabaseManagementName"))
.OrderByDescending(f => f.Depth) .OrderByDescending(f => f.Depth)
.OrderByDescending(f => f.IsFolder); .OrderByDescending(f => f.IsFolder);
foreach (var projectFile in canReplacePaths) foreach (var projectFile in canReplacePaths)

3
aspnet-core/framework/cli/LINGYUN.Abp.Cli/Properties/launchSettings.json

@ -3,7 +3,8 @@
"LINGYUN.Abp.Cli": { "LINGYUN.Abp.Cli": {
"commandName": "Project", "commandName": "Project",
//"commandLineArgs": "generate-view -t vben-view -m auditing -o D:\\Projects\\Development\\view-script -url http://127.0.0.1:30000/" //"commandLineArgs": "generate-view -t vben-view -m auditing -o D:\\Projects\\Development\\view-script -url http://127.0.0.1:30000/"
"commandLineArgs": "generate-proxy -t flutter -asp rest-service -u http://127.0.0.1:30000 -m notifications -o D:\\Projects\\Development\\flutter-script -skip-cli-version-check" // "commandLineArgs": "generate-proxy -t flutter -asp rest-service -u http://127.0.0.1:30000 -m notifications -o D:\\Projects\\Development\\flutter-script -skip-cli-version-check"
"commandLineArgs": "create MyCompanyName.MyProjectName -t lam -pk MyPackageName -o /Users/feijie/Projects/Tests --dbms MySql --cs \"Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None\" --no-random-port"
} }
} }
} }

7
aspnet-core/framework/cli/LINGYUN.Abp.Cli/README.zh-Hans.md

@ -8,6 +8,13 @@
dotnet tool install --global LINGYUN.Abp.Cli dotnet tool install --global LINGYUN.Abp.Cli
``` ```
打包项目为LINGYUN.Abp.Cli.8.3.0.nupkg
```shell
dotnet pack -o ./nupkg
dotnet tool install -g LINGYUN.Abp.Cli --version 8.3.0 --add-source ./nupkg
```
## 使用方法 ## 使用方法
```shell ```shell

33
aspnet-core/framework/cloud-aliyun/README.md

@ -0,0 +1,33 @@
# LINGYUN.Abp.Aliyun 模块概述
## 简介
LINGYUN.Abp.Aliyun 模块集成了阿里云的 SDK,提供了对阿里云服务的全面支持,包括认证、短信服务和对象存储等功能。
## 包含的项目列表
- **LINGYUN.Abp.Aliyun**
- **LINGYUN.Abp.Aliyun.Features**
- **LINGYUN.Abp.Aliyun.SettingManagement**
## 每个项目的主要功能概述
### LINGYUN.Abp.Aliyun
- 提供阿里云服务的基础 SDK 集成。
- 支持阿里云 RAM 认证和 STS Token 访问。
- 支持短信服务和对象存储。
- 提供分布式缓存支持。
### LINGYUN.Abp.Aliyun.Features
- 提供阿里云服务的功能定义和管理。
- 支持启用/禁用阿里云服务功能。
- 与 ABP 功能管理系统集成。
### LINGYUN.Abp.Aliyun.SettingManagement
- 提供阿里云服务配置的查询接口。
- 通过 API 接口获取阿里云配置信息。
- 与 ABP 设置管理系统集成。
## 模块的整体用途和重要性
该模块为开发者提供了与阿里云服务的无缝集成,简化了云服务的使用和管理,提升了应用程序的灵活性和可扩展性。
## 如何使用或集成该模块
在项目中引用相应的模块,并根据需要配置阿里云的相关参数。确保与 ABP 框架的其他模块配合使用,以实现最佳效果。

42
aspnet-core/framework/cloud-tencent/README.md

@ -0,0 +1,42 @@
# LINGYUN.Abp.Tencent 模块概述
## 简介
LINGYUN.Abp.Tencent 模块集成了腾讯云的各项服务,提供了对腾讯云服务的全面支持,包括对象存储、短信服务、QQ 互联和语音合成等功能。
## 包含的项目列表
- **LINGYUN.Abp.Tencent**
- **LINGYUN.Abp.BlobStoring.Tencent**
- **LINGYUN.Abp.Sms.Tencent**
- **LINGYUN.Abp.Tencent.QQ**
- **LINGYUN.Abp.Tencent.SettingManagement**
- **LINGYUN.Abp.Tencent.TTS**
## 每个项目的主要功能概述
### LINGYUN.Abp.Tencent
- 提供腾讯云 SDK 客户端工厂,支持动态创建腾讯云各项服务的客户端。
- 支持多租户配置和多语言本地化。
- 提供统一的腾讯云服务配置管理。
### LINGYUN.Abp.BlobStoring.Tencent
- 支持腾讯云对象存储服务,自动创建存储桶。
- 支持多区域配置和文件大小限制。
### LINGYUN.Abp.Sms.Tencent
- 支持腾讯云短信服务的发送功能,支持多手机号批量发送。
- 内置错误处理和日志记录。
### LINGYUN.Abp.Tencent.QQ
- 支持 QQ 互联快速登录,支持多租户配置。
### LINGYUN.Abp.Tencent.SettingManagement
- 提供腾讯云服务的配置管理界面,支持全局和租户级别的配置管理。
### LINGYUN.Abp.Tencent.TTS
- 支持腾讯云语音合成服务,提供 TTS 客户端工厂。
## 模块的整体用途和重要性
该模块为开发者提供了与腾讯云服务的无缝集成,简化了云服务的使用和管理,提升了应用程序的灵活性和可扩展性。
## 如何使用或集成该模块
在项目中引用相应的模块,并根据需要配置腾讯云的相关参数。确保与 ABP 框架的其他模块配合使用,以实现最佳效果。

59
aspnet-core/framework/common/README.md

@ -0,0 +1,59 @@
# common 模块概述
## 模块简介
`common`模块是ABP框架的基础模块,提供了一系列通用功能和服务,旨在支持各种应用程序的开发和扩展。该模块包含多个子模块,每个子模块实现了特定的功能,帮助开发者快速构建高效的应用程序。
## 包含的项目列表
1. **LINGYUN.Abp.Aliyun.Authorization**
- 提供阿里云基础认证功能,支持AppKeyId和AccessKeySecret的配置。
2. **LINGYUN.Abp.AspNetCore.HttpOverrides**
- 实现HTTP传输标头的重写,支持获取反向代理中的真实客户地址。
3. **LINGYUN.Abp.AspNetCore.Mvc.Client**
- 提供可配置的用户配置缓存时间,支持多租户接口。
4. **LINGYUN.Abp.BackgroundJobs.Hangfire**
- 基于Hangfire实现的后台作业模块,支持即时、延迟和周期性任务。
5. **LINGYUN.Abp.ExceptionHandling**
- 提供统一的异常处理和通知机制,支持自定义异常处理程序。
6. **LINGYUN.Abp.Location**
- 提供地理编码、反向地理编码和IP地理位置解析功能。
7. **LINGYUN.Abp.IdGenerator**
- 实现分布式唯一ID生成器,支持雪花算法。
8. **LINGYUN.Abp.Wrapper**
- 统一包装API返回结果和异常处理。
## 每个项目的主要功能概述
- **阿里云认证模块**: 提供阿里云的认证功能,简化了对阿里云服务的访问。
- **HTTP重写模块**: 处理HTTP请求中的标头,确保获取真实的客户端地址。
- **MVC客户端模块**: 提供用户配置缓存,支持多租户架构。
- **后台作业模块**: 支持任务的调度和执行,确保后台任务的可靠性。
- **异常处理模块**: 处理应用中的异常,提供统一的通知机制。
- **位置服务模块**: 提供地理位置相关的功能,支持地址与坐标之间的转换。
- **ID生成模块**: 生成分布式唯一ID,确保在高并发环境下的唯一性。
- **包装器模块**: 统一处理API的返回结果和异常,提升API的可用性。
## 模块的整体用途和重要性
`common`模块为ABP框架提供了基础设施,支持开发者在构建应用时快速集成常用功能,减少重复工作,提高开发效率。通过这些模块,开发者能够更专注于业务逻辑的实现,而无需担心底层的实现细节。
## 如何使用或集成该模块的简要说明
在项目中使用`common`模块时,只需在模块类中添加相应的依赖项,并在`ConfigureServices`方法中进行必要的配置。例如:
```csharp
[DependsOn(typeof(LINGYUN.Abp.Aliyun.Authorization))]
public class YourProjectModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// 配置服务
}
}
```
## 提示
本项目中的README是由AI模型分析代码逻辑后自动生成的,如有误,请提issues或PR。

5
aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/LY.MicroService.Applications.Single.DbMigrator.csproj

@ -35,6 +35,10 @@
<Content Include="appsettings.PostgreSql.json"> <Content Include="appsettings.PostgreSql.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<None Remove="appsettings.json" />
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -46,6 +50,7 @@
<ProjectReference Include="..\..\modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin\LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj" /> <ProjectReference Include="..\..\modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin\LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj" />
<ProjectReference Include="..\LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql\LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql.csproj" /> <ProjectReference Include="..\LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql\LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql.csproj" />
<ProjectReference Include="..\LY.MicroService.Applications.Single.EntityFrameworkCore.MySql\LY.MicroService.Applications.Single.EntityFrameworkCore.Mysql.csproj" /> <ProjectReference Include="..\LY.MicroService.Applications.Single.EntityFrameworkCore.MySql\LY.MicroService.Applications.Single.EntityFrameworkCore.Mysql.csproj" />
<ProjectReference Include="..\LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer\LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

6
aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/SingleDbMigratorModule.cs

@ -1,7 +1,7 @@
using LINGYUN.Abp.UI.Navigation.VueVbenAdmin; using LINGYUN.Abp.UI.Navigation.VueVbenAdmin;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql; using LY.MicroService.Applications.Single.EntityFrameworkCore.PostgreSql;
// using LY.MicroService.Applications.Single.EntityFrameworkCore.MySql; using LY.MicroService.Applications.Single.EntityFrameworkCore.MySql;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -9,8 +9,8 @@ namespace LY.MicroService.Applications.Single.DbMigrator;
[DependsOn( [DependsOn(
typeof(AbpUINavigationVueVbenAdminModule), typeof(AbpUINavigationVueVbenAdminModule),
typeof(SingleMigrationsEntityFrameworkCorePostgreSqlModule), // typeof(SingleMigrationsEntityFrameworkCorePostgreSqlModule),
// typeof(SingleMigrationsEntityFrameworkCoreMySqlModule), typeof(SingleMigrationsEntityFrameworkCoreMySqlModule),
typeof(AbpAutofacModule) typeof(AbpAutofacModule)
)] )]
public partial class SingleDbMigratorModule : AbpModule public partial class SingleDbMigratorModule : AbpModule

228
aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/appsettings.SqlServer.json

@ -0,0 +1,228 @@
{
"App": {
"ShowPii": true,
"SelfUrl": "http://127.0.0.1:30001/",
"CorsOrigins": "http://127.0.0.1:3100,http://127.0.0.1:30001",
"Urls": {
"Applications": {
"MVC": {
"RootUrl": "http://127.0.0.1:30001/",
"Urls": {
"Abp.Account.EmailConfirm": "Account/EmailConfirm",
"Abp.Account.EmailVerifyLogin": "Account/VerifyCode"
}
},
"STS": {
"RootUrl": "http://127.0.0.1:30001/"
},
"VueVbenAdmin": {
"RootUrl": "http://127.0.0.1:3100",
"Urls": {
"Abp.Account.EmailConfirm": "account/email-confirm"
}
}
}
}
},
"Auditing": {
"AllEntitiesSelector": true
},
"DistributedCache": {
"HideErrors": true,
"KeyPrefix": "LINGYUN.Abp.Application",
"GlobalCacheEntryOptions": {
"SlidingExpiration": "30:00:00",
"AbsoluteExpirationRelativeToNow": "60:00:00"
}
},
"ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=Platform-V70;User Id=sa;Password=yourStrong(!)Password;TrustServerCertificate=True"
},
"DistributedLock": {
"IsEnabled": true,
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=14"
}
},
"Elsa": {
"Features": {
"DefaultPersistence": {
"Enabled": true,
"ConnectionStringIdentifier": "Default",
"EntityFrameworkCore": {
"SqlServer": {
"Enabled": true
}
}
},
"Console": true,
"Http": true,
"Email": true,
"TemporalQuartz": true,
"JavaScriptActivities": true,
"UserTask": true,
"Conductor": true,
"Telnyx": true,
"BlobStoring": true,
"Emailing": true,
"Notification": true,
"Sms": true,
"IM": true,
"PublishWebhook": true,
"Webhooks": {
"Enabled": true,
"ConnectionStringIdentifier": "Default",
"EntityFrameworkCore": {
"SqlServer": {
"Enabled": true
}
}
},
"WorkflowSettings": {
"Enabled": true,
"ConnectionStringIdentifier": "Default",
"EntityFrameworkCore": {
"SqlServer": {
"Enabled": true
}
}
}
},
"Server": {
"BaseUrl": "http://127.0.0.1:30000"
}
},
"Quartz": {
"UsePersistentStore": false,
"Properties": {
"quartz.jobStore.dataSource": "tkm",
"quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
"quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz",
"quartz.dataSource.tkm.connectionString": "Server=127.0.0.1;Database=Platform-V70;User Id=sa;Password=yourStrong(!)Password;",
"quartz.dataSource.tkm.provider": "SqlServer",
"quartz.jobStore.clustered": "true",
"quartz.serializer.type": "json",
"quartz.dataSource.tkm.connectionStringName": "TaskManagement"
}
},
"Redis": {
"IsEnabled": true,
"Configuration": "127.0.0.1,defaultDatabase=15",
"InstanceName": "LINGYUN.Abp.Application"
},
"AuthServer": {
"UseOpenIddict": true,
"Authority": "http://127.0.0.1:30001/",
"ApiName": "lingyun-abp-application",
"SwaggerClientId": "InternalServiceClient",
"SwaggerClientSecret": "1q2w3E*"
},
"IdentityServer": {
"Clients": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:3100/"
},
"InternalService": {
"ClientId": "InternalServiceClient"
}
}
},
"OpenIddict": {
"Applications": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:3100/"
},
"InternalService": {
"ClientId": "InternalServiceClient"
}
},
"Lifetime": {
"AuthorizationCode": "00:05:00",
"AccessToken": "14:00:00",
"DeviceCode": "00:10:00",
"IdentityToken": "00:20:00",
"RefreshToken": "14:00:00",
"RefreshTokenReuseLeeway": "00:00:30",
"UserCode": "00:10:00"
}
},
"Identity": {
"Password": {
"RequiredLength": 6,
"RequiredUniqueChars": 0,
"RequireNonAlphanumeric": false,
"RequireLowercase": false,
"RequireUppercase": false,
"RequireDigit": false
},
"Lockout": {
"AllowedForNewUsers": false,
"LockoutDuration": 5,
"MaxFailedAccessAttempts": 5
},
"SignIn": {
"RequireConfirmedEmail": false,
"RequireConfirmedPhoneNumber": false
}
},
"FeatureManagement": {
"IsDynamicStoreEnabled": true
},
"SettingManagement": {
"IsDynamicStoreEnabled": true
},
"PermissionManagement": {
"IsDynamicStoreEnabled": true
},
"TextTemplating": {
"IsDynamicStoreEnabled": true
},
"WebhooksManagement": {
"IsDynamicStoreEnabled": true
},
"Logging": {
"Serilog": {
"Elasticsearch": {
"IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}"
}
}
},
"AuditLogging": {
"Elasticsearch": {
"IndexPrefix": "abp.dev.auditing"
}
},
"Elasticsearch": {
"NodeUris": "http://127.0.0.1:9200"
},
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"System": "Warning",
"Microsoft": "Warning",
"DotNetCore": "Debug"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"restrictedToMinimumLevel": "Debug",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "http://127.0.0.1:9200",
"indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}",
"autoRegisterTemplate": true,
"autoRegisterTemplateVersion": "ESv7"
}
}
]
}
}

3
aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/appsettings.json

@ -3,7 +3,8 @@
"Kind": "Local" "Kind": "Local"
}, },
"ConnectionStrings": { "ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None" "Default": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None"//MySql
// "Default": "Host=127.0.0.1;Database=Platform-V70;Username=postgres;Password=123456;SslMode=Prefer"//PostgreSql
}, },
"StringEncryption": { "StringEncryption": {
"DefaultPassPhrase": "s46c5q55nxpeS8Ra", "DefaultPassPhrase": "s46c5q55nxpeS8Ra",

5828
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/Migrations/20241218145610_AddNewMigration_20241218_225542.Designer.cs

File diff suppressed because it is too large

183
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/Migrations/20241218145610_AddNewMigration_20241218_225542.cs

@ -0,0 +1,183 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.MySql.Migrations
{
/// <inheritdoc />
public partial class AddNewMigration_20241218_225542 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AbpAuthEntitites",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TypeFullName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
IsAuditEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
ExtraProperties = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_AbpAuthEntitites", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AbpAuthEntityProperties",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TypeFullName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ValueRange = table.Column<string>(type: "varchar(512)", maxLength: 512, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
TypeInfoId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_AbpAuthEntityProperties", x => x.Id);
table.ForeignKey(
name: "FK_AbpAuthEntityProperties_AbpAuthEntitites_TypeInfoId",
column: x => x.TypeInfoId,
principalTable: "AbpAuthEntitites",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AbpAuthOrganizationUnitEntityRules",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
OrgId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
OrgCode = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ExtraProperties = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
Operation = table.Column<int>(type: "int", nullable: false),
FilterGroup = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EntityTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
EntityTypeFullName = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
AllowProperties = table.Column<string>(type: "varchar(512)", maxLength: 512, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_AbpAuthOrganizationUnitEntityRules", x => x.Id);
table.ForeignKey(
name: "FK_AbpAuthOrganizationUnitEntityRules_AbpAuthEntitites_EntityTy~",
column: x => x.EntityTypeId,
principalTable: "AbpAuthEntitites",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AbpAuthRoleEntityRules",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
RoleId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
RoleName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ExtraProperties = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
Operation = table.Column<int>(type: "int", nullable: false),
FilterGroup = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EntityTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
EntityTypeFullName = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
AllowProperties = table.Column<string>(type: "varchar(512)", maxLength: 512, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_AbpAuthRoleEntityRules", x => x.Id);
table.ForeignKey(
name: "FK_AbpAuthRoleEntityRules_AbpAuthEntitites_EntityTypeId",
column: x => x.EntityTypeId,
principalTable: "AbpAuthEntitites",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_AbpAuthEntitites_TypeFullName",
table: "AbpAuthEntitites",
column: "TypeFullName");
migrationBuilder.CreateIndex(
name: "IX_AbpAuthEntityProperties_TypeInfoId_TypeFullName",
table: "AbpAuthEntityProperties",
columns: new[] { "TypeInfoId", "TypeFullName" });
migrationBuilder.CreateIndex(
name: "IX_AbpAuthOrganizationUnitEntityRules_EntityTypeId",
table: "AbpAuthOrganizationUnitEntityRules",
column: "EntityTypeId");
migrationBuilder.CreateIndex(
name: "IX_AbpAuthRoleEntityRules_EntityTypeId",
table: "AbpAuthRoleEntityRules",
column: "EntityTypeId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AbpAuthEntityProperties");
migrationBuilder.DropTable(
name: "AbpAuthOrganizationUnitEntityRules");
migrationBuilder.DropTable(
name: "AbpAuthRoleEntityRules");
migrationBuilder.DropTable(
name: "AbpAuthEntitites");
}
}
}

289
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/Migrations/SingleMigrationsDbContextModelSnapshot.cs

@ -24,6 +24,257 @@ namespace LY.MicroService.Applications.Single.EntityFrameworkCore.MySql.Migratio
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128)")
.HasColumnName("DisplayName");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("Name");
b.Property<string>("TypeFullName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("varchar(256)")
.HasColumnName("TypeFullName");
b.Property<Guid>("TypeInfoId")
.HasColumnType("char(36)");
b.Property<string>("ValueRange")
.HasMaxLength(512)
.HasColumnType("varchar(512)")
.HasColumnName("ValueRange");
b.HasKey("Id");
b.HasIndex("TypeInfoId", "TypeFullName");
b.ToTable("AbpAuthEntityProperties", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128)")
.HasColumnName("DisplayName");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsAuditEnabled")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("Name");
b.Property<string>("TypeFullName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("varchar(256)")
.HasColumnName("TypeFullName");
b.HasKey("Id");
b.HasIndex("TypeFullName");
b.ToTable("AbpAuthEntitites", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("AllowProperties")
.HasMaxLength(512)
.HasColumnType("varchar(512)")
.HasColumnName("AllowProperties");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("EntityTypeFullName")
.HasColumnType("longtext");
b.Property<Guid>("EntityTypeId")
.HasColumnType("char(36)");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<string>("FilterGroup")
.HasColumnType("longtext")
.HasColumnName("FilterGroup");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<int>("Operation")
.HasColumnType("int");
b.Property<string>("OrgCode")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128)")
.HasColumnName("OrgCode");
b.Property<Guid>("OrgId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityTypeId");
b.ToTable("AbpAuthOrganizationUnitEntityRules", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("AllowProperties")
.HasMaxLength(512)
.HasColumnType("varchar(512)")
.HasColumnName("AllowProperties");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("EntityTypeFullName")
.HasColumnType("longtext");
b.Property<Guid>("EntityTypeId")
.HasColumnType("char(36)");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<string>("FilterGroup")
.HasColumnType("longtext")
.HasColumnName("FilterGroup");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<int>("Operation")
.HasColumnType("int");
b.Property<Guid>("RoleId")
.HasColumnType("char(36)");
b.Property<string>("RoleName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("varchar(256)")
.HasColumnName("RoleName");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityTypeId");
b.ToTable("AbpAuthRoleEntityRules", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.Demo.Authors.Author", b => modelBuilder.Entity("LINGYUN.Abp.Demo.Authors.Author", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -5254,6 +5505,39 @@ namespace LY.MicroService.Applications.Single.EntityFrameworkCore.MySql.Migratio
b.ToTable("AbpSettingDefinitions", (string)null); b.ToTable("AbpSettingDefinitions", (string)null);
}); });
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b =>
{
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "TypeInfo")
.WithMany("Properties")
.HasForeignKey("TypeInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("TypeInfo");
});
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b =>
{
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo")
.WithMany()
.HasForeignKey("EntityTypeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("EntityTypeInfo");
});
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b =>
{
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo")
.WithMany()
.HasForeignKey("EntityTypeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("EntityTypeInfo");
});
modelBuilder.Entity("LINGYUN.Abp.Demo.Books.Book", b => modelBuilder.Entity("LINGYUN.Abp.Demo.Books.Book", b =>
{ {
b.HasOne("LINGYUN.Abp.Demo.Authors.Author", null) b.HasOne("LINGYUN.Abp.Demo.Authors.Author", null)
@ -5616,6 +5900,11 @@ namespace LY.MicroService.Applications.Single.EntityFrameworkCore.MySql.Migratio
.HasForeignKey("AuthorizationId"); .HasForeignKey("AuthorizationId");
}); });
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b =>
{
b.Navigation("Properties");
});
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b =>
{ {
b.Navigation("ConnectionStrings"); b.Navigation("ConnectionStrings");

16
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Volo.Abp.EntityFrameworkCore.SqlServer" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\elsa\LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer\LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer.csproj" />
<ProjectReference Include="..\LY.MicroService.Applications.Single.EntityFrameworkCore\LY.MicroService.Applications.Single.EntityFrameworkCore.csproj" />
</ItemGroup>
</Project>

59
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/README.en.md

@ -0,0 +1,59 @@
# SQL Server Database Migration Guide
This guide will help you manage SQL Server database migrations using the migration scripts.
## Prerequisites
1. Ensure .NET Core SDK is installed
2. Ensure Entity Framework Core tools are installed
```powershell
dotnet tool install --global dotnet-ef
```
3. Ensure SQL Server connection string is properly configured
## Usage Instructions
### 1. Create New Migration
1. Run the migration script in the `aspnet-core/migrations` directory:
```powershell
# Use English version
.\MigrateEn.ps1
# Or use Chinese version
.\Migrate.ps1
```
2. Select SQL Server database context from the menu:
```
[3] LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer
```
3. Enter migration name (optional):
- Press Enter to use default name: `AddNewMigration_yyyyMMdd_HHmmss`
- Or enter custom name, e.g.: `AddNewFeature`
### 2. Generate SQL Script
After creating the migration, the script will ask if you want to generate SQL script:
1. Choose whether to generate SQL script (Y/N)
2. If Y is selected, following options will be available:
- `[A]` - Generate SQL script for all migrations
- `[L]` - Generate SQL script for latest migration only
- `[0-9]` - Generate from specified migration version
Generated SQL scripts will be saved in:
```
aspnet-core/InitSql/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/
```
### 3. Apply Migration
Generated SQL scripts can be applied to database through:
1. Using SQL Server Management Studio or other SQL Server client tools to execute SQL script
2. Or using command line:
```bash
sqlcmd -S your_server -d your_database -i your_script.sql
```

59
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/README.md

@ -0,0 +1,59 @@
# SQL Server 数据库迁移指南
本指南将帮助您使用迁移脚本来管理 SQL Server 数据库的迁移操作。
## 前置条件
1. 确保已安装 .NET Core SDK
2. 确保已安装 Entity Framework Core 工具
```powershell
dotnet tool install --global dotnet-ef
```
3. 确保已正确配置 SQL Server 连接字符串
## 使用说明
### 1. 创建新的迁移
1. 在 `aspnet-core/migrations` 目录下运行迁移脚本:
```powershell
# 使用中文版本
.\Migrate.ps1
# 或使用英文版本
.\MigrateEn.ps1
```
2. 在菜单中选择 SQL Server 数据库上下文:
```
[3] LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer
```
3. 输入迁移名称(可选):
- 直接回车将使用默认名称:`AddNewMigration_yyyyMMdd_HHmmss`
- 或输入自定义名称,如:`AddNewFeature`
### 2. 生成 SQL 脚本
在创建迁移后,脚本会询问是否需要生成 SQL 脚本:
1. 选择是否生成 SQL 脚本 (Y/N)
2. 如果选择 Y,将提供以下选项:
- `[A]` - 生成所有迁移的 SQL 脚本
- `[L]` - 仅生成最新迁移的 SQL 脚本
- `[0-9]` - 从指定的迁移版本开始生成
生成的 SQL 脚本将保存在:
```
aspnet-core/InitSql/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/
```
### 3. 应用迁移
生成的 SQL 脚本可以通过以下方式应用到数据库:
1. 使用 SQL Server Management Studio 或其他 SQL Server 客户端工具执行 SQL 脚本
2. 或使用命令行:
```bash
sqlcmd -S your_server -d your_database -i your_script.sql
```

35
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/SingleMigrationsDbContextFactory.cs

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer;
public class SingleMigrationsDbContextFactory : IDesignTimeDbContextFactory<SingleMigrationsDbContext>
{
public SingleMigrationsDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
var connectionString = configuration.GetConnectionString("Default");
var builder = new DbContextOptionsBuilder<SingleMigrationsDbContext>()
.UseSqlServer(connectionString,
b => b.MigrationsAssembly("LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer"));
return new SingleMigrationsDbContext(builder!.Options);
}
private static IConfigurationRoot BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory(),
"../LY.MicroService.Applications.Single.DbMigrator/"))
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile(
"appsettings.SqlServer.json",
optional: false);
return builder.Build();
}
}

26
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer/SingleMigrationsEntityFrameworkCoreSqlServerModule.cs

@ -0,0 +1,26 @@
using LINGYUN.Abp.Elsa.EntityFrameworkCore.SqlServer;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.Modularity;
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer;
[DependsOn(
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpElsaEntityFrameworkCoreSqlServerModule),
typeof(SingleMigrationsEntityFrameworkCoreModule)
)]
public class SingleMigrationsEntityFrameworkCoreSqlServerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<SingleMigrationsDbContext>();
Configure<AbpDbContextOptions>(options =>
{
options.UseSqlServer();
});
}
}

200
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/SingleDbMigrationService.cs

@ -1,101 +1,101 @@
using LINGYUN.Abp.Saas.Tenants; using LINGYUN.Abp.Saas.Tenants;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.DistributedLocking; using Volo.Abp.DistributedLocking;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Migrations; using Volo.Abp.EntityFrameworkCore.Migrations;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace LY.MicroService.Applications.Single.EntityFrameworkCore; namespace LY.MicroService.Applications.Single.EntityFrameworkCore;
public class SingleDbMigrationService : EfCoreRuntimeDatabaseMigratorBase<SingleMigrationsDbContext>, ITransientDependency public class SingleDbMigrationService : EfCoreRuntimeDatabaseMigratorBase<SingleMigrationsDbContext>, ITransientDependency
{ {
protected IDataSeeder DataSeeder { get; } protected IDataSeeder DataSeeder { get; }
protected ITenantRepository TenantRepository { get; } protected ITenantRepository TenantRepository { get; }
public SingleDbMigrationService( public SingleDbMigrationService(
IUnitOfWorkManager unitOfWorkManager, IUnitOfWorkManager unitOfWorkManager,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IAbpDistributedLock abpDistributedLock, IAbpDistributedLock abpDistributedLock,
IDistributedEventBus distributedEventBus, IDistributedEventBus distributedEventBus,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
IDataSeeder dataSeeder, IDataSeeder dataSeeder,
ITenantRepository tenantRepository) ITenantRepository tenantRepository)
: base("SingleDbMigrator", unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) : base("SingleDbMigrator", unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory)
{ {
DataSeeder = dataSeeder; DataSeeder = dataSeeder;
TenantRepository = tenantRepository; TenantRepository = tenantRepository;
} }
protected async override Task LockAndApplyDatabaseMigrationsAsync() protected async override Task LockAndApplyDatabaseMigrationsAsync()
{ {
await base.LockAndApplyDatabaseMigrationsAsync(); await base.LockAndApplyDatabaseMigrationsAsync();
var tenants = await TenantRepository.GetListAsync(); var tenants = await TenantRepository.GetListAsync();
foreach (var tenant in tenants.Where(x => x.IsActive)) foreach (var tenant in tenants.Where(x => x.IsActive))
{ {
Logger.LogInformation($"Trying to acquire the distributed lock for database migration: {DatabaseName} with tenant: {tenant.Name}."); Logger.LogInformation($"Trying to acquire the distributed lock for database migration: {DatabaseName} with tenant: {tenant.Name}.");
var schemaMigrated = false; var schemaMigrated = false;
await using (var handle = await DistributedLock.TryAcquireAsync("DatabaseMigration_" + DatabaseName + "_Tenant" + tenant.Id.ToString())) await using (var handle = await DistributedLock.TryAcquireAsync("DatabaseMigration_" + DatabaseName + "_Tenant" + tenant.Id.ToString()))
{ {
if (handle is null) if (handle is null)
{ {
Logger.LogInformation($"Distributed lock could not be acquired for database migration: {DatabaseName} with tenant: {tenant.Name}. Operation cancelled."); Logger.LogInformation($"Distributed lock could not be acquired for database migration: {DatabaseName} with tenant: {tenant.Name}. Operation cancelled.");
return; return;
} }
Logger.LogInformation($"Distributed lock is acquired for database migration: {DatabaseName} with tenant: {tenant.Name}..."); Logger.LogInformation($"Distributed lock is acquired for database migration: {DatabaseName} with tenant: {tenant.Name}...");
using (CurrentTenant.Change(tenant.Id)) using (CurrentTenant.Change(tenant.Id))
{ {
// Create database tables if needed // Create database tables if needed
using var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false); using var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false);
var dbContext = await ServiceProvider var dbContext = await ServiceProvider
.GetRequiredService<IDbContextProvider<SingleMigrationsDbContext>>() .GetRequiredService<IDbContextProvider<SingleMigrationsDbContext>>()
.GetDbContextAsync(); .GetDbContextAsync();
var pendingMigrations = await dbContext var pendingMigrations = await dbContext
.Database .Database
.GetPendingMigrationsAsync(); .GetPendingMigrationsAsync();
if (pendingMigrations.Any()) if (pendingMigrations.Any())
{ {
await dbContext.Database.MigrateAsync(); await dbContext.Database.MigrateAsync();
schemaMigrated = true; schemaMigrated = true;
} }
await uow.CompleteAsync(); await uow.CompleteAsync();
await SeedAsync(); await SeedAsync();
if (schemaMigrated || AlwaysSeedTenantDatabases) if (schemaMigrated || AlwaysSeedTenantDatabases)
{ {
await DistributedEventBus.PublishAsync( await DistributedEventBus.PublishAsync(
new AppliedDatabaseMigrationsEto new AppliedDatabaseMigrationsEto
{ {
DatabaseName = DatabaseName, DatabaseName = DatabaseName,
TenantId = tenant.Id TenantId = tenant.Id
} }
); );
} }
} }
} }
Logger.LogInformation($"Distributed lock has been released for database migration: {DatabaseName} with tenant: {tenant.Name}..."); Logger.LogInformation($"Distributed lock has been released for database migration: {DatabaseName} with tenant: {tenant.Name}...");
} }
} }
protected async override Task SeedAsync() protected async override Task SeedAsync()
{ {
await DataSeeder.SeedAsync(CurrentTenant.Id); await DataSeeder.SeedAsync(CurrentTenant.Id);
} }
} }

5
aspnet-core/migrations/Migrate.ps1

@ -21,6 +21,11 @@ $dbContexts = @{
Context = "SingleMigrationsDbContext" Context = "SingleMigrationsDbContext"
Factory = "SingleMigrationsDbContextFactory" Factory = "SingleMigrationsDbContextFactory"
} }
“3” = @{
Name = "LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer"
Context = "SingleMigrationsDbContext"
Factory = "SingleMigrationsDbContextFactory"
}
} }
# 显示DbContext选择菜单 # 显示DbContext选择菜单

5
aspnet-core/migrations/MigrateEn.ps1

@ -21,6 +21,11 @@ $dbContexts = @{
Context = "SingleMigrationsDbContext" Context = "SingleMigrationsDbContext"
Factory = "SingleMigrationsDbContextFactory" Factory = "SingleMigrationsDbContextFactory"
} }
"3" = @{
Name = "LY.MicroService.Applications.Single.EntityFrameworkCore.SqlServer"
Context = "SingleMigrationsDbContext"
Factory = "SingleMigrationsDbContextFactory"
}
} }
# Display DbContext selection menu # Display DbContext selection menu

263
aspnet-core/services/Directory.Packages.props

@ -0,0 +1,263 @@
<Project>
<Import Project="..\..\Directory.Packages.props" />
<PropertyGroup>
<LYAbpPackageVersion>8.3.0</LYAbpPackageVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="DistributedLock.Redis" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Elsa.Activities.Email" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Elsa.Activities.Http" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Elsa.Activities.UserTask" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Elsa.Activities.Temporal.Quartz" Version="$(LYAbpPackageVersion)" />
<!--<PackageVersion Include="Elsa.Designer.Components.Web" Version="$(LYAbpPackageVersion)" />-->
<PackageVersion Include="Elsa.Webhooks.Api" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="OpenIddict.Validation.DataProtection" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="OpenIddict.Server.DataProtection" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.AspNetCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Enrichers.Environment" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Enrichers.Assembly" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Enrichers.Process" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Enrichers.Thread" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Sinks.Elasticsearch" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Serilog.Sinks.File" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Quartz.Serialization.Json" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Web.OpenIddict" Version="$(LYAbpPackageVersion)" />
<!--<PackageVersion Include="Volo.Abp.Account.Web.IdentityServer" Version="$(LYAbpPackageVersion)" />-->
<PackageVersion Include="Volo.Abp.AspNetCore.Serilog" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Autofac" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Caching.StackExchangeRedis" Version="$(LYAbpPackageVersion)" />
<!-- <PackageVersion Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="$(LYAbpPackageVersion)" />-->
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.PostgreSql" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.Identity" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.AspNetCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Imaging.ImageSharp" Version="$(LYAbpPackageVersion)" />
<!--<PackageVersion Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />-->
<PackageVersion Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="LINGYUN.Abp.AuditLogging.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AuditLogging" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Authentication.QQ" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Authentication.WeChat" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Authorization.OrganizationUnits" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Aliyun.SettingManagement" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Aliyun" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Tencent.QQ" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Tencent.SettingManagement" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Tencent" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.HttpOverrides" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Data.DbMigrator" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.ExceptionHandling.Emailing" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Features.LimitValidation.Redis.Client" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Features.LimitValidation.Redis" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Features.LimitValidation" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Http.Client.Wrapper" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdGenerator" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.RealTime" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Wrapper" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dynamic.Queryable.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dynamic.Queryable.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dynamic.Queryable.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Linq.Dynamic.Queryable" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Exporter.MiniExcel" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.FeatureManagement.Client" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.Mvc.Localization" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Localization.CultureMap" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Localization.Persistence" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Logging.Serilog.Elasticsearch" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Logging" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Serilog.Enrichers.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Serilog.Enrichers.UniqueId" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Sms.Aliyun" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.Mvc.Wrapper" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.UI.Navigation" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenApi.Authorization" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.SettingManagement.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MultiTenancy.Editions" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.WeChat" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.MiniProgram" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official.Handlers" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.SettingManagement" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work.Handlers" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat" Version="$(LYAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="LINGYUN.Abp.Account.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.Templates" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Auditing.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Auditing.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Auditing.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.StackExchangeRedis" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Demo.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Demo.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Demo.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.BlobStoring" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Emailing" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.IM" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Notifications" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Sms" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Webhooks" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities" Version="$(LYAbpPackageVersion)" />
<!-- <PackageVersion Include="LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql" Version="$(LYAbpPackageVersion)" />-->
<PackageVersion Include="LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Server" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.FeatureManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.FeatureManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Session" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.AspNetCore.Session" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Notifications" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.OrganizaztionUnits" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.LinkUser" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Portal" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.SmsValidator" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.WeChat.Work" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Session.AspNetCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.AspNetCore.Session" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.AspNetCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IM.SignalR" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IM" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.ExceptionHandling.Notifications" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.ExceptionHandling" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Common" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Core" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Emailing" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.SignalR" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.WeChat.MiniProgram" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.WeChat.Work" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.LinkUser" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Sms" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Portal" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.WeChat" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.WeChat.Work" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.FileSystem" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Imaging" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Minio" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.SettingManagement" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.PermissionManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.PermissionManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.UI.Navigation.VueVbenAdmin" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Settings.VueVbenAdmin" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Theme.VueVbenAdmin" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.SettingManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.SettingManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Abstractions" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Activities" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.DistributedLocking" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.EventBus" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.ExceptionHandling" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Jobs" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Notifications" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Quartz" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.Core" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.EventBus" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.Identity" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.Saas" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Application.Contracts" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Application" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Domain.Shared" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Domain" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.HttpApi" Version="$(LYAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks" Version="$(LYAbpPackageVersion)" />
</ItemGroup>
</Project>

12
aspnet-core/services/LY.AIO.Applications.Single/.config/dotnet-tools.json

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "7.0.3",
"commands": [
"dotnet-ef"
]
}
}
}

2
aspnet-core/services/LY.AIO.Applications.Single/.gitignore

@ -0,0 +1,2 @@
wwwroot
package*.json

89
aspnet-core/services/LY.AIO.Applications.Single/Authentication/AbpCookieAuthenticationHandler.cs

@ -0,0 +1,89 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;
namespace LY.AIO.Applications.Single.Authentication;
public class AbpCookieAuthenticationHandler : CookieAuthenticationHandler
{
public AbpCookieAuthenticationHandler(
IOptionsMonitor<CookieAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder) : base(options, logger, encoder)
{
}
public AbpCookieAuthenticationHandler(
IOptionsMonitor<CookieAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected const string XRequestFromHeader = "X-Request-From";
protected const string DontRedirectRequestFromHeader = "vben";
protected override Task InitializeEventsAsync()
{
var events = new CookieAuthenticationEvents
{
OnRedirectToLogin = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
},
OnRedirectToAccessDenied = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
},
OnRedirectToLogout = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
},
OnRedirectToReturnUrl = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
}
};
Events = events;
return Task.CompletedTask;
}
}

38
aspnet-core/services/LY.AIO.Applications.Single/BackgroundJobs/NotificationPublishJob.cs

@ -0,0 +1,38 @@
using LINGYUN.Abp.Notifications;
using Microsoft.Extensions.Options;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
namespace LY.AIO.Applications.Single.BackgroundJobs;
public class NotificationPublishJob : AsyncBackgroundJob<NotificationPublishJobArgs>, ITransientDependency
{
protected AbpNotificationsPublishOptions Options { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected INotificationDataSerializer NotificationDataSerializer { get; }
public NotificationPublishJob(
IOptions<AbpNotificationsPublishOptions> options,
IServiceScopeFactory serviceScopeFactory,
INotificationDataSerializer notificationDataSerializer)
{
Options = options.Value;
ServiceScopeFactory = serviceScopeFactory;
NotificationDataSerializer = notificationDataSerializer;
}
public override async Task ExecuteAsync(NotificationPublishJobArgs args)
{
var providerType = Type.GetType(args.ProviderType);
using (var scope = ServiceScopeFactory.CreateScope())
{
if (scope.ServiceProvider.GetRequiredService(providerType) is INotificationPublishProvider publishProvider)
{
var store = scope.ServiceProvider.GetRequiredService<INotificationStore>();
var notification = await store.GetNotificationOrNullAsync(args.TenantId, args.NotificationId);
notification.Data = NotificationDataSerializer.Serialize(notification.Data);
await publishProvider.PublishAsync(notification, args.UserIdentifiers);
}
}
}
}

22
aspnet-core/services/LY.AIO.Applications.Single/BackgroundJobs/NotificationPublishJobArgs.cs

@ -0,0 +1,22 @@
using LINGYUN.Abp.Notifications;
namespace LY.AIO.Applications.Single.BackgroundJobs;
public class NotificationPublishJobArgs
{
public Guid? TenantId { get; set; }
public long NotificationId { get; set; }
public string ProviderType { get; set; }
public List<UserIdentifier> UserIdentifiers { get; set; }
public NotificationPublishJobArgs()
{
UserIdentifiers = new List<UserIdentifier>();
}
public NotificationPublishJobArgs(long id, string providerType, List<UserIdentifier> userIdentifiers, Guid? tenantId = null)
{
NotificationId = id;
ProviderType = providerType;
UserIdentifiers = userIdentifiers;
TenantId = tenantId;
}
}

11
aspnet-core/services/LY.AIO.Applications.Single/Controllers/HomeController.cs

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Mvc;
namespace LY.AIO.Applications.Single.Controllers;
public class HomeController : Controller
{
public IActionResult Index()
{
return Redirect("/swagger");
}
}

70
aspnet-core/services/LY.AIO.Applications.Single/Controllers/SettingMergeController.cs

@ -0,0 +1,70 @@
using LINGYUN.Abp.SettingManagement;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace LY.AIO.Applications.Single.Controllers;
[ExposeServices(
typeof(SettingController),
typeof(SettingMergeController))]
public class SettingMergeController : SettingController
{
private readonly SettingManagementMergeOptions _mergeOptions;
public SettingMergeController(
ISettingAppService settingAppService,
ISettingTestAppService settingTestAppService,
IOptions<SettingManagementMergeOptions> mergeOptions)
: base(settingAppService, settingTestAppService)
{
_mergeOptions = mergeOptions.Value;
}
[HttpGet]
[Route("by-current-tenant")]
public async override Task<SettingGroupResult> GetAllForCurrentTenantAsync()
{
var result = new SettingGroupResult();
var markTypeMap = new List<Type>
{
typeof(SettingMergeController),
};
foreach (var serviceType in _mergeOptions.GlobalSettingProviders
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType))))
{
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>();
var currentResult = await settingService.GetAllForCurrentTenantAsync();
foreach (var group in currentResult.Items)
{
result.AddGroup(group);
}
markTypeMap.Add(serviceType);
}
return result;
}
[HttpGet]
[Route("by-global")]
public async override Task<SettingGroupResult> GetAllForGlobalAsync()
{
var result = new SettingGroupResult();
var markTypeMap = new List<Type>
{
typeof(SettingMergeController),
};
foreach (var serviceType in _mergeOptions.GlobalSettingProviders
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType))))
{
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>();
var currentResult = await settingService.GetAllForGlobalAsync();
foreach (var group in currentResult.Items)
{
result.AddGroup(group);
}
markTypeMap.Add(serviceType);
}
return result;
}
}

45
aspnet-core/services/LY.AIO.Applications.Single/Controllers/UserSettingMergeController.cs

@ -0,0 +1,45 @@
using LINGYUN.Abp.SettingManagement;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace LY.AIO.Applications.Single.Controllers;
[ExposeServices(
typeof(UserSettingController),
typeof(UserSettingMergeController))]
public class UserSettingMergeController : UserSettingController
{
private readonly SettingManagementMergeOptions _mergeOptions;
public UserSettingMergeController(
IUserSettingAppService service,
IOptions<SettingManagementMergeOptions> mergeOptions)
: base(service)
{
_mergeOptions = mergeOptions.Value;
}
[HttpGet]
[Route("by-current-user")]
public async override Task<SettingGroupResult> GetAllForCurrentUserAsync()
{
var result = new SettingGroupResult();
var markTypeMap = new List<Type>
{
typeof(UserSettingMergeController),
};
foreach (var serviceType in _mergeOptions.UserSettingProviders
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType))))
{
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IUserSettingAppService>();
var currentResult = await settingService.GetAllForCurrentUserAsync();
foreach (var group in currentResult.Items)
{
result.AddGroup(group);
}
markTypeMap.Add(serviceType);
}
return result;
}
}

19
aspnet-core/services/LY.AIO.Applications.Single/Dockerfile

@ -0,0 +1,19 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0
LABEL maintainer="colin.in@foxmail.com"
WORKDIR /app
COPY . /app
#东8区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
EXPOSE 80/tcp
VOLUME [ "./app/blobs" ]
VOLUME [ "./app/Logs" ]
VOLUME [ "./app/Modules" ]
RUN apt update
RUN apt install wget -y
ENTRYPOINT ["dotnet", "LY.MicroService.Applications.Single.dll"]

59
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/ChatMessageEventHandler.cs

@ -0,0 +1,59 @@
using LINGYUN.Abp.IM;
using LINGYUN.Abp.IM.Messages;
using LINGYUN.Abp.RealTime;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
namespace LY.AIO.Applications.Single.EventBus.Distributed
{
public class ChatMessageEventHandler : IDistributedEventHandler<RealTimeEto<ChatMessage>>, ITransientDependency
{
/// <summary>
/// Reference to <see cref="ILogger<DefaultNotificationDispatcher>"/>.
/// </summary>
public ILogger<ChatMessageEventHandler> Logger { get; set; }
/// <summary>
/// Reference to <see cref="AbpIMOptions"/>.
/// </summary>
protected AbpIMOptions Options { get; }
protected IMessageStore MessageStore { get; }
protected IMessageBlocker MessageBlocker { get; }
protected IMessageSenderProviderManager MessageSenderProviderManager { get; }
public ChatMessageEventHandler(
IOptions<AbpIMOptions> options,
IMessageStore messageStore,
IMessageBlocker messageBlocker,
IMessageSenderProviderManager messageSenderProviderManager)
{
Options = options.Value;
MessageStore = messageStore;
MessageBlocker = messageBlocker;
MessageSenderProviderManager = messageSenderProviderManager;
Logger = NullLogger<ChatMessageEventHandler>.Instance;
}
public async virtual Task HandleEventAsync(RealTimeEto<ChatMessage> eventData)
{
Logger.LogDebug($"Persistent chat message.");
var message = eventData.Data;
// 消息拦截
// 扩展敏感词汇过滤
await MessageBlocker.InterceptAsync(message);
await MessageStore.StoreMessageAsync(message);
// 发送消息
foreach (var provider in MessageSenderProviderManager.Providers)
{
Logger.LogDebug($"Sending message with provider {provider.Name}");
await provider.SendMessageAsync(message);
}
}
}
}

470
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/NotificationEventHandler.cs

@ -0,0 +1,470 @@
using LINGYUN.Abp.Notifications;
using LY.AIO.Applications.Single.BackgroundJobs;
using LY.AIO.Applications.Single.MultiTenancy;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System.Globalization;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Json;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.TextTemplating;
using Volo.Abp.Uow;
namespace LY.AIO.Applications.Single.EventBus.Distributed
{
/// <summary>
/// 订阅通知发布事件,统一发布消息
/// </summary>
/// <remarks>
/// 作用在于SignalR客户端只会与一台服务器建立连接,
/// 只有启用了SignlR服务端的才能真正将消息发布到客户端
/// </remarks>
public class NotificationEventHandler :
IDistributedEventHandler<NotificationEto<NotificationData>>,
IDistributedEventHandler<NotificationEto<NotificationTemplate>>,
ITransientDependency
{
/// <summary>
/// Reference to <see cref="ILogger<DefaultNotificationDispatcher>"/>.
/// </summary>
public ILogger<NotificationEventHandler> Logger { get; set; }
/// <summary>
/// Reference to <see cref="AbpNotificationsPublishOptions"/>.
/// </summary>
protected AbpNotificationsPublishOptions Options { get; }
/// <summary>
/// Reference to <see cref="ICurrentTenant"/>.
/// </summary>
protected ICurrentTenant CurrentTenant { get; }
/// <summary>
/// Reference to <see cref="ITenantConfigurationCache"/>.
/// </summary>
protected ITenantConfigurationCache TenantConfigurationCache { get; }
/// <summary>
/// Reference to <see cref="IJsonSerializer"/>.
/// </summary>
protected IJsonSerializer JsonSerializer { get; }
/// <summary>
/// Reference to <see cref="IBackgroundJobManager"/>.
/// </summary>
protected IBackgroundJobManager BackgroundJobManager { get; }
/// <summary>
/// Reference to <see cref="ITemplateRenderer"/>.
/// </summary>
protected ITemplateRenderer TemplateRenderer { get; }
/// <summary>
/// Reference to <see cref="INotificationStore"/>.
/// </summary>
protected INotificationStore NotificationStore { get; }
/// <summary>
/// Reference to <see cref="IStringLocalizerFactory"/>.
/// </summary>
protected IStringLocalizerFactory StringLocalizerFactory { get; }
/// <summary>
/// Reference to <see cref="INotificationDataSerializer"/>.
/// </summary>
protected INotificationDataSerializer NotificationDataSerializer { get; }
/// <summary>
/// Reference to <see cref="INotificationDefinitionManager"/>.
/// </summary>
protected INotificationDefinitionManager NotificationDefinitionManager { get; }
/// <summary>
/// Reference to <see cref="INotificationSubscriptionManager"/>.
/// </summary>
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; }
/// <summary>
/// Reference to <see cref="INotificationPublishProviderManager"/>.
/// </summary>
protected INotificationPublishProviderManager NotificationPublishProviderManager { get; }
/// <summary>
/// Initializes a new instance of the <see cref="NotificationEventHandler"/> class.
/// </summary>
public NotificationEventHandler(
ICurrentTenant currentTenant,
ITenantConfigurationCache tenantConfigurationCache,
IJsonSerializer jsonSerializer,
ITemplateRenderer templateRenderer,
IBackgroundJobManager backgroundJobManager,
IStringLocalizerFactory stringLocalizerFactory,
IOptions<AbpNotificationsPublishOptions> options,
INotificationStore notificationStore,
INotificationDataSerializer notificationDataSerializer,
INotificationDefinitionManager notificationDefinitionManager,
INotificationSubscriptionManager notificationSubscriptionManager,
INotificationPublishProviderManager notificationPublishProviderManager)
{
Options = options.Value;
TenantConfigurationCache = tenantConfigurationCache;
CurrentTenant = currentTenant;
JsonSerializer = jsonSerializer;
TemplateRenderer = templateRenderer;
BackgroundJobManager = backgroundJobManager;
StringLocalizerFactory = stringLocalizerFactory;
NotificationStore = notificationStore;
NotificationDataSerializer = notificationDataSerializer;
NotificationDefinitionManager = notificationDefinitionManager;
NotificationSubscriptionManager = notificationSubscriptionManager;
NotificationPublishProviderManager = notificationPublishProviderManager;
Logger = NullLogger<NotificationEventHandler>.Instance;
}
[UnitOfWork]
public async virtual Task HandleEventAsync(NotificationEto<NotificationTemplate> eventData)
{
var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name);
if (notification == null)
{
return;
}
var culture = eventData.Data.Culture;
if (culture.IsNullOrWhiteSpace())
{
culture = CultureInfo.CurrentCulture.Name;
}
using (CultureHelper.Use(culture, culture))
{
if (notification.NotificationType == NotificationType.System)
{
using (CurrentTenant.Change(null))
{
await SendToTenantAsync(null, notification, eventData);
var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync();
foreach (var activeTenant in allActiveTenants)
{
await SendToTenantAsync(activeTenant.Id, notification, eventData);
}
}
}
else
{
await SendToTenantAsync(eventData.TenantId, notification, eventData);
}
}
}
[UnitOfWork]
public async virtual Task HandleEventAsync(NotificationEto<NotificationData> eventData)
{
var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name);
if (notification == null)
{
return;
}
if (notification.NotificationType == NotificationType.System)
{
using (CurrentTenant.Change(null))
{
await SendToTenantAsync(null, notification, eventData);
var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync();
foreach (var activeTenant in allActiveTenants)
{
await SendToTenantAsync(activeTenant.Id, notification, eventData);
}
}
}
else
{
await SendToTenantAsync(eventData.TenantId, notification, eventData);
}
}
protected async virtual Task SendToTenantAsync(
Guid? tenantId,
NotificationDefinition notification,
NotificationEto<NotificationTemplate> eventData)
{
using (CurrentTenant.Change(tenantId))
{
var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers);
// 过滤用户指定提供者
if (eventData.UseProviders.Any())
{
providers = providers.Where(p => eventData.UseProviders.Contains(p.Name));
}
else if (notification.Providers.Any())
{
providers = providers.Where(p => notification.Providers.Contains(p.Name));
}
var notificationInfo = new NotificationInfo
{
Name = notification.Name,
TenantId = tenantId,
Severity = eventData.Severity,
Type = notification.NotificationType,
ContentType = notification.ContentType,
CreationTime = eventData.CreationTime,
Lifetime = notification.NotificationLifetime,
};
notificationInfo.SetId(eventData.Id);
var title = notification.DisplayName.Localize(StringLocalizerFactory);
var message = "";
try
{
// 由于模板通知受租户影响, 格式化失败的消息将被丢弃.
message = await TemplateRenderer.RenderAsync(
templateName: eventData.Data.Name,
model: eventData.Data.ExtraProperties,
cultureName: eventData.Data.Culture,
globalContext: new Dictionary<string, object>
{
// 模板不支持 $ 字符, 改为普通关键字
{ NotificationKeywords.Name, notification.Name },
{ NotificationKeywords.FormUser, eventData.Data.FormUser },
{ NotificationKeywords.Id, eventData.Id },
{ NotificationKeywords.Title, title.ToString() },
{ NotificationKeywords.CreationTime, eventData.CreationTime.ToString(Options.DateTimeFormat) },
});
}
catch(Exception ex)
{
Logger.LogWarning("Formatting template notification failed, message will be discarded, cause :{message}", ex.Message);
return;
}
var notificationData = new NotificationData();
notificationData.WriteStandardData(
title: title.ToString(),
message: message,
createTime: eventData.CreationTime,
formUser: eventData.Data.FormUser);
notificationData.ExtraProperties.AddIfNotContains(eventData.Data.ExtraProperties);
notificationInfo.Data = notificationData;
var subscriptionUsers = await GerSubscriptionUsersAsync(
notificationInfo.Name,
eventData.Users,
tenantId);
await PersistentNotificationAsync(
notificationInfo,
subscriptionUsers,
providers);
if (subscriptionUsers.Any())
{
// 发布通知
foreach (var provider in providers)
{
await PublishToSubscriberAsync(provider, notificationInfo, subscriptionUsers);
}
}
}
}
protected async virtual Task SendToTenantAsync(
Guid? tenantId,
NotificationDefinition notification,
NotificationEto<NotificationData> eventData)
{
using (CurrentTenant.Change(tenantId))
{
var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers);
// 过滤用户指定提供者
if (eventData.UseProviders.Any())
{
providers = providers.Where(p => eventData.UseProviders.Contains(p.Name));
}
else if (notification.Providers.Any())
{
providers = providers.Where(p => notification.Providers.Contains(p.Name));
}
var notificationInfo = new NotificationInfo
{
Name = notification.Name,
CreationTime = eventData.CreationTime,
Data = eventData.Data,
Severity = eventData.Severity,
Lifetime = notification.NotificationLifetime,
TenantId = tenantId,
Type = notification.NotificationType,
ContentType = notification.ContentType,
};
notificationInfo.SetId(eventData.Id);
notificationInfo.Data = NotificationDataSerializer.Serialize(notificationInfo.Data);
// 获取用户订阅
var subscriptionUsers = await GerSubscriptionUsersAsync(
notificationInfo.Name,
eventData.Users,
tenantId);
// 持久化通知
await PersistentNotificationAsync(
notificationInfo,
subscriptionUsers,
providers);
if (subscriptionUsers.Any())
{
// 发布订阅通知
foreach (var provider in providers)
{
await PublishToSubscriberAsync(provider, notificationInfo, subscriptionUsers);
}
}
}
}
/// <summary>
/// 获取用户订阅列表
/// </summary>
/// <param name="notificationName">通知名称</param>
/// <param name="sendToUsers">接收用户列表</param>
/// <param name="tenantId">租户标识</param>
/// <returns>用户订阅列表</returns>
protected async Task<IEnumerable<UserIdentifier>> GerSubscriptionUsersAsync(
string notificationName,
IEnumerable<UserIdentifier> sendToUsers,
Guid? tenantId = null)
{
try
{
// 获取用户订阅列表
var userSubscriptions = await NotificationSubscriptionManager.GetUsersSubscriptionsAsync(
tenantId,
notificationName,
sendToUsers);
return userSubscriptions.Select(us => new UserIdentifier(us.UserId, us.UserName));
}
catch(Exception ex)
{
Logger.LogWarning("Failed to get user subscription, message will not be received by the user, reason: {message}", ex.Message);
}
return new List<UserIdentifier>();
}
/// <summary>
/// 持久化通知并返回订阅用户列表
/// </summary>
/// <param name="notificationInfo">通知实体</param>
/// <param name="subscriptionUsers">订阅用户列表</param>
/// <param name="sendToProviders">通知发送提供者</param>
/// <returns>返回订阅者列表</returns>
protected async Task PersistentNotificationAsync(
NotificationInfo notificationInfo,
IEnumerable<UserIdentifier> subscriptionUsers,
IEnumerable<INotificationPublishProvider> sendToProviders)
{
try
{
// 持久化通知
await NotificationStore.InsertNotificationAsync(notificationInfo);
if (!subscriptionUsers.Any())
{
return;
}
// 持久化用户通知
await NotificationStore.InsertUserNotificationsAsync(notificationInfo, subscriptionUsers.Select(u => u.UserId));
if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne)
{
// 一次性通知取消用户订阅
await NotificationStore.DeleteUserSubscriptionAsync(
notificationInfo.TenantId,
subscriptionUsers,
notificationInfo.Name);
}
}
catch (Exception ex)
{
Logger.LogWarning("Failed to persistent notification failed, reason: {message}", ex.Message);
foreach (var provider in sendToProviders)
{
// 处理持久化失败进入后台队列
await ProcessingFailedToQueueAsync(provider, notificationInfo, subscriptionUsers);
}
}
}
/// <summary>
/// 发布订阅者通知
/// </summary>
/// <param name="provider">通知发布者</param>
/// <param name="notificationInfo">通知信息</param>
/// <param name="subscriptionUserIdentifiers">订阅用户列表</param>
/// <returns></returns>
protected async Task PublishToSubscriberAsync(
INotificationPublishProvider provider,
NotificationInfo notificationInfo,
IEnumerable<UserIdentifier> subscriptionUsers)
{
try
{
Logger.LogDebug($"Sending notification with provider {provider.Name}");
// 2024-10-10: 框架层面应该取消通知数据转换,而是交给提供商来实现
//var notifacationDataMapping = Options.NotificationDataMappings
// .GetMapItemOrDefault(provider.Name, notificationInfo.Name);
//if (notifacationDataMapping != null)
//{
// notificationInfo.Data = notifacationDataMapping.MappingFunc(notificationInfo.Data);
//}
// 发布
await provider.PublishAsync(notificationInfo, subscriptionUsers);
Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful");
}
catch (Exception ex)
{
Logger.LogWarning($"Send notification error with provider {provider.Name}");
Logger.LogWarning($"Error message:{ex.Message}");
Logger.LogDebug($"Failed to send notification {notificationInfo.Name}. Try to push notification to background job");
// 发送失败的消息进入后台队列
await ProcessingFailedToQueueAsync(provider, notificationInfo, subscriptionUsers);
}
}
/// <summary>
/// 处理失败的消息进入后台队列
/// </summary>
/// <remarks>
/// 注: 如果入队失败,消息将被丢弃.
/// </remarks>
/// <param name="provider"></param>
/// <param name="notificationInfo"></param>
/// <param name="subscriptionUsers"></param>
/// <returns></returns>
protected async Task ProcessingFailedToQueueAsync(
INotificationPublishProvider provider,
NotificationInfo notificationInfo,
IEnumerable<UserIdentifier> subscriptionUsers)
{
try
{
// 发送失败的消息进入后台队列
await BackgroundJobManager.EnqueueAsync(
new NotificationPublishJobArgs(
notificationInfo.GetId(),
provider.GetType().AssemblyQualifiedName,
subscriptionUsers.ToList(),
notificationInfo.TenantId));
}
catch(Exception ex)
{
Logger.LogWarning("Failed to push to background job, notification will be discarded, error cause: {message}", ex.Message);
}
}
}
}

53
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/TenantSynchronizer.cs

@ -0,0 +1,53 @@
using LINGYUN.Abp.Saas.Tenants;
using LY.AIO.Applications.Single.MultiTenancy;
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.Uow;
namespace LY.AIO.Applications.Single.EventBus.Distributed
{
public class TenantSynchronizer :
IDistributedEventHandler<EntityCreatedEto<TenantEto>>,
IDistributedEventHandler<EntityUpdatedEto<TenantEto>>,
IDistributedEventHandler<EntityDeletedEto<TenantEto>>,
IDistributedEventHandler<TenantConnectionStringUpdatedEto>,
ITransientDependency
{
protected IDataSeeder DataSeeder { get; }
protected ITenantConfigurationCache TenantConfigurationCache { get; }
public TenantSynchronizer(
IDataSeeder dataSeeder,
ITenantConfigurationCache tenantConfigurationCache)
{
DataSeeder = dataSeeder;
TenantConfigurationCache = tenantConfigurationCache;
}
[UnitOfWork]
public async virtual Task HandleEventAsync(EntityCreatedEto<TenantEto> eventData)
{
await TenantConfigurationCache.RefreshAsync();
await DataSeeder.SeedAsync(eventData.Entity.Id);
}
public async virtual Task HandleEventAsync(EntityUpdatedEto<TenantEto> eventData)
{
await TenantConfigurationCache.RefreshAsync();
}
public async virtual Task HandleEventAsync(EntityDeletedEto<TenantEto> eventData)
{
await TenantConfigurationCache.RefreshAsync();
}
public async virtual Task HandleEventAsync(TenantConnectionStringUpdatedEto eventData)
{
await TenantConfigurationCache.RefreshAsync();
}
}
}

30
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/UserCreateEventHandler.cs

@ -0,0 +1,30 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Users;
namespace LY.AIO.Applications.Single.EventBus.Distributed
{
public class UserCreateEventHandler : IDistributedEventHandler<EntityCreatedEto<UserEto>>, ITransientDependency
{
private readonly ILocalEventBus _localEventBus;
public UserCreateEventHandler(
ILocalEventBus localEventBus)
{
_localEventBus = localEventBus;
}
/// <summary>
/// 接收添加用户事件,发布本地事件
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public async Task HandleEventAsync(EntityCreatedEto<UserEto> eventData)
{
var localUserCreateEventData = new EntityCreatedEventData<UserEto>(eventData.Entity);
await _localEventBus.PublishAsync(localUserCreateEventData);
}
}
}

112
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Distributed/WebhooksEventHandler.cs

@ -0,0 +1,112 @@
using LINGYUN.Abp.Webhooks;
using LINGYUN.Abp.Webhooks.EventBus;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
namespace LY.AIO.Applications.Single.EventBus.Distributed;
public class WebhooksEventHandler :
IDistributedEventHandler<WebhooksEventData>,
ITransientDependency
{
public IWebhookEventStore WebhookEventStore { get; set; }
private readonly ICurrentTenant _currentTenant;
private readonly IBackgroundJobManager _backgroundJobManager;
private readonly IWebhookSubscriptionManager _webhookSubscriptionManager;
public WebhooksEventHandler(
IWebhookSubscriptionManager webhookSubscriptionManager,
ICurrentTenant currentTenant,
IBackgroundJobManager backgroundJobManager)
{
_currentTenant = currentTenant;
_backgroundJobManager = backgroundJobManager;
_webhookSubscriptionManager = webhookSubscriptionManager;
WebhookEventStore = NullWebhookEventStore.Instance;
}
public async virtual Task HandleEventAsync(WebhooksEventData eventData)
{
var subscriptions = await _webhookSubscriptionManager
.GetAllSubscriptionsOfTenantsIfFeaturesGrantedAsync(
eventData.TenantIds,
eventData.WebhookName);
await PublishAsync(eventData.WebhookName, eventData.Data, subscriptions, eventData.SendExactSameData, eventData.Headers);
}
protected async virtual Task PublishAsync(
string webhookName,
string data,
List<WebhookSubscriptionInfo> webhookSubscriptions,
bool sendExactSameData = false,
WebhookHeader headers = null)
{
if (webhookSubscriptions.IsNullOrEmpty())
{
return;
}
var subscriptionsGroupedByTenant = webhookSubscriptions.GroupBy(x => x.TenantId);
foreach (var subscriptionGroupedByTenant in subscriptionsGroupedByTenant)
{
var webhookInfo = await SaveAndGetWebhookAsync(subscriptionGroupedByTenant.Key, webhookName, data);
foreach (var webhookSubscription in subscriptionGroupedByTenant)
{
var headersToSend = webhookSubscription.Headers;
if (headers != null)
{
if (headers.UseOnlyGivenHeaders)//do not use the headers defined in subscription
{
headersToSend = headers.Headers;
}
else
{
//use the headers defined in subscription. If additional headers has same header, use additional headers value.
foreach (var additionalHeader in headers.Headers)
{
headersToSend[additionalHeader.Key] = additionalHeader.Value;
}
}
}
await _backgroundJobManager.EnqueueAsync(new WebhookSenderArgs
{
TenantId = webhookSubscription.TenantId,
WebhookEventId = webhookInfo.Id,
Data = webhookInfo.Data,
WebhookName = webhookInfo.WebhookName,
WebhookSubscriptionId = webhookSubscription.Id,
Headers = headersToSend,
Secret = webhookSubscription.Secret,
WebhookUri = webhookSubscription.WebhookUri,
SendExactSameData = sendExactSameData
});
}
}
}
protected async virtual Task<WebhookEvent> SaveAndGetWebhookAsync(
Guid? tenantId,
string webhookName,
string data)
{
var webhookInfo = new WebhookEvent
{
WebhookName = webhookName,
Data = data,
TenantId = tenantId
};
var webhookId = await WebhookEventStore.InsertAndGetIdAsync(webhookInfo);
webhookInfo.Id = webhookId;
return webhookInfo;
}
}

58
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Local/UserCreateJoinIMEventHandler.cs

@ -0,0 +1,58 @@
using LINGYUN.Abp.MessageService.Chat;
using LINGYUN.Abp.MessageService.Notifications;
using LINGYUN.Abp.Notifications;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.Uow;
using Volo.Abp.Users;
namespace LY.AIO.Applications.Single.EventBus.Local
{
public class UserCreateJoinIMEventHandler : ILocalEventHandler<EntityCreatedEventData<UserEto>>, ITransientDependency
{
private readonly IChatDataSeeder _chatDataSeeder;
private readonly INotificationSubscriptionManager _notificationSubscriptionManager;
public UserCreateJoinIMEventHandler(
IChatDataSeeder chatDataSeeder,
INotificationSubscriptionManager notificationSubscriptionManager)
{
_chatDataSeeder = chatDataSeeder;
_notificationSubscriptionManager = notificationSubscriptionManager;
}
/// <summary>
/// 接收添加用户事件,初始化IM用户种子
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
[UnitOfWork]
public async virtual Task HandleEventAsync(EntityCreatedEventData<UserEto> eventData)
{
await SeedChatDataAsync(eventData.Entity);
await SeedUserSubscriptionNotifiersAsync(eventData.Entity);
}
protected async virtual Task SeedChatDataAsync(IUserData user)
{
await _chatDataSeeder.SeedAsync(user);
}
protected async virtual Task SeedUserSubscriptionNotifiersAsync(IUserData user)
{
var userIdentifier = new UserIdentifier(user.Id, user.UserName);
await _notificationSubscriptionManager
.SubscribeAsync(
user.TenantId,
userIdentifier,
MessageServiceNotificationNames.IM.FriendValidation);
await _notificationSubscriptionManager
.SubscribeAsync(
user.TenantId,
userIdentifier,
MessageServiceNotificationNames.IM.NewFriend);
}
}
}

69
aspnet-core/services/LY.AIO.Applications.Single/EventBus/Local/UserCreateSendWelcomeEventHandler.cs

@ -0,0 +1,69 @@
using LINGYUN.Abp.Notifications;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.Users;
namespace LY.AIO.Applications.Single.EventBus.Local
{
public class UserCreateSendWelcomeEventHandler : ILocalEventHandler<EntityCreatedEventData<UserEto>>, ITransientDependency
{
private readonly INotificationSender _notificationSender;
private readonly INotificationSubscriptionManager _notificationSubscriptionManager;
public UserCreateSendWelcomeEventHandler(
INotificationSender notificationSender,
INotificationSubscriptionManager notificationSubscriptionManager
)
{
_notificationSender = notificationSender;
_notificationSubscriptionManager = notificationSubscriptionManager;
}
public async Task HandleEventAsync(EntityCreatedEventData<UserEto> eventData)
{
var userIdentifer = new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName);
// 订阅用户欢迎消息
await SubscribeInternalNotifers(userIdentifer, eventData.Entity.TenantId);
await _notificationSender.SendNofiterAsync(
UserNotificationNames.WelcomeToApplication,
new NotificationTemplate(
UserNotificationNames.WelcomeToApplication,
formUser: eventData.Entity.UserName,
data: new Dictionary<string, object>
{
{ "name", eventData.Entity.UserName },
}),
userIdentifer,
eventData.Entity.TenantId,
NotificationSeverity.Info);
}
private async Task SubscribeInternalNotifers(UserIdentifier userIdentifer, Guid? tenantId = null)
{
// 订阅内置通知
await _notificationSubscriptionManager
.SubscribeAsync(
tenantId,
userIdentifer,
DefaultNotifications.SystemNotice);
await _notificationSubscriptionManager
.SubscribeAsync(
tenantId,
userIdentifer,
DefaultNotifications.OnsideNotice);
await _notificationSubscriptionManager
.SubscribeAsync(
tenantId,
userIdentifer,
DefaultNotifications.ActivityNotice);
// 订阅用户欢迎消息
await _notificationSubscriptionManager
.SubscribeAsync(
tenantId,
userIdentifer,
UserNotificationNames.WelcomeToApplication);
}
}
}

19
aspnet-core/services/LY.AIO.Applications.Single/IdentityResources/CustomIdentityResources.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.Identity;
using IdentityServer4.Models;
namespace LY.AIO.Applications.Single.IdentityResources;
public class CustomIdentityResources
{
public class AvatarUrl : IdentityResource
{
public AvatarUrl()
{
Name = IdentityConsts.ClaimType.Avatar.Name;
DisplayName = IdentityConsts.ClaimType.Avatar.DisplayName;
Description = IdentityConsts.ClaimType.Avatar.Description;
Emphasize = true;
UserClaims = new string[] { IdentityConsts.ClaimType.Avatar.Name };
}
}
}

272
aspnet-core/services/LY.AIO.Applications.Single/LY.AIO.Applications.Single.csproj

@ -0,0 +1,272 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\common.secrets.props" />
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>LY.AIO.Applications.Single</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DistributedLock.Redis" />
<PackageReference Include="Elsa.Activities.Email" />
<PackageReference Include="Elsa.Activities.Http" />
<PackageReference Include="Elsa.Activities.UserTask" />
<PackageReference Include="Elsa.Activities.Temporal.Quartz" />
<!--<PackageReference Include="Elsa.Designer.Components.Web" />-->
<PackageReference Include="Elsa.Webhooks.Api" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" />
<PackageReference Include="OpenIddict.Validation.DataProtection" />
<PackageReference Include="OpenIddict.Server.DataProtection" />
<PackageReference Include="Serilog.AspNetCore" />
<PackageReference Include="Serilog.Enrichers.Environment" />
<PackageReference Include="Serilog.Enrichers.Assembly" />
<PackageReference Include="Serilog.Enrichers.Process" />
<PackageReference Include="Serilog.Enrichers.Thread" />
<PackageReference Include="Serilog.Settings.Configuration" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" />
<PackageReference Include="Serilog.Sinks.File" />
<PackageReference Include="Swashbuckle.AspNetCore" />
<PackageReference Include="Quartz.Serialization.Json" />
<PackageReference Include="Volo.Abp.Account.Web.OpenIddict" />
<!--<PackageReference Include="Volo.Abp.Account.Web.IdentityServer" />-->
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Volo.Abp.Autofac" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.PostgreSql" />
<PackageReference Include="Volo.Abp.FeatureManagement.Application" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" />
<PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" />
<PackageReference Include="Volo.Abp.PermissionManagement.Application" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Identity" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" />
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" />
<PackageReference Include="Volo.Abp.Identity.AspNetCore" />
<PackageReference Include="Volo.Abp.Imaging.ImageSharp" />
<!--<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" />-->
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" />
<PackageReference Include="Volo.Abp.OpenIddict.EntityFrameworkCore" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="LINGYUN.Abp.AuditLogging.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.AuditLogging" />
<PackageReference Include="LINGYUN.Abp.Authentication.QQ" />
<PackageReference Include="LINGYUN.Abp.Authentication.WeChat" />
<PackageReference Include="LINGYUN.Abp.Authorization.OrganizationUnits" />
<PackageReference Include="LINGYUN.Abp.Aliyun.SettingManagement" />
<PackageReference Include="LINGYUN.Abp.Aliyun" />
<PackageReference Include="LINGYUN.Abp.Tencent.QQ" />
<PackageReference Include="LINGYUN.Abp.Tencent.SettingManagement" />
<PackageReference Include="LINGYUN.Abp.Tencent" />
<PackageReference Include="LINGYUN.Abp.AspNetCore.HttpOverrides" />
<PackageReference Include="LINGYUN.Abp.Data.DbMigrator" />
<PackageReference Include="LINGYUN.Abp.ExceptionHandling.Emailing" />
<PackageReference Include="LINGYUN.Abp.ExceptionHandling" />
<PackageReference Include="LINGYUN.Abp.Features.LimitValidation.Redis.Client" />
<PackageReference Include="LINGYUN.Abp.Features.LimitValidation.Redis" />
<PackageReference Include="LINGYUN.Abp.Features.LimitValidation" />
<PackageReference Include="LINGYUN.Abp.Http.Client.Wrapper" />
<PackageReference Include="LINGYUN.Abp.IdGenerator" />
<PackageReference Include="LINGYUN.Abp.RealTime" />
<PackageReference Include="LINGYUN.Abp.Wrapper" />
<PackageReference Include="LINGYUN.Abp.Dynamic.Queryable.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.Dynamic.Queryable.Application" />
<PackageReference Include="LINGYUN.Abp.Dynamic.Queryable.HttpApi" />
<PackageReference Include="LINGYUN.Linq.Dynamic.Queryable" />
<PackageReference Include="LINGYUN.Abp.Exporter.MiniExcel" />
<PackageReference Include="LINGYUN.Abp.FeatureManagement.Client" />
<PackageReference Include="LINGYUN.Abp.AspNetCore.Mvc.Localization" />
<PackageReference Include="LINGYUN.Abp.Localization.CultureMap" />
<PackageReference Include="LINGYUN.Abp.Localization.Persistence" />
<PackageReference Include="LINGYUN.Abp.Logging.Serilog.Elasticsearch" />
<PackageReference Include="LINGYUN.Abp.Logging" />
<PackageReference Include="LINGYUN.Abp.Serilog.Enrichers.Application" />
<PackageReference Include="LINGYUN.Abp.Serilog.Enrichers.UniqueId" />
<PackageReference Include="LINGYUN.Abp.Sms.Aliyun" />
<PackageReference Include="LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper" />
<PackageReference Include="LINGYUN.Abp.AspNetCore.Mvc.Wrapper" />
<PackageReference Include="LINGYUN.Abp.UI.Navigation" />
<PackageReference Include="LINGYUN.Abp.OpenApi.Authorization" />
<PackageReference Include="LINGYUN.Abp.OpenApi" />
<PackageReference Include="LINGYUN.Abp.SettingManagement.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.MultiTenancy.Editions" />
<PackageReference Include="LINGYUN.Abp.Identity.WeChat" />
<PackageReference Include="LINGYUN.Abp.WeChat.MiniProgram" />
<PackageReference Include="LINGYUN.Abp.WeChat.Official.Handlers" />
<PackageReference Include="LINGYUN.Abp.WeChat.Official" />
<PackageReference Include="LINGYUN.Abp.WeChat.Official.Application" />
<PackageReference Include="LINGYUN.Abp.WeChat.Official.HttpApi" />
<PackageReference Include="LINGYUN.Abp.WeChat.SettingManagement" />
<PackageReference Include="LINGYUN.Abp.WeChat.Work.Application" />
<PackageReference Include="LINGYUN.Abp.WeChat.Work.Handlers" />
<PackageReference Include="LINGYUN.Abp.WeChat.Work.HttpApi" />
<PackageReference Include="LINGYUN.Abp.WeChat.Work" />
<PackageReference Include="LINGYUN.Abp.WeChat" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="LINGYUN.Abp.Account.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.Account.Application" />
<PackageReference Include="LINGYUN.Abp.Account.HttpApi" />
<PackageReference Include="LINGYUN.Abp.Account.Templates" />
<PackageReference Include="LINGYUN.Abp.Auditing.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.Auditing.Application" />
<PackageReference Include="LINGYUN.Abp.Auditing.HttpApi" />
<PackageReference Include="LINGYUN.Abp.CachingManagement.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.CachingManagement.Application" />
<PackageReference Include="LINGYUN.Abp.CachingManagement.Domain" />
<PackageReference Include="LINGYUN.Abp.CachingManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.CachingManagement.StackExchangeRedis" />
<PackageReference Include="LINGYUN.Abp.DataProtectionManagement.Application" />
<PackageReference Include="LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.DataProtectionManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities.BlobStoring" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities.Emailing" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities.IM" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities.Notifications" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities.Sms" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities.Webhooks" />
<PackageReference Include="LINGYUN.Abp.Elsa.Activities" />
<!-- <PackageReference Include="LINGYUN.Abp.Elsa.EntityFrameworkCore.PostgreSql" />-->
<PackageReference Include="LINGYUN.Abp.Elsa.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.Elsa.Server" />
<PackageReference Include="LINGYUN.Abp.Elsa" />
<PackageReference Include="LINGYUN.Abp.FeatureManagement.Application" />
<PackageReference Include="LINGYUN.Abp.FeatureManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.Session" />
<PackageReference Include="LINGYUN.Abp.Identity.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.Identity.Application" />
<PackageReference Include="LINGYUN.Abp.Identity.AspNetCore.Session" />
<PackageReference Include="LINGYUN.Abp.Identity.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.Identity.Domain" />
<PackageReference Include="LINGYUN.Abp.Identity.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.Identity.HttpApi" />
<PackageReference Include="LINGYUN.Abp.Identity.Notifications" />
<PackageReference Include="LINGYUN.Abp.Identity.OrganizaztionUnits" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.Application" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.Domain" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.HttpApi" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.LinkUser" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.Portal" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.SmsValidator" />
<PackageReference Include="LINGYUN.Abp.IdentityServer.WeChat.Work" />
<PackageReference Include="LINGYUN.Abp.Identity.Session.AspNetCore" />
<PackageReference Include="LINGYUN.Abp.LocalizationManagement.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.LocalizationManagement.Application" />
<PackageReference Include="LINGYUN.Abp.LocalizationManagement.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.LocalizationManagement.Domain" />
<PackageReference Include="LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.LocalizationManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.AspNetCore.Session" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.AspNetCore" />
<PackageReference Include="LINGYUN.Abp.IM.SignalR" />
<PackageReference Include="LINGYUN.Abp.IM" />
<PackageReference Include="LINGYUN.Abp.MessageService.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.MessageService.Application" />
<PackageReference Include="LINGYUN.Abp.MessageService.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.MessageService.Domain" />
<PackageReference Include="LINGYUN.Abp.MessageService.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.MessageService.HttpApi" />
<PackageReference Include="LINGYUN.Abp.ExceptionHandling.Notifications" />
<PackageReference Include="LINGYUN.Abp.Notifications.Common" />
<PackageReference Include="LINGYUN.Abp.Notifications.Core" />
<PackageReference Include="LINGYUN.Abp.Notifications.Emailing" />
<PackageReference Include="LINGYUN.Abp.Notifications.SignalR" />
<PackageReference Include="LINGYUN.Abp.Notifications.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.Notifications.Application" />
<PackageReference Include="LINGYUN.Abp.Notifications.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.Notifications.Domain" />
<PackageReference Include="LINGYUN.Abp.Notifications.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.Notifications.HttpApi" />
<PackageReference Include="LINGYUN.Abp.Notifications.WeChat.MiniProgram" />
<PackageReference Include="LINGYUN.Abp.Notifications.WeChat.Work" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.Application" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.HttpApi" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.LinkUser" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.Sms" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.Portal" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.WeChat" />
<PackageReference Include="LINGYUN.Abp.OpenIddict.WeChat.Work" />
<PackageReference Include="LINGYUN.Abp.OssManagement.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.OssManagement.Application" />
<PackageReference Include="LINGYUN.Abp.OssManagement.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.OssManagement.Domain" />
<PackageReference Include="LINGYUN.Abp.OssManagement.FileSystem" />
<!-- <PackageReference Include="LINGYUN.Abp.OssManagement.Imaging" />-->
<!-- <PackageReference Include="LINGYUN.Abp.OssManagement.Minio" />-->
<PackageReference Include="LINGYUN.Abp.OssManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.OssManagement.SettingManagement" />
<PackageReference Include="LINGYUN.Abp.PermissionManagement.Application" />
<PackageReference Include="LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits" />
<PackageReference Include="LINGYUN.Abp.PermissionManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.UI.Navigation.VueVbenAdmin" />
<PackageReference Include="LINGYUN.Platform.Application.Contracts" />
<PackageReference Include="LINGYUN.Platform.Application" />
<PackageReference Include="LINGYUN.Platform.Application.Contracts" />
<PackageReference Include="LINGYUN.Platform.Application" />
<PackageReference Include="LINGYUN.Platform.Domain.Shared" />
<PackageReference Include="LINGYUN.Platform.Domain" />
<PackageReference Include="LINGYUN.Platform.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Platform.HttpApi" />
<PackageReference Include="LINGYUN.Platform.Settings.VueVbenAdmin" />
<PackageReference Include="LINGYUN.Platform.Theme.VueVbenAdmin" />
<PackageReference Include="LINGYUN.Abp.Saas.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.Saas.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.Saas.Domain" />
<PackageReference Include="LINGYUN.Abp.Saas.Application" />
<PackageReference Include="LINGYUN.Abp.Saas.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.Saas.HttpApi" />
<PackageReference Include="LINGYUN.Abp.SettingManagement.Application" />
<PackageReference Include="LINGYUN.Abp.SettingManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.Abstractions" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.Activities" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.DistributedLocking" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.EventBus" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.ExceptionHandling" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.Jobs" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.Notifications" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks.Quartz" />
<PackageReference Include="LINGYUN.Abp.BackgroundTasks" />
<PackageReference Include="LINGYUN.Abp.TaskManagement.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.TaskManagement.Application" />
<PackageReference Include="LINGYUN.Abp.TaskManagement.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.TaskManagement.Domain" />
<PackageReference Include="LINGYUN.Abp.TaskManagement.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.TaskManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.TextTemplating.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.TextTemplating.Application" />
<PackageReference Include="LINGYUN.Abp.TextTemplating.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.TextTemplating.Domain" />
<PackageReference Include="LINGYUN.Abp.TextTemplating.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.TextTemplating.HttpApi" />
<PackageReference Include="LINGYUN.Abp.Webhooks.Core" />
<PackageReference Include="LINGYUN.Abp.Webhooks.EventBus" />
<PackageReference Include="LINGYUN.Abp.Webhooks.Identity" />
<PackageReference Include="LINGYUN.Abp.Webhooks.Saas" />
<PackageReference Include="LINGYUN.Abp.WebhooksManagement.Application.Contracts" />
<PackageReference Include="LINGYUN.Abp.WebhooksManagement.Application" />
<PackageReference Include="LINGYUN.Abp.WebhooksManagement.Domain.Shared" />
<PackageReference Include="LINGYUN.Abp.WebhooksManagement.Domain" />
<PackageReference Include="LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore" />
<PackageReference Include="LINGYUN.Abp.WebhooksManagement.HttpApi" />
<PackageReference Include="LINGYUN.Abp.Webhooks" />
</ItemGroup>
<ItemGroup>
<Folder Include="blobs\host\public\" />
</ItemGroup>
<ItemGroup>
<None Remove="blobs\host\public\iShot_2024-12-04_11.51.43.png" />
</ItemGroup>
</Project>

935
aspnet-core/services/LY.AIO.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs

@ -0,0 +1,935 @@
using Elsa;
using Elsa.Options;
using LINGYUN.Abp.Aliyun.Localization;
using LINGYUN.Abp.BackgroundTasks;
using LINGYUN.Abp.DataProtectionManagement;
using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Exporter.MiniExcel;
using LINGYUN.Abp.Idempotent;
using LINGYUN.Abp.Identity.Session;
using LINGYUN.Abp.IdentityServer.IdentityResources;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.Notifications;
using LINGYUN.Abp.OpenIddict.AspNetCore.Session;
using LINGYUN.Abp.OpenIddict.LinkUser;
using LINGYUN.Abp.OpenIddict.Permissions;
using LINGYUN.Abp.OpenIddict.Portal;
using LINGYUN.Abp.OpenIddict.Sms;
using LINGYUN.Abp.OpenIddict.WeChat;
using LINGYUN.Abp.Saas;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
using LINGYUN.Abp.Tencent.Localization;
using LINGYUN.Abp.TextTemplating;
using LINGYUN.Abp.WebhooksManagement;
using LINGYUN.Abp.WeChat.Common.Messages.Handlers;
using LINGYUN.Abp.WeChat.Localization;
using LINGYUN.Abp.WeChat.Work;
using LINGYUN.Abp.Wrapper;
using LINGYUN.Platform.Localization;
using LY.AIO.Applications.Single.Authentication;
using LY.AIO.Applications.Single.IdentityResources;
using LY.AIO.Applications.Single.Microsoft.Extensions.DependencyInjection;
using LY.AIO.Applications.Single.WeChat.Official.Messages;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.IdentityModel.Logging;
using Microsoft.OpenApi.Models;
using MiniExcelLibs.Attributes;
using OpenIddict.Server;
using OpenIddict.Server.AspNetCore;
using Quartz;
using StackExchange.Redis;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.Auditing;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.Caching;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Features;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Http.Client;
using Volo.Abp.Identity.Localization;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.OpenIddict;
using Volo.Abp.OpenIddict.Localization;
using Volo.Abp.PermissionManagement;
using Volo.Abp.Quartz;
using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement;
using Volo.Abp.SettingManagement.Localization;
using Volo.Abp.Threading;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
using VoloAbpExceptionHandlingOptions = Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingOptions;
namespace LY.AIO.Applications.Single;
public partial class MicroServiceApplicationsSingleModule
{
protected const string DefaultCorsPolicyName = "Default";
public static string ApplicationName { get; set; } = "MicroService-Applications-Single";
private readonly static OneTimeRunner OneTimeRunner = new();
private void PreConfigureFeature()
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Modules.Editions().EnableAll();
});
}
private void PreConfigureApp(IConfiguration configuration)
{
AbpSerilogEnrichersConsts.ApplicationName = ApplicationName;
PreConfigure<AbpSerilogEnrichersUniqueIdOptions>(options =>
{
// 以开放端口区别,应在0-31之间
options.SnowflakeIdOptions.WorkerId = 1;
options.SnowflakeIdOptions.WorkerIdBits = 5;
options.SnowflakeIdOptions.DatacenterId = 1;
});
if (configuration.GetValue<bool>("App:ShowPii"))
{
IdentityModelEventSource.ShowPII = true;
}
}
private void PreConfigureAuthServer(IConfiguration configuration)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
//options.AddAudiences("lingyun-abp-application");
options.UseLocalServer();
options.UseAspNetCore();
options.UseDataProtection();
});
});
}
private void PreConfigureIdentity()
{
PreConfigure<IdentityBuilder>(builder =>
{
builder.AddDefaultTokenProviders();
});
}
private void PreConfigureCertificate(IConfiguration configuration, IWebHostEnvironment environment)
{
var cerConfig = configuration.GetSection("Certificates");
if (environment.IsProduction() && cerConfig.Exists())
{
// 开发环境下存在证书配置
// 且证书文件存在则使用自定义的证书文件来启动Ids服务器
var cerPath = Path.Combine(environment.ContentRootPath, cerConfig["CerPath"]);
if (File.Exists(cerPath))
{
var certificate = new X509Certificate2(cerPath, cerConfig["Password"]);
if (configuration.GetValue<bool>("AuthServer:UseOpenIddict"))
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
//https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.AddSigningCertificate(certificate);
builder.AddEncryptionCertificate(certificate);
builder.UseDataProtection();
// 禁用https
builder.UseAspNetCore()
.DisableTransportSecurityRequirement();
});
}
else
{
PreConfigure<AbpIdentityServerBuilderOptions>(options =>
{
options.AddDeveloperSigningCredential = false;
});
PreConfigure<IIdentityServerBuilder>(builder =>
{
builder.AddSigningCredential(certificate);
});
}
}
}
else
{
if (configuration.GetValue<bool>("AuthServer:UseOpenIddict"))
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
//https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(builder =>
{
//https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html
using (var algorithm = RSA.Create(keySizeInBits: 2048))
{
var subject = new X500DistinguishedName("CN=Fabrikam Encryption Certificate");
var request = new CertificateRequest(subject, algorithm, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, critical: true));
var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(2));
builder.AddSigningCertificate(certificate);
}
using (var algorithm = RSA.Create(keySizeInBits: 2048))
{
var subject = new X500DistinguishedName("CN=Fabrikam Signing Certificate");
var request = new CertificateRequest(subject, algorithm, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, critical: true));
var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(2));
builder.AddEncryptionCertificate(certificate);
}
builder.UseDataProtection();
// 禁用https
builder.UseAspNetCore()
.DisableTransportSecurityRequirement();
});
}
}
}
private void PreConfigureQuartz(IConfiguration configuration)
{
PreConfigure<AbpQuartzOptions>(options =>
{
// 如果使用持久化存储, 则配置quartz持久层
if (configuration.GetSection("Quartz:UsePersistentStore").Get<bool>())
{
var settings = configuration.GetSection("Quartz:Properties").Get<Dictionary<string, string>>();
if (settings != null)
{
foreach (var setting in settings)
{
options.Properties[setting.Key] = setting.Value;
}
}
options.Configurator += (config) =>
{
config.UsePersistentStore(store =>
{
store.UseProperties = false;
store.UseNewtonsoftJsonSerializer();
});
};
}
});
}
private void PreConfigureElsa(IServiceCollection services, IConfiguration configuration)
{
var elsaSection = configuration.GetSection("Elsa");
var startups = new[]
{
typeof(Elsa.Activities.Console.Startup),
typeof(Elsa.Activities.Http.Startup),
typeof(Elsa.Activities.UserTask.Startup),
typeof(Elsa.Activities.Temporal.Quartz.Startup),
typeof(Elsa.Activities.Email.Startup),
typeof(Elsa.Scripting.JavaScript.Startup),
typeof(Elsa.Activities.Webhooks.Startup),
};
PreConfigure<ElsaOptionsBuilder>(elsa =>
{
elsa
.AddActivitiesFrom<MicroServiceApplicationsSingleModule>()
.AddWorkflowsFrom<MicroServiceApplicationsSingleModule>()
.AddFeatures(startups, configuration)
.ConfigureWorkflowChannels(options => elsaSection.GetSection("WorkflowChannels").Bind(options));
elsa.DistributedLockingOptionsBuilder
.UseProviderFactory(sp => name =>
{
var provider = sp.GetRequiredService<IDistributedLockProvider>();
return provider.CreateLock(name);
});
});
services.AddNotificationHandlersFrom<MicroServiceApplicationsSingleModule>();
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(Elsa.Webhooks.Api.Endpoints.List).Assembly);
});
}
private void ConfigureAuthServer(IConfiguration configuration)
{
Configure<OpenIddictServerAspNetCoreBuilder>(builder =>
{
builder.DisableTransportSecurityRequirement();
});
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
Configure<OpenIddictServerOptions>(options =>
{
var lifetime = configuration.GetSection("OpenIddict:Lifetime");
options.AuthorizationCodeLifetime = lifetime.GetValue("AuthorizationCode", options.AuthorizationCodeLifetime);
options.AccessTokenLifetime = lifetime.GetValue("AccessToken", options.AccessTokenLifetime);
options.DeviceCodeLifetime = lifetime.GetValue("DeviceCode", options.DeviceCodeLifetime);
options.IdentityTokenLifetime = lifetime.GetValue("IdentityToken", options.IdentityTokenLifetime);
options.RefreshTokenLifetime = lifetime.GetValue("RefreshToken", options.RefreshTokenLifetime);
options.RefreshTokenReuseLeeway = lifetime.GetValue("RefreshTokenReuseLeeway", options.RefreshTokenReuseLeeway);
options.UserCodeLifetime = lifetime.GetValue("UserCode", options.UserCodeLifetime);
});
Configure<AbpOpenIddictAspNetCoreSessionOptions>(options =>
{
options.PersistentSessionGrantTypes.Add(SmsTokenExtensionGrantConsts.GrantType);
options.PersistentSessionGrantTypes.Add(PortalTokenExtensionGrantConsts.GrantType);
options.PersistentSessionGrantTypes.Add(LinkUserTokenExtensionGrantConsts.GrantType);
options.PersistentSessionGrantTypes.Add(WeChatTokenExtensionGrantConsts.OfficialGrantType);
options.PersistentSessionGrantTypes.Add(WeChatTokenExtensionGrantConsts.MiniProgramGrantType);
options.PersistentSessionGrantTypes.Add(AbpWeChatWorkGlobalConsts.GrantType);
});
}
private void ConfigureEndpoints(IServiceCollection services)
{
// 不需要
//Configure<AbpEndpointRouterOptions>(options =>
//{
// options.EndpointConfigureActions.Add(
// (context) =>
// {
// context.Endpoints.MapFallbackToPage("/_Host");
// });
//});
var preActions = services.GetPreConfigureActions<AbpAspNetCoreMvcOptions>();
services.AddAbpApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true;
//options.ApiVersionReader = new HeaderApiVersionReader("api-version"); //Supports header too
//options.ApiVersionReader = new MediaTypeApiVersionReader(); //Supports accept header too
}, mvcOptions =>
{
mvcOptions.ConfigureAbp(preActions.Configure());
});
//services.AddApiVersioning(config =>
//{
// // Specify the default API Version as 1.0
// config.DefaultApiVersion = new ApiVersion(1, 0);
// // Advertise the API versions supported for the particular endpoint (through 'api-supported-versions' response header which lists all available API versions for that endpoint)
// config.ReportApiVersions = true;
//});
//services.AddVersionedApiExplorer(options =>
//{
// // add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// // note: the specified format code will format the version as "'v'major[.minor][-status]"
// options.GroupNameFormat = "'v'VVV";
// // note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// // can also be used to control the format of the API version in route templates
// options.SubstituteApiVersionInUrl = true;
//});
}
private void ConfigureKestrelServer()
{
Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = null;
options.Limits.MaxRequestBufferSize = null;
});
}
private void ConfigureBlobStoring(IConfiguration configuration)
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseFileSystem(fileSystem =>
{
fileSystem.BasePath = Path.Combine(Directory.GetCurrentDirectory(), "blobs");
});
//containerConfiguration.UseMinio(minio =>
//{
// configuration.GetSection("Minio").Bind(minio);
//});
});
});
}
private void ConfigureBackgroundTasks()
{
Configure<AbpBackgroundTasksOptions>(options =>
{
options.NodeName = ApplicationName;
options.JobCleanEnabled = true;
options.JobFetchEnabled = true;
options.JobCheckEnabled = true;
});
}
private void ConfigureTextTemplating(IConfiguration configuration)
{
if (configuration.GetValue<bool>("TextTemplating:IsDynamicStoreEnabled"))
{
Configure<AbpTextTemplatingCachingOptions>(options =>
{
options.IsDynamicTemplateDefinitionStoreEnabled = true;
});
}
}
private void ConfigureFeatureManagement(IConfiguration configuration)
{
if (configuration.GetValue<bool>("FeatureManagement:IsDynamicStoreEnabled"))
{
Configure<FeatureManagementOptions>(options =>
{
options.IsDynamicFeatureStoreEnabled = true;
});
}
Configure<FeatureManagementOptions>(options =>
{
options.ProviderPolicies[EditionFeatureValueProvider.ProviderName] = AbpSaasPermissions.Editions.ManageFeatures;
options.ProviderPolicies[TenantFeatureValueProvider.ProviderName] = AbpSaasPermissions.Tenants.ManageFeatures;
});
}
private void ConfigureSettingManagement(IConfiguration configuration)
{
if (configuration.GetValue<bool>("SettingManagement:IsDynamicStoreEnabled"))
{
Configure<SettingManagementOptions>(options =>
{
options.IsDynamicSettingStoreEnabled = true;
});
}
}
private void ConfigureWebhooksManagement(IConfiguration configuration)
{
if (configuration.GetValue<bool>("WebhooksManagement:IsDynamicStoreEnabled"))
{
Configure<WebhooksManagementOptions>(options =>
{
options.IsDynamicWebhookStoreEnabled = true;
});
}
}
/// <summary>
/// 配置数据导出
/// </summary>
private void ConfigureExporter()
{
Configure<AbpExporterMiniExcelOptions>(options =>
{
// options.MapExportSetting(typeof(BookDto), config =>
// {
// config.DynamicColumns = new[]
// {
// // 忽略某些字段
// new DynamicExcelColumn(nameof(BookDto.AuthorId)){ Ignore = true },
// new DynamicExcelColumn(nameof(BookDto.LastModificationTime)){ Ignore = true },
// new DynamicExcelColumn(nameof(BookDto.LastModifierId)){ Ignore = true },
// new DynamicExcelColumn(nameof(BookDto.CreationTime)){ Ignore = true },
// new DynamicExcelColumn(nameof(BookDto.CreatorId)){ Ignore = true },
// new DynamicExcelColumn(nameof(BookDto.Id)){ Ignore = true },
// };
// });
});
}
/// <summary>
/// 配置数据权限
/// </summary>
private void ConfigureEntityDataProtected()
{
// Configure<DataProtectionManagementOptions>(options =>
// {
// options.AddEntities(typeof(DemoResource),
// new[]
// {
// typeof(Book),
// });
// });
}
private void ConfigurePermissionManagement(IConfiguration configuration)
{
if (configuration.GetValue<bool>("PermissionManagement:IsDynamicStoreEnabled"))
{
Configure<PermissionManagementOptions>(options =>
{
options.IsDynamicPermissionStoreEnabled = true;
});
}
Configure<PermissionManagementOptions>(options =>
{
// Rename IdentityServer.Client.ManagePermissions
// See https://github.com/abpframework/abp/blob/dev/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/AbpPermissionManagementDomainIdentityServerModule.cs
options.ProviderPolicies[ClientPermissionValueProvider.ProviderName] = AbpOpenIddictPermissions.Applications.ManagePermissions;
//if (configuration.GetValue<bool>("AuthServer:UseOpenIddict"))
//{
// options.ProviderPolicies[ClientPermissionValueProvider.ProviderName] = AbpOpenIddictPermissions.Applications.ManagePermissions;
//}
//else
//{
// options.ProviderPolicies[ClientPermissionValueProvider.ProviderName] = AbpIdentityServerPermissions.Clients.ManagePermissions;
//}
});
}
private void ConfigureNotificationManagement(IConfiguration configuration)
{
if (configuration.GetValue<bool>("NotificationsManagement:IsDynamicStoreEnabled"))
{
Configure<AbpNotificationsManagementOptions>(options =>
{
options.IsDynamicNotificationsStoreEnabled = true;
});
}
}
private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration)
{
var distributedLockEnabled = configuration["DistributedLock:IsEnabled"];
if (distributedLockEnabled.IsNullOrEmpty() || bool.Parse(distributedLockEnabled))
{
var redis = ConnectionMultiplexer.Connect(configuration["DistributedLock:Redis:Configuration"]);
services.AddSingleton<IDistributedLockProvider>(_ => new RedisDistributedSynchronizationProvider(redis.GetDatabase()));
}
}
private void ConfigureVirtualFileSystem()
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<MicroServiceApplicationsSingleModule>("LY.MicroService.Applications.Single");
});
}
private void ConfigureIdempotent()
{
Configure<AbpIdempotentOptions>(options =>
{
options.IsEnabled = true;
options.DefaultTimeout = 0;
});
}
private void ConfigureDbContext()
{
Configure<AbpDbContextOptions>(options =>
{
// AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);//解决PostgreSql设置为utc时间后无法写入local时区的问题
// options.UseNpgsql();
options.UseMySQL();
});
}
private void ConfigureDataSeeder()
{
Configure<CustomIdentityResourceDataSeederOptions>(options =>
{
options.Resources.Add(new CustomIdentityResources.AvatarUrl());
});
}
private void ConfigureExceptionHandling()
{
// 自定义需要处理的异常
Configure<AbpExceptionHandlingOptions>(options =>
{
// 加入需要处理的异常类型
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>();
options.Handlers.Add<AbpInitializationException>();
options.Handlers.Add<OutOfMemoryException>();
options.Handlers.Add<System.Data.Common.DbException>();
options.Handlers.Add<global::Microsoft.EntityFrameworkCore.DbUpdateException>();
options.Handlers.Add<System.Data.DBConcurrencyException>();
});
// 自定义需要发送邮件通知的异常类型
Configure<AbpEmailExceptionHandlingOptions>(options =>
{
// 是否发送堆栈信息
options.SendStackTrace = true;
// 未指定异常接收者的默认接收邮件
// 指定自己的邮件地址
});
Configure<VoloAbpExceptionHandlingOptions>(options =>
{
options.SendStackTraceToClients = false;
options.SendExceptionsDetailsToClients = false;
});
}
private void ConfigureJsonSerializer(IConfiguration configuration)
{
// 统一时间日期格式
Configure<AbpJsonOptions>(options =>
{
var jsonConfiguration = configuration.GetSection("Json");
if (jsonConfiguration.Exists())
{
jsonConfiguration.Bind(options);
}
});
// 中文序列化的编码问题
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
});
}
private void ConfigureCaching(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options =>
{
configuration.GetSection("DistributedCache").Bind(options);
});
Configure<RedisCacheOptions>(options =>
{
var redisConfig = ConfigurationOptions.Parse(options.Configuration);
options.ConfigurationOptions = redisConfig;
options.InstanceName = configuration["Redis:InstanceName"];
});
}
private void ConfigureMultiTenancy(IConfiguration configuration)
{
// 多租户
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = true;
});
var tenantResolveCfg = configuration.GetSection("App:Domains");
if (tenantResolveCfg.Exists())
{
Configure<AbpTenantResolveOptions>(options =>
{
var domains = tenantResolveCfg.Get<string[]>();
foreach (var domain in domains)
{
options.AddDomainTenantResolver(domain);
}
});
}
}
private void ConfigureAuditing(IConfiguration configuration)
{
Configure<AbpAuditingOptions>(options =>
{
options.ApplicationName = ApplicationName;
// 是否启用实体变更记录
var allEntitiesSelectorIsEnabled = configuration["Auditing:AllEntitiesSelector"];
if (allEntitiesSelectorIsEnabled.IsNullOrWhiteSpace() ||
(bool.TryParse(allEntitiesSelectorIsEnabled, out var enabled) && enabled))
{
options.EntityHistorySelectors.AddAllEntities();
}
});
}
private void ConfigureSwagger(IServiceCollection services)
{
// Swagger
services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "App API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "bearer",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
},
new string[] { }
}
});
options.OperationFilter<TenantHeaderParamter>();
});
}
private void ConfigureIdentity(IConfiguration configuration)
{
// 增加配置文件定义,在新建租户时需要
Configure<IdentityOptions>(options =>
{
var identityConfiguration = configuration.GetSection("Identity");
if (identityConfiguration.Exists())
{
identityConfiguration.Bind(options);
}
});
Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
Configure<IdentitySessionCleanupOptions>(options =>
{
options.IsCleanupEnabled = true;
});
}
private void ConfigureMvcUiTheme()
{
Configure<AbpBundlingOptions>(options =>
{
//options.StyleBundles.Configure(
// LeptonXLiteThemeBundles.Styles.Global,
// bundle =>
// {
// bundle.AddFiles("/global-styles.css");
// }
//);
});
}
private void ConfigureLocalization()
{
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options
.AddLanguagesMapOrUpdate(
"vue-admin-element-ui",
new NameValue("zh-Hans", "zh"),
new NameValue("en", "en"));
// vben admin 语言映射
options
.AddLanguagesMapOrUpdate(
"vben-admin-ui",
new NameValue("zh_CN", "zh-Hans"));
options.Resources.Get<AbpSettingManagementResource>()
.AddBaseTypes(
typeof(IdentityResource),
typeof(AliyunResource),
typeof(TencentCloudResource),
typeof(WeChatResource),
typeof(PlatformResource),
typeof(AbpOpenIddictResource),
typeof(AbpIdentityServerResource));
options.UseAllPersistence();
});
Configure<AbpLocalizationCultureMapOptions>(options =>
{
var zhHansCultureMapInfo = new CultureMapInfo
{
TargetCulture = "zh-Hans",
SourceCultures = new string[] { "zh", "zh_CN", "zh-CN" }
};
options.CulturesMaps.Add(zhHansCultureMapInfo);
options.UiCulturesMaps.Add(zhHansCultureMapInfo);
});
}
private void ConfigureWrapper()
{
Configure<AbpWrapperOptions>(options =>
{
options.IsEnabled = true;
// options.IsWrapUnauthorizedEnabled = true;
options.IgnoreNamespaces.Add("Elsa");
});
}
private void PreConfigureWrapper()
{
//PreConfigure<AbpDaprClientProxyOptions>(options =>
//{
// options.ProxyRequestActions.Add(
// (appid, httprequestmessage) =>
// {
// httprequestmessage.Headers.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true");
// });
//});
PreConfigure<AbpHttpClientBuilderOptions>(options =>
{
options.ProxyClientActions.Add(
(_, _, client) =>
{
client.DefaultRequestHeaders.TryAddWithoutValidation(AbpHttpWrapConsts.AbpDontWrapResult, "true");
});
});
}
private void ConfigureAuditing()
{
Configure<AbpAuditingOptions>(options =>
{
// options.IsEnabledForGetRequests = true;
options.ApplicationName = ApplicationName;
});
}
private void ConfigureUrls(IConfiguration configuration)
{
Configure<AppUrlOptions>(options =>
{
var applicationConfiguration = configuration.GetSection("App:Urls:Applications");
foreach (var appConfig in applicationConfiguration.GetChildren())
{
options.Applications[appConfig.Key].RootUrl = appConfig["RootUrl"];
foreach (var urlsConfig in appConfig.GetSection("Urls").GetChildren())
{
options.Applications[appConfig.Key].Urls[urlsConfig.Key] = urlsConfig.Value;
}
}
});
}
private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false)
{
Configure<AbpAntiForgeryOptions>(options =>
{
options.AutoValidate = false;
});
services.Replace<CookieAuthenticationHandler, AbpCookieAuthenticationHandler>(ServiceLifetime.Scoped);
services.AddAuthentication()
.AddAbpJwtBearer(options =>
{
configuration.GetSection("AuthServer").Bind(options);
options.Events ??= new JwtBearerEvents();
options.Events.OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/api/files")))
{
context.Token = accessToken;
}
return Task.CompletedTask;
};
});
if (!isDevelopment)
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
services
.AddDataProtection()
.SetApplicationName("LINGYUN.Abp.Application")
.PersistKeysToStackExchangeRedis(redis, "LINGYUN.Abp.Application:DataProtection:Protection-Keys");
}
services.AddSameSiteCookiePolicy();
}
private void ConfigureCors(IServiceCollection services, IConfiguration configuration)
{
services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.WithAbpWrapExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
private void ConfigureWeChat()
{
Configure<AbpWeChatMessageHandleOptions>(options =>
{
// 回复文本消息
options.MapMessage<
LINGYUN.Abp.WeChat.Official.Messages.Models.TextMessage,
TextMessageReplyContributor>();
// 处理关注事件
options.MapEvent<
LINGYUN.Abp.WeChat.Official.Messages.Models.UserSubscribeEvent,
UserSubscribeEventContributor>();
options.MapMessage<
LINGYUN.Abp.WeChat.Work.Common.Messages.Models.TextMessage,
WeChat.Work.Messages.TextMessageReplyContributor>();
});
}
}

394
aspnet-core/services/LY.AIO.Applications.Single/MicroServiceApplicationsSingleModule.cs

@ -0,0 +1,394 @@
using LINGYUN.Abp.Account;
using LINGYUN.Abp.Account.Templates;
using LINGYUN.Abp.Aliyun.SettingManagement;
using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper;
using LINGYUN.Abp.AspNetCore.Mvc.Localization;
using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
using LINGYUN.Abp.Auditing;
using LINGYUN.Abp.AuditLogging.EntityFrameworkCore;
using LINGYUN.Abp.Authentication.QQ;
using LINGYUN.Abp.Authentication.WeChat;
using LINGYUN.Abp.Authorization.OrganizationUnits;
using LINGYUN.Abp.BackgroundTasks;
using LINGYUN.Abp.BackgroundTasks.Activities;
using LINGYUN.Abp.BackgroundTasks.DistributedLocking;
using LINGYUN.Abp.BackgroundTasks.EventBus;
using LINGYUN.Abp.BackgroundTasks.ExceptionHandling;
using LINGYUN.Abp.BackgroundTasks.Jobs;
using LINGYUN.Abp.BackgroundTasks.Notifications;
using LINGYUN.Abp.BackgroundTasks.Quartz;
using LINGYUN.Abp.CachingManagement;
using LINGYUN.Abp.CachingManagement.StackExchangeRedis;
using LINGYUN.Abp.Dapr.Client;
using LINGYUN.Abp.Data.DbMigrator;
using LINGYUN.Abp.DataProtectionManagement;
using LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore;
// using LINGYUN.Abp.Demo;
// using LINGYUN.Abp.Demo.EntityFrameworkCore;
using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Exporter.MiniExcel;
using LINGYUN.Abp.FeatureManagement;
using LINGYUN.Abp.FeatureManagement.HttpApi;
using LINGYUN.Abp.Features.LimitValidation;
using LINGYUN.Abp.Features.LimitValidation.Redis.Client;
using LINGYUN.Abp.Http.Client.Wrapper;
using LINGYUN.Abp.Identity;
using LINGYUN.Abp.Identity.AspNetCore.Session;
using LINGYUN.Abp.Identity.EntityFrameworkCore;
using LINGYUN.Abp.Identity.Notifications;
using LINGYUN.Abp.Identity.OrganizaztionUnits;
using LINGYUN.Abp.Identity.Session.AspNetCore;
using LINGYUN.Abp.Identity.WeChat;
using LINGYUN.Abp.IdGenerator;
using LINGYUN.Abp.IM.SignalR;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.Localization.Persistence;
using LINGYUN.Abp.LocalizationManagement;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.MessageService;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using LINGYUN.Abp.MultiTenancy.Editions;
using LINGYUN.Abp.Notifications;
using LINGYUN.Abp.Notifications.Common;
using LINGYUN.Abp.Notifications.Emailing;
using LINGYUN.Abp.Notifications.EntityFrameworkCore;
using LINGYUN.Abp.Notifications.SignalR;
using LINGYUN.Abp.Notifications.WeChat.MiniProgram;
using LINGYUN.Abp.OpenApi.Authorization;
using LINGYUN.Abp.OpenIddict;
using LINGYUN.Abp.OpenIddict.AspNetCore;
using LINGYUN.Abp.OpenIddict.AspNetCore.Session;
using LINGYUN.Abp.OpenIddict.Portal;
using LINGYUN.Abp.OpenIddict.Sms;
using LINGYUN.Abp.OpenIddict.WeChat;
using LINGYUN.Abp.OpenIddict.WeChat.Work;
using LINGYUN.Abp.OssManagement;
using LINGYUN.Abp.OssManagement.FileSystem;
// using LINGYUN.Abp.OssManagement.Imaging;
using LINGYUN.Abp.OssManagement.SettingManagement;
using LINGYUN.Abp.PermissionManagement;
using LINGYUN.Abp.PermissionManagement.HttpApi;
using LINGYUN.Abp.PermissionManagement.OrganizationUnits;
using LINGYUN.Abp.Saas;
using LINGYUN.Abp.Saas.EntityFrameworkCore;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
using LINGYUN.Abp.SettingManagement;
using LINGYUN.Abp.Sms.Aliyun;
using LINGYUN.Abp.TaskManagement;
using LINGYUN.Abp.TaskManagement.EntityFrameworkCore;
using LINGYUN.Abp.Tencent.QQ;
using LINGYUN.Abp.Tencent.SettingManagement;
using LINGYUN.Abp.TextTemplating;
using LINGYUN.Abp.TextTemplating.EntityFrameworkCore;
using LINGYUN.Abp.UI.Navigation;
using LINGYUN.Abp.UI.Navigation.VueVbenAdmin;
using LINGYUN.Abp.Webhooks;
using LINGYUN.Abp.Webhooks.EventBus;
using LINGYUN.Abp.Webhooks.Identity;
using LINGYUN.Abp.Webhooks.Saas;
using LINGYUN.Abp.WebhooksManagement;
using LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore;
using LINGYUN.Abp.WeChat.MiniProgram;
using LINGYUN.Abp.WeChat.Official;
using LINGYUN.Abp.WeChat.Official.Handlers;
using LINGYUN.Abp.WeChat.SettingManagement;
using LINGYUN.Abp.WeChat.Work;
using LINGYUN.Abp.WeChat.Work.Handlers;
using LINGYUN.Platform;
using LINGYUN.Platform.EntityFrameworkCore;
using LINGYUN.Platform.HttpApi;
using LINGYUN.Platform.Settings.VueVbenAdmin;
using LINGYUN.Platform.Theme.VueVbenAdmin;
using Volo.Abp;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore.PostgreSql;
using Volo.Abp.EventBus;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Imaging;
using Volo.Abp.Modularity;
using Volo.Abp.OpenIddict.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.PermissionManagement.OpenIddict;
using Volo.Abp.SettingManagement;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.Threading;
// using LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql;
using Volo.Abp.EntityFrameworkCore.MySQL;
namespace LY.AIO.Applications.Single;
[DependsOn(
typeof(AbpAccountApplicationModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpAccountWebOpenIddictModule),
typeof(AbpAuditingApplicationModule),
typeof(AbpAuditingHttpApiModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule),
typeof(AbpCachingManagementStackExchangeRedisModule),
typeof(AbpCachingManagementApplicationModule),
typeof(AbpCachingManagementHttpApiModule),
typeof(AbpIdentityAspNetCoreSessionModule),
typeof(AbpIdentitySessionAspNetCoreModule),
typeof(AbpIdentityNotificationsModule),
typeof(AbpIdentityDomainModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpIdentityHttpApiModule),
typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpLocalizationManagementDomainModule),
typeof(AbpLocalizationManagementApplicationModule),
typeof(AbpLocalizationManagementHttpApiModule),
typeof(AbpLocalizationManagementEntityFrameworkCoreModule),
typeof(AbpSerilogEnrichersApplicationModule),
typeof(AbpSerilogEnrichersUniqueIdModule),
typeof(AbpMessageServiceDomainModule),
typeof(AbpMessageServiceApplicationModule),
typeof(AbpMessageServiceHttpApiModule),
typeof(AbpMessageServiceEntityFrameworkCoreModule),
typeof(AbpNotificationsDomainModule),
typeof(AbpNotificationsApplicationModule),
typeof(AbpNotificationsHttpApiModule),
typeof(AbpNotificationsEntityFrameworkCoreModule),
//typeof(AbpIdentityServerSessionModule),
//typeof(AbpIdentityServerApplicationModule),
//typeof(AbpIdentityServerHttpApiModule),
//typeof(AbpIdentityServerEntityFrameworkCoreModule),
typeof(AbpOpenIddictAspNetCoreModule),
typeof(AbpOpenIddictAspNetCoreSessionModule),
typeof(AbpOpenIddictApplicationModule),
typeof(AbpOpenIddictHttpApiModule),
typeof(AbpOpenIddictEntityFrameworkCoreModule),
typeof(AbpOpenIddictSmsModule),
typeof(AbpOpenIddictPortalModule),
typeof(AbpOpenIddictWeChatModule),
typeof(AbpOpenIddictWeChatWorkModule),
//typeof(AbpOssManagementMinioModule), // 取消注释以使用Minio
typeof(AbpOssManagementFileSystemModule),
// typeof(AbpOssManagementImagingModule),
typeof(AbpOssManagementDomainModule),
typeof(AbpOssManagementApplicationModule),
typeof(AbpOssManagementHttpApiModule),
typeof(AbpOssManagementSettingManagementModule),
typeof(AbpImagingImageSharpModule),
typeof(PlatformDomainModule),
typeof(PlatformApplicationModule),
typeof(PlatformHttpApiModule),
typeof(PlatformEntityFrameworkCoreModule),
typeof(PlatformSettingsVueVbenAdminModule),
typeof(PlatformThemeVueVbenAdminModule),
typeof(AbpUINavigationVueVbenAdminModule),
typeof(AbpSaasDomainModule),
typeof(AbpSaasApplicationModule),
typeof(AbpSaasHttpApiModule),
typeof(AbpSaasEntityFrameworkCoreModule),
typeof(TaskManagementDomainModule),
typeof(TaskManagementApplicationModule),
typeof(TaskManagementHttpApiModule),
typeof(TaskManagementEntityFrameworkCoreModule),
typeof(AbpTextTemplatingDomainModule),
typeof(AbpTextTemplatingApplicationModule),
typeof(AbpTextTemplatingHttpApiModule),
typeof(AbpTextTemplatingEntityFrameworkCoreModule),
typeof(AbpWebhooksModule),
typeof(AbpWebhooksEventBusModule),
typeof(AbpWebhooksIdentityModule),
typeof(AbpWebhooksSaasModule),
typeof(WebhooksManagementDomainModule),
typeof(WebhooksManagementApplicationModule),
typeof(WebhooksManagementHttpApiModule),
typeof(WebhooksManagementEntityFrameworkCoreModule),
typeof(AbpFeatureManagementApplicationModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementDomainModule),
typeof(AbpSettingManagementApplicationModule),
typeof(AbpSettingManagementHttpApiModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpPermissionManagementHttpApiModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpPermissionManagementDomainOpenIddictModule),
// typeof(AbpPermissionManagementDomainIdentityServerModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementDomainOrganizationUnitsModule), // 组织机构权限管理
// typeof(AbpEntityFrameworkCorePostgreSqlModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
typeof(AbpAliyunSmsModule),
typeof(AbpAliyunSettingManagementModule),
typeof(AbpAuthenticationQQModule),
typeof(AbpAuthenticationWeChatModule),
typeof(AbpAuthorizationOrganizationUnitsModule),
typeof(AbpIdentityOrganizaztionUnitsModule),
typeof(AbpBackgroundTasksModule),
typeof(AbpBackgroundTasksActivitiesModule),
typeof(AbpBackgroundTasksDistributedLockingModule),
typeof(AbpBackgroundTasksEventBusModule),
typeof(AbpBackgroundTasksExceptionHandlingModule),
typeof(AbpBackgroundTasksJobsModule),
typeof(AbpBackgroundTasksNotificationsModule),
typeof(AbpBackgroundTasksQuartzModule),
typeof(AbpDataProtectionManagementApplicationModule),
typeof(AbpDataProtectionManagementHttpApiModule),
typeof(AbpDataProtectionManagementEntityFrameworkCoreModule),
// typeof(AbpDemoApplicationModule),
// typeof(AbpDemoHttpApiModule),
// typeof(AbpDemoEntityFrameworkCoreModule),
typeof(AbpDaprClientModule),
typeof(AbpExceptionHandlingModule),
typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpFeaturesLimitValidationModule),
typeof(AbpFeaturesValidationRedisClientModule),
typeof(AbpAspNetCoreMvcLocalizationModule),
typeof(AbpLocalizationCultureMapModule),
typeof(AbpLocalizationPersistenceModule),
typeof(AbpOpenApiAuthorizationModule),
typeof(AbpIMSignalRModule),
typeof(AbpNotificationsModule),
typeof(AbpNotificationsCommonModule),
typeof(AbpNotificationsSignalRModule),
typeof(AbpNotificationsEmailingModule),
typeof(AbpMultiTenancyEditionsModule),
typeof(AbpTencentQQModule),
typeof(AbpTencentCloudSettingManagementModule),
typeof(AbpIdentityWeChatModule),
typeof(AbpNotificationsWeChatMiniProgramModule),
typeof(AbpWeChatMiniProgramModule),
typeof(AbpWeChatOfficialModule),
typeof(AbpWeChatOfficialApplicationModule),
typeof(AbpWeChatOfficialHttpApiModule),
typeof(AbpWeChatWorkModule),
typeof(AbpWeChatWorkApplicationModule),
typeof(AbpWeChatWorkHttpApiModule),
typeof(AbpWeChatOfficialHandlersModule),
typeof(AbpWeChatWorkHandlersModule),
typeof(AbpWeChatSettingManagementModule),
typeof(AbpDataDbMigratorModule),
typeof(AbpIdGeneratorModule),
typeof(AbpUINavigationModule),
typeof(AbpAccountTemplatesModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpCachingStackExchangeRedisModule),
// typeof(AbpElsaModule),
// typeof(AbpElsaServerModule),
// typeof(AbpElsaActivitiesModule),
// typeof(AbpElsaEntityFrameworkCoreModule),
// typeof(AbpElsaEntityFrameworkCorePostgreSqlModule),
// typeof(AbpElsaModule),
// typeof(AbpElsaServerModule),
// typeof(AbpElsaActivitiesModule),
// typeof(AbpElsaEntityFrameworkCoreModule),
// typeof(AbpElsaEntityFrameworkCoreMySqlModule),
typeof(AbpExporterMiniExcelModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpHttpClientWrapperModule),
typeof(AbpAspNetCoreMvcWrapperModule),
typeof(AbpAspNetCoreMvcIdempotentWrapperModule),
typeof(AbpAspNetCoreHttpOverridesModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpEventBusModule),
typeof(AbpAutofacModule)
)]
public partial class MicroServiceApplicationsSingleModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
PreConfigureWrapper();
PreConfigureFeature();
PreConfigureIdentity();
PreConfigureApp(configuration);
PreConfigureQuartz(configuration);
PreConfigureAuthServer(configuration);
PreConfigureElsa(context.Services, configuration);
PreConfigureCertificate(configuration, hostingEnvironment);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
ConfigureWeChat();
ConfigureWrapper();
ConfigureExporter();
ConfigureAuditing();
ConfigureDbContext();
ConfigureIdempotent();
ConfigureMvcUiTheme();
ConfigureDataSeeder();
ConfigureLocalization();
ConfigureKestrelServer();
ConfigureBackgroundTasks();
ConfigureExceptionHandling();
ConfigureVirtualFileSystem();
ConfigureEntityDataProtected();
ConfigureUrls(configuration);
ConfigureCaching(configuration);
ConfigureAuditing(configuration);
ConfigureIdentity(configuration);
ConfigureAuthServer(configuration);
ConfigureSwagger(context.Services);
ConfigureEndpoints(context.Services);
ConfigureBlobStoring(configuration);
ConfigureMultiTenancy(configuration);
ConfigureJsonSerializer(configuration);
ConfigureTextTemplating(configuration);
ConfigureFeatureManagement(configuration);
ConfigureSettingManagement(configuration);
ConfigureWebhooksManagement(configuration);
ConfigurePermissionManagement(configuration);
ConfigureNotificationManagement(configuration);
ConfigureCors(context.Services, configuration);
ConfigureDistributedLock(context.Services, configuration);
ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment());
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
AsyncHelper.RunSync(async () => await OnApplicationInitializationAsync(context));
}
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
await context.ServiceProvider.GetRequiredService<IDataSeeder>().SeedAsync(); ;
}
}

67
aspnet-core/services/LY.AIO.Applications.Single/Microsoft/Extensions/DependencyInjection/SameSiteCookiesServiceCollectionExtensions.cs

@ -0,0 +1,67 @@
namespace LY.AIO.Applications.Single.Microsoft.Extensions.DependencyInjection
{
public static class SameSiteCookiesServiceCollectionExtensions
{
public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
return services;
}
private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent))
{
// For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1)
options.SameSite = SameSiteMode.Unspecified;
}
}
}
private static bool DisallowsSameSiteNone(string userAgent)
{
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the iOS networking stack
if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))
{
return true;
}
// Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// Because they do not use the Mac OS networking stack.
if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
userAgent.Contains("Version/") && userAgent.Contains("Safari"))
{
return true;
}
// Cover Chrome 50-69, because some versions are broken by SameSite=None,
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
}
return false;
}
}
}

10
aspnet-core/services/LY.AIO.Applications.Single/MultiTenancy/ITenantConfigurationCache.cs

@ -0,0 +1,10 @@
using Volo.Abp.MultiTenancy;
namespace LY.AIO.Applications.Single.MultiTenancy;
public interface ITenantConfigurationCache
{
Task RefreshAsync();
Task<List<TenantConfiguration>> GetTenantsAsync();
}

59
aspnet-core/services/LY.AIO.Applications.Single/MultiTenancy/TenantConfigurationCache.cs

@ -0,0 +1,59 @@
using LINGYUN.Abp.Saas.Tenants;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace LY.AIO.Applications.Single.MultiTenancy;
public class TenantConfigurationCache : ITenantConfigurationCache, ITransientDependency
{
protected ITenantRepository TenantRepository { get; }
protected IDistributedCache<TenantConfigurationCacheItem> TenantCache { get; }
public TenantConfigurationCache(
ITenantRepository tenantRepository,
IDistributedCache<TenantConfigurationCacheItem> tenantCache)
{
TenantRepository = tenantRepository;
TenantCache = tenantCache;
}
public async virtual Task RefreshAsync()
{
var cacheKey = GetCacheKey();
await TenantCache.RemoveAsync(cacheKey);
}
public async virtual Task<List<TenantConfiguration>> GetTenantsAsync()
{
return (await GetForCacheItemAsync()).Tenants;
}
protected async virtual Task<TenantConfigurationCacheItem> GetForCacheItemAsync()
{
var cacheKey = GetCacheKey();
var cacheItem = await TenantCache.GetAsync(cacheKey);
if (cacheItem == null)
{
var allActiveTenants = await TenantRepository.GetListAsync();
cacheItem = new TenantConfigurationCacheItem(
allActiveTenants
.Where(t => t.IsActive)
.Select(t => new TenantConfiguration(t.Id, t.Name)
{
IsActive = t.IsActive,
}).ToList());
await TenantCache.SetAsync(cacheKey, cacheItem);
}
return cacheItem;
}
protected virtual string GetCacheKey()
{
return "_Abp_Tenant_Configuration";
}
}

19
aspnet-core/services/LY.AIO.Applications.Single/MultiTenancy/TenantConfigurationCacheItem.cs

@ -0,0 +1,19 @@
using Volo.Abp.MultiTenancy;
namespace LY.AIO.Applications.Single.MultiTenancy;
[IgnoreMultiTenancy]
public class TenantConfigurationCacheItem
{
public List<TenantConfiguration> Tenants { get; set; }
public TenantConfigurationCacheItem()
{
Tenants = new List<TenantConfiguration>();
}
public TenantConfigurationCacheItem(List<TenantConfiguration> tenants)
{
Tenants = tenants;
}
}

103
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml

@ -0,0 +1,103 @@
@using Volo.Abp.Account.Localization
@using Volo.Abp.Users
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Localization
@using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@using Volo.Abp.Data
@using Volo.Abp.Identity.Settings
@using Volo.Abp.Localization
@using Volo.Abp.Settings
@using Volo.Abp.ObjectExtending
@inject IHtmlLocalizer<AccountResource> L
@inject ICurrentUser CurrentUser
@inject ISettingProvider SettingManager
@inject IThemeManager ThemeManager
@inject IStringLocalizerFactory StringLocalizerFactory
@model Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo.AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel
@{
var isUserNameUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled), "true",
StringComparison.OrdinalIgnoreCase);
var isEmailUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsEmailUpdateEnabled), "true",
StringComparison.OrdinalIgnoreCase);
}
<h4>@L["PersonalSettings"]</h4><hr/>
<form method="post" id="PersonalSettingsForm">
<input asp-for="ConcurrencyStamp" />
<abp-input asp-for="UserName" readonly="!isUserNameUpdateEnabled"/>
<abp-row>
<abp-column size-md="_6">
<abp-input asp-for="Name"/>
</abp-column>
<abp-column size-md="_6">
<abp-input asp-for="Surname"/>
</abp-column>
</abp-row>
<abp-row>
<abp-column size-md="_9">
<abp-input asp-for="Email" readonly="!isEmailUpdateEnabled"/>
</abp-column>
<abp-column size-md="_3">
@if (CurrentUser.EmailVerified)
{
<abp-button button-type="Success" text="@L["Confirmed"].Value"/>
}
else
{
@*<abp-button href="/Account/SendEmailConfirm" button-type="Link" text="@L["Validation"].Value" />*@
<a href="/Account/SendEmailConfirm">@L["Validation"].Value</a>
}
</abp-column>
</abp-row>
<abp-input asp-for="PhoneNumber"/>
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel>())
{
var isAllowed = propertyInfo.Configuration.GetOrDefault(IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit);
if (isAllowed == null || !isAllowed.Equals(true))
{
continue;
}
if (!propertyInfo.Name.EndsWith("_Text"))
{
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
{
if (propertyInfo.Type.IsEnum)
{
Model.ExtraProperties.ToEnum(propertyInfo.Name, propertyInfo.Type);
}
<abp-select asp-for="ExtraProperties[propertyInfo.Name]"
name="ExtraProperties.@propertyInfo.Name"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-selected-item-name="@Model.GetProperty(propertyInfo.Name + "_Text")"
autocomplete-selected-item-value="@Model.GetProperty(propertyInfo.Name)"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName">
</abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="ExtraProperties[propertyInfo.Name]"
name="ExtraProperties.@propertyInfo.Name"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.GetProperty(propertyInfo.Name))" />
}
}
}
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>

28
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js

@ -0,0 +1,28 @@
(function ($) {
$(function () {
var l = abp.localization.getResource("AbpAccount");
$('#PersonalSettingsForm').submit(function (e) {
e.preventDefault();
if (!$('#PersonalSettingsForm').valid()) {
return false;
}
var input = $('#PersonalSettingsForm').serializeFormToObject();
volo.abp.account.profile.update(input).then(function (result) {
abp.notify.success(l('PersonalSettingsSaved'));
updateConcurrencyStamp();
});
});
});
abp.event.on('passwordChanged', updateConcurrencyStamp);
function updateConcurrencyStamp(){
volo.abp.account.profile.get().then(function(profile){
$("#ConcurrencyStamp").val(profile.concurrencyStamp);
});
}
})(jQuery);

17
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirm.cshtml

@ -0,0 +1,17 @@
@page
@inject IHtmlLocalizer<AccountResource> L
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@model LY.AIO.Applications.Single.Pages.Account.EmailConfirmModel
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<h4>@L["EmailConfirm"]</h4>
<form method="post">
<abp-input asp-for="UserId"/>
<abp-input asp-for="ConfirmToken"/>
<a abp-button="Secondary" asp-page="./Login">@L["Cancel"]</a>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>
</div>
</div>

72
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirm.cshtml.cs

@ -0,0 +1,72 @@
using LINGYUN.Abp.Account;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace LY.AIO.Applications.Single.Pages.Account
{
public class EmailConfirmModel : AccountPageModel
{
[Required]
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid UserId { get; set; }
[Required]
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ConfirmToken { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
public IMyProfileAppService MyProfileAppService { get; set; }
public EmailConfirmModel()
{
LocalizationResourceType = typeof(AccountResource);
}
public async virtual Task<IActionResult> OnPostAsync()
{
try
{
ValidateModel();
await MyProfileAppService.ConfirmEmailAsync(
new ConfirmEmailInput
{
ConfirmToken = ConfirmToken,
});
}
catch (AbpIdentityResultException e)
{
if (!string.IsNullOrWhiteSpace(e.Message))
{
Alerts.Warning(GetLocalizeExceptionMessage(e));
return Page();
}
throw;
}
catch (AbpValidationException)
{
return Page();
}
return RedirectToPage("./ConfirmEmailConfirmation", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash
});
}
}
}

13
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirmConfirmation.cshtml

@ -0,0 +1,13 @@
@page
@model LY.AIO.Applications.Single.Pages.Account.EmailConfirmConfirmationModel
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@inject IHtmlLocalizer<AccountResource> L
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<h4>@L["EmailConfirm"]</h4>
<p>@L["YourEmailIsSuccessfullyConfirm"]</p>
<a abp-button="Primary" href="@Url.Content(Model.ReturnUrl)">@L["GoToTheApplication"]</a>
</div>
</div>

22
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/EmailConfirmConfirmation.cshtml.cs

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Web.Pages.Account;
namespace LY.AIO.Applications.Single.Pages.Account;
[AllowAnonymous]
public class EmailConfirmConfirmationModel : AccountPageModel
{
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
public async virtual Task<IActionResult> OnGetAsync()
{
ReturnUrl = await GetRedirectUrlAsync(ReturnUrl, ReturnUrlHash);
return Page();
}
}

26
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendCode.cshtml

@ -0,0 +1,26 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@model LY.AIO.Applications.Single.Pages.Account.SendCodeModel
@inject IHtmlLocalizer<AccountResource> L
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<h4>@L["TwoFactor"]</h4>
<form method="post" class="mt-4">
<abp-input asp-for="RememberMe" />
<input asp-for="ReturnUrl" />
<input asp-for="ReturnUrlHash" />
<div class="form-group">
<abp-select asp-for="Input.SelectedProvider" label="@L["SelectedProvider"].Value" asp-items="@Model.Providers"></abp-select>
</div>
<div class="d-grid gap-2">
<abp-button type="submit" button-type="Primary" class="mt-2 mb-3">@L["SendVerifyCode"]</abp-button>
</div>
<a asp-page="./Login" asp-all-route-data="@(new Dictionary<string, string> {{"returnUrl", Model.ReturnUrl}, {"returnUrlHash", Model.ReturnUrlHash}})">
<i class="fa fa-long-arrow-left"></i> @L["Login"]
</a>
</form>
</div>
</div>

125
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendCode.cshtml.cs

@ -0,0 +1,125 @@
using LINGYUN.Abp.Account.Emailing;
using LINGYUN.Abp.Identity.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Volo.Abp;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Sms;
namespace LY.AIO.Applications.Single.Pages.Account
{
public class SendCodeModel : AccountPageModel
{
[BindProperty]
public SendCodeInputModel Input { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public bool RememberMe { get; set; }
public IEnumerable<SelectListItem> Providers { get; set; }
protected ISmsSender SmsSender { get; }
protected IAccountEmailVerifySender AccountEmailVerifySender { get; }
public SendCodeModel(
ISmsSender smsSender,
IAccountEmailVerifySender accountEmailVerifySender)
{
SmsSender = smsSender;
AccountEmailVerifySender = accountEmailVerifySender;
LocalizationResourceType = typeof(AccountResource);
}
public virtual async Task<IActionResult> OnGetAsync()
{
Input = new SendCodeInputModel();
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
// ˫������Ϣ��֤ʧ��,һ�㶼�dz�ʱ�˻����û���Ϣ���
Alerts.Warning(L["TwoFactorAuthenticationInvaidUser"]);
return Page();
}
var userFactors = await UserManager.GetValidTwoFactorProvidersAsync(user);
Providers = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
return Page();
}
public virtual async Task<IActionResult> OnPostAsync()
{
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
Alerts.Warning(L["TwoFactorAuthenticationInvaidUser"]);
return Page();
}
if (Input.SelectedProvider == "Authenticator")
{
// �û�ͨ���ʼ�/�������ӽ�����Ȩҳ��
return RedirectToPage("VerifyAuthenticatorCode", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = RememberMe
});
}
// ������֤��
var code = await UserManager.GenerateTwoFactorTokenAsync(user, Input.SelectedProvider);
if (string.IsNullOrWhiteSpace(code))
{
Alerts.Warning(L["InvaidGenerateTwoFactorToken"]);
return Page();
}
if (Input.SelectedProvider == "Email")
{
await AccountEmailVerifySender
.SendMailLoginVerifyCodeAsync(
code,
user.UserName,
user.Email);
}
else if (Input.SelectedProvider == "Phone")
{
var phoneNumber = await UserManager.GetPhoneNumberAsync(user);
var templateCode = await SettingProvider.GetOrNullAsync(IdentitySettingNames.User.SmsUserSignin);
Check.NotNullOrWhiteSpace(templateCode, nameof(IdentitySettingNames.User.SmsUserSignin));
// TODO: �Ժ���չ����ģ�巢��
var smsMessage = new SmsMessage(phoneNumber, code);
smsMessage.Properties.Add("code", code);
smsMessage.Properties.Add("TemplateCode", templateCode);
await SmsSender.SendAsync(smsMessage);
}
return RedirectToPage("VerifyCode", new
{
provider = Input.SelectedProvider,
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = RememberMe
});
}
}
public class SendCodeInputModel
{
public string SelectedProvider { get; set; }
}
}

16
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendEmailConfirm.cshtml

@ -0,0 +1,16 @@
@page
@inject IHtmlLocalizer<AccountResource> L
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@model LY.AIO.Applications.Single.Pages.Account.SendEmailConfirmModel
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<h4>@L["EmailConfirm"]</h4>
<form method="post">
<abp-input asp-for="Email" readonly="true" />
<a abp-button="Secondary" asp-page="./Login">@L["Cancel"]</a>
<abp-button type="submit" button-type="Primary" text="@L["ClickToValidation"].Value"/>
</form>
</div>
</div>

73
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/SendEmailConfirm.cshtml.cs

@ -0,0 +1,73 @@
using LINGYUN.Abp.Account;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace LY.AIO.Applications.Single.Pages.Account
{
public class SendEmailConfirmModel : AccountPageModel
{
[BindProperty(SupportsGet = true)]
public string Email { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
public IMyProfileAppService MyProfileAppService { get; set; }
public SendEmailConfirmModel()
{
LocalizationResourceType = typeof(AccountResource);
}
public virtual Task<IActionResult> OnGetAsync()
{
Email = CurrentUser.Email;
return Task.FromResult<IActionResult>(Page());
}
public async virtual Task<IActionResult> OnPostAsync()
{
try
{
ValidateModel();
await MyProfileAppService.SendEmailConfirmLinkAsync(
new SendEmailConfirmCodeDto
{
Email = Email,
AppName = "MVC",
ReturnUrl = ReturnUrl,
ReturnUrlHash = ReturnUrlHash
});
}
catch (AbpIdentityResultException e)
{
if (!string.IsNullOrWhiteSpace(e.Message))
{
Alerts.Warning(GetLocalizeExceptionMessage(e));
return Page();
}
throw;
}
catch (AbpValidationException)
{
return Page();
}
return RedirectToPage("~/Account/Manage", new
{
returnUrl = ReturnUrl
});
}
}
}

63
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/TwoFactorSupportedLoginModel.cs

@ -0,0 +1,63 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.Account.Web;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.OpenIddict;
using IdentityOptions = Microsoft.AspNetCore.Identity.IdentityOptions;
namespace LY.AIO.Applications.Single.Pages.Account
{
/// <summary>
/// 重写登录模型,实现双因素登录
/// </summary>
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(LoginModel), typeof(OpenIddictSupportedLoginModel))]
public class TwoFactorSupportedLoginModel : OpenIddictSupportedLoginModel
{
public TwoFactorSupportedLoginModel(
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions,
IOptions<IdentityOptions> identityOptions,
IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache,
AbpOpenIddictRequestHelper openIddictRequestHelper)
: base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache, openIddictRequestHelper)
{
}
protected async override Task<List<ExternalProviderModel>> GetExternalProviders()
{
var providers = await base.GetExternalProviders();
foreach (var provider in providers)
{
var localizedDisplayName = L[provider.DisplayName];
if (localizedDisplayName.ResourceNotFound)
{
localizedDisplayName = L["AuthenticationScheme:" + provider.DisplayName];
}
if (!localizedDisplayName.ResourceNotFound)
{
provider.DisplayName = localizedDisplayName.Value;
}
}
return providers;
}
protected override Task<IActionResult> TwoFactorLoginResultAsync()
{
// 重定向双因素认证页面
return Task.FromResult<IActionResult>(RedirectToPage("SendCode", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = LoginInput.RememberMe
}));
}
}
}

4
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/UseRecoveryCode.cshtml

@ -0,0 +1,4 @@
@page
@model LY.AIO.Applications.Single.Pages.Account.UseRecoveryCodeModel
@{
}

11
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/UseRecoveryCode.cshtml.cs

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace LY.AIO.Applications.Single.Pages.Account
{
public class UseRecoveryCodeModel : PageModel
{
public void OnGet()
{
}
}
}

26
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyAuthenticatorCode.cshtml

@ -0,0 +1,26 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@model LY.AIO.Applications.Single.Pages.Account.VerifyAuthenticatorCodeModel
@inject IHtmlLocalizer<AccountResource> L
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<form method="post" class="mt-4">
<input asp-for="RememberMe" />
<input asp-for="ReturnUrlHash" />
<div class="form-group">
<label asp-for="Input.VerifyCode"></label>
<input asp-for="Input.VerifyCode" class="form-control" />
<span asp-validation-for="Input.VerifyCode" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RememberBrowser"></label>
<abp-input asp-for="RememberBrowser" />
</div>
<abp-button type="submit" button-type="Primary" class="btn-block btn-lg mt-3">@L["VerifyAuthenticatorCode"]</abp-button>
<a asp-page="./Login" asp-all-route-data="@(new Dictionary<string, string> {{"returnUrl", Model.ReturnUrl}, {"returnUrlHash", Model.ReturnUrlHash}})">
<i class="fa fa-long-arrow-left"></i> @L["Login"]
</a>
</form>
</div>
</div>

59
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyAuthenticatorCode.cshtml.cs

@ -0,0 +1,59 @@
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Account.Web.Pages.Account;
namespace LY.AIO.Applications.Single.Pages.Account
{
public class VerifyAuthenticatorCodeModel : AccountPageModel
{
[BindProperty]
public VerifyAuthenticatorCodeInputModel Input { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
[BindProperty(SupportsGet = true)]
public bool RememberBrowser { get; set; }
[HiddenInput]
public bool RememberMe { get; set; }
public virtual IActionResult OnGet()
{
Input = new VerifyAuthenticatorCodeInputModel();
return Page();
}
public virtual async Task<IActionResult> OnPostAsync()
{
var result = await SignInManager.TwoFactorAuthenticatorSignInAsync(Input.VerifyCode, RememberMe, RememberBrowser);
if (result.Succeeded)
{
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash);
}
if (result.IsLockedOut)
{
Logger.LogWarning(7, "User account locked out.");
Alerts.Warning(L["UserLockedOutMessage"]);
return Page();
}
else
{
Alerts.Danger(L["TwoFactorAuthenticationInvaidUser"]);// TODO: ����״̬��Ľ��
return Page();
}
}
}
public class VerifyAuthenticatorCodeInputModel
{
[Required]
public string VerifyCode { get; set; }
}
}

29
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyCode.cshtml

@ -0,0 +1,29 @@
@page
@inject IHtmlLocalizer<AccountResource> L
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@model LY.AIO.Applications.Single.Pages.Account.VerifyCodeModel
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<form method="post" class="mt-4">
<input asp-for="Provider" />
<input asp-for="ReturnUrl" />
<input asp-for="ReturnUrlHash" />
<input asp-for="RememberMe" />
<div class="form-group">
<abp-input asp-for="Input.VerifyCode" label="@L["VerifyCode"].Value" class="form-control" />
</div>
<abp-row>
<abp-column>
<abp-input asp-for="Input.RememberBrowser" label="@L["RememberBrowser"].Value" />
</abp-column>
</abp-row>
<div class="d-grid gap-2">
<abp-button type="submit" button-type="Primary" class="mt-2 mb-3">@L["VerifyAuthenticatorCode"]</abp-button>
</div>
<a asp-page="./SendCode" asp-all-route-data="@(new Dictionary<string, string> {{"returnUrl", Model.ReturnUrl}, {"returnUrlHash", Model.ReturnUrlHash}})">
<i class="fa fa-long-arrow-left"></i> @L["ReSendVerifyCode"]
</a>
</form>
</div>
</div>

90
aspnet-core/services/LY.AIO.Applications.Single/Pages/Account/VerifyCode.cshtml.cs

@ -0,0 +1,90 @@
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
namespace LY.AIO.Applications.Single.Pages.Account
{
public class VerifyCodeModel : AccountPageModel
{
[BindProperty]
public VerifyCodeInputModel Input { get; set; }
/// <summary>
/// ˫������֤�ṩ����
/// </summary>
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string Provider { get; set; }
/// <summary>
/// �ض���Url
/// </summary>
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
/// <summary>
///
/// </summary>
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
/// <summary>
/// �Ƿ��ס��¼״̬
/// </summary>
[HiddenInput]
[BindProperty(SupportsGet = true)]
public bool RememberMe { get; set; }
public VerifyCodeModel()
{
LocalizationResourceType = typeof(AccountResource);
}
public virtual IActionResult OnGet()
{
Input = new VerifyCodeInputModel();
return Page();
}
public virtual async Task<IActionResult> OnPostAsync()
{
// ��֤�û���¼״̬
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
Alerts.Warning(L["TwoFactorAuthenticationInvaidUser"]);
return Page();
}
// ˫���ص�¼
var result = await SignInManager.TwoFactorSignInAsync(Provider, Input.VerifyCode, RememberMe, Input.RememberBrowser);
if (result.Succeeded)
{
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash);
}
if (result.IsLockedOut)
{
Logger.LogWarning(7, "User account locked out.");
Alerts.Warning(L["UserLockedOutMessage"]);
return Page();
}
else
{
Alerts.Danger(L["TwoFactorAuthenticationInvaidUser"]);// TODO: ����״̬��Ľ��
return Page();
}
}
}
public class VerifyCodeInputModel
{
/// <summary>
/// �Ƿ���������м�ס��¼״̬
/// </summary>
public bool RememberBrowser { get; set; }
/// <summary>
/// ���͵���֤��
/// </summary>
[Required]
public string VerifyCode { get; set; }
}
}

36
aspnet-core/services/LY.AIO.Applications.Single/Pages/Index.cshtml

@ -0,0 +1,36 @@
@page
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
@using Volo.Abp.Users
@model LY.AIO.Applications.Single.Pages.IndexModel
@inject ICurrentUser CurrentUser
@if (CurrentUser.IsAuthenticated)
{
<div>
<abp-row>
<abp-column size-md="_3" class="text-center">
<i class="fa fa-user d-block" style="font-size: 10em; color: #12b900"></i>
<a abp-button="Primary" asp-controller="Logout" asp-action="Index" asp-area="Account">Logout</a>
</abp-column>
<abp-column size-md="_9">
<h2>@CurrentUser.UserName</h2>
<h5 class="text-muted">@CurrentUser.Email</h5>
<div>
<strong>Roles</strong>: @CurrentUser.Roles.JoinAsString(", ")
<br />
<strong>Claims</strong>: <br />
@Html.Raw(CurrentUser.GetAllClaims().Select(c => $"{c.Type}={c.Value}").JoinAsString(" <br /> "))
</div>
</abp-column>
</abp-row>
</div>
}
@if (!CurrentUser.IsAuthenticated)
{
<div class="text-center">
<i class="fa fa-user d-block" style="font-size: 10em; color: #aaa"></i><br/><br />
<a abp-button="Primary" asp-page="/Account/Login">Login</a>
</div>
}

11
aspnet-core/services/LY.AIO.Applications.Single/Pages/Index.cshtml.cs

@ -0,0 +1,11 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace LY.AIO.Applications.Single.Pages
{
public class IndexModel : AbpPageModel
{
public void OnGet()
{
}
}
}

4
aspnet-core/services/LY.AIO.Applications.Single/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

82
aspnet-core/services/LY.AIO.Applications.Single/Program.cs

@ -0,0 +1,82 @@
using LINGYUN.Abp.Identity.Session.AspNetCore;
using LY.AIO.Applications.Single;
using Microsoft.AspNetCore.Cors;
using Serilog;
using Volo.Abp.IO;
using Volo.Abp.Modularity.PlugIns;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy
.WithOrigins(
builder.Configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.WithAbpWrapExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
builder.Host.AddAppSettingsSecretsJson()
.UseAutofac()
.UseSerilog((context, provider, config) =>
{
config.ReadFrom.Configuration(context.Configuration);
});
await builder.AddApplicationAsync<MicroServiceApplicationsSingleModule>(options =>
{
MicroServiceApplicationsSingleModule.ApplicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME")
?? MicroServiceApplicationsSingleModule.ApplicationName;
options.ApplicationName = MicroServiceApplicationsSingleModule.ApplicationName;
options.Configuration.UserSecretsId = Environment.GetEnvironmentVariable("APPLICATION_USER_SECRETS_ID");
options.Configuration.UserSecretsAssembly = typeof(MicroServiceApplicationsSingleModule).Assembly;
var pluginFolder = Path.Combine(
Directory.GetCurrentDirectory(), "Modules");
DirectoryHelper.CreateIfNotExists(pluginFolder);
options.PlugInSources.AddFolder(
pluginFolder,
SearchOption.AllDirectories);
});
var app = builder.Build();
await app.InitializeApplicationAsync();
app.UseForwardedHeaders();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// app.UseAbpExceptionHandling();
app.UseCookiePolicy();
app.UseMapRequestLocalization();
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseMultiTenancy();
app.UseUnitOfWork();
app.UseAbpOpenIddictValidation();
app.UseAbpSession();
app.UseDynamicClaims();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support App API");
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
await app.RunAsync();

30
aspnet-core/services/LY.AIO.Applications.Single/Properties/launchSettings.json

@ -0,0 +1,30 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:19139",
"sslPort": 0
}
},
"profiles": {
"LY.MicroService.Applications.Single": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://0.0.0.0:30001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
},
"LY.MicroService.Applications.Single.Development": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://0.0.0.0:30000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

35
aspnet-core/services/LY.AIO.Applications.Single/TenantHeaderParamter.cs

@ -0,0 +1,35 @@
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.MultiTenancy;
namespace LY.AIO.Applications.Single;
public class TenantHeaderParamter : IOperationFilter
{
private readonly AbpMultiTenancyOptions _multiTenancyOptions;
private readonly AbpAspNetCoreMultiTenancyOptions _aspNetCoreMultiTenancyOptions;
public TenantHeaderParamter(
IOptions<AbpMultiTenancyOptions> multiTenancyOptions,
IOptions<AbpAspNetCoreMultiTenancyOptions> aspNetCoreMultiTenancyOptions)
{
_multiTenancyOptions = multiTenancyOptions.Value;
_aspNetCoreMultiTenancyOptions = aspNetCoreMultiTenancyOptions.Value;
}
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (_multiTenancyOptions.IsEnabled)
{
operation.Parameters = operation.Parameters ?? new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = _aspNetCoreMultiTenancyOptions.TenantKey,
In = ParameterLocation.Header,
Description = "Tenant Id in http header",
Required = false
});
}
}
}

21
aspnet-core/services/LY.AIO.Applications.Single/WeChat/Official/Messages/TextMessageReplyContributor.cs

@ -0,0 +1,21 @@
using LINGYUN.Abp.WeChat.Common.Messages.Handlers;
using LINGYUN.Abp.WeChat.Official.Messages.Models;
using LINGYUN.Abp.WeChat.Official.Services;
namespace LY.AIO.Applications.Single.WeChat.Official.Messages;
/// <summary>
/// 文本消息客服回复
/// </summary>
public class TextMessageReplyContributor : IMessageHandleContributor<TextMessage>
{
public async virtual Task HandleAsync(MessageHandleContext<TextMessage> context)
{
var messageSender = context.ServiceProvider.GetRequiredService<IServiceCenterMessageSender>();
await messageSender.SendAsync(
new LINGYUN.Abp.WeChat.Official.Services.Models.TextMessageModel(
context.Message.FromUserName,
new LINGYUN.Abp.WeChat.Official.Services.Models.TextMessage(
context.Message.Content)));
}
}

21
aspnet-core/services/LY.AIO.Applications.Single/WeChat/Official/Messages/UserSubscribeEventContributor.cs

@ -0,0 +1,21 @@
using LINGYUN.Abp.WeChat.Common.Messages.Handlers;
using LINGYUN.Abp.WeChat.Official.Messages.Models;
using LINGYUN.Abp.WeChat.Official.Services;
namespace LY.AIO.Applications.Single.WeChat.Official.Messages;
/// <summary>
/// 用户关注回复消息
/// </summary>
public class UserSubscribeEventContributor : IEventHandleContributor<UserSubscribeEvent>
{
public async virtual Task HandleAsync(MessageHandleContext<UserSubscribeEvent> context)
{
var messageSender = context.ServiceProvider.GetRequiredService<IServiceCenterMessageSender>();
await messageSender.SendAsync(
new LINGYUN.Abp.WeChat.Official.Services.Models.TextMessageModel(
context.Message.FromUserName,
new LINGYUN.Abp.WeChat.Official.Services.Models.TextMessage(
"感谢您的关注, 点击菜单了解更多.")));
}
}

24
aspnet-core/services/LY.AIO.Applications.Single/WeChat/Work/Messages/TextMessageReplyContributor.cs

@ -0,0 +1,24 @@
using LINGYUN.Abp.WeChat.Common.Messages.Handlers;
using LINGYUN.Abp.WeChat.Work.Common.Messages.Models;
using LINGYUN.Abp.WeChat.Work.Messages;
namespace LY.AIO.Applications.Single.WeChat.Work.Messages;
/// <summary>
/// 文本消息客服回复
/// </summary>
public class TextMessageReplyContributor : IMessageHandleContributor<TextMessage>
{
public async virtual Task HandleAsync(MessageHandleContext<TextMessage> context)
{
var messageSender = context.ServiceProvider.GetRequiredService<IWeChatWorkMessageSender>();
await messageSender.SendAsync(
new LINGYUN.Abp.WeChat.Work.Messages.Models.WeChatWorkTextMessage(
context.Message.AgentId.ToString(),
new LINGYUN.Abp.WeChat.Work.Messages.Models.TextMessage(
context.Message.Content))
{
ToUser = context.Message.FromUserName,
});
}
}

249
aspnet-core/services/LY.AIO.Applications.Single/appsettings.Development.json

@ -0,0 +1,249 @@
{
"App": {
"ShowPii": true,
"SelfUrl": "http://127.0.0.1:30001/",
"CorsOrigins": "http://127.0.0.1:3100,http://127.0.0.1:30001",
"Urls": {
"Applications": {
"MVC": {
"RootUrl": "http://127.0.0.1:30001/",
"Urls": {
"Abp.Account.EmailConfirm": "Account/EmailConfirm",
"Abp.Account.EmailVerifyLogin": "Account/VerifyCode"
}
},
"STS": {
"RootUrl": "http://127.0.0.1:30001/"
},
"VueVbenAdmin": {
"RootUrl": "http://127.0.0.1:3100",
"Urls": {
"Abp.Account.EmailConfirm": "account/email-confirm"
}
}
}
}
},
"Auditing": {
"AllEntitiesSelector": true
},
"DistributedCache": {
"HideErrors": true,
"KeyPrefix": "LINGYUN.Abp.Application",
"GlobalCacheEntryOptions": {
"SlidingExpiration": "30:00:00",
"AbsoluteExpirationRelativeToNow": "60:00:00"
}
},
"ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None"//Mysql
// "Default": "Host=127.0.0.1;Database=Platform-V70;Username=postgres;Password=123456;"//Postgres
},
"DistributedLock": {
"IsEnabled": true,
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=14"
}
},
"Elsa": {
"Features": {
"DefaultPersistence": {
"Enabled": true,
"ConnectionStringIdentifier": "Default",
"EntityFrameworkCore": {
"MySql": {
"Enabled": true
}
}
},
"Console": true,
"Http": true,
"Email": true,
"TemporalQuartz": true,
"JavaScriptActivities": true,
"UserTask": true,
"Conductor": true,
"Telnyx": true,
"BlobStoring": true,
"Emailing": true,
"Notification": true,
"Sms": true,
"IM": true,
"PublishWebhook": true,
"Webhooks": {
"Enabled": true,
"ConnectionStringIdentifier": "Default",
"EntityFrameworkCore": {
"MySql": {
"Enabled": true
}
}
},
"WorkflowSettings": {
"Enabled": true,
"ConnectionStringIdentifier": "Default",
"EntityFrameworkCore": {
"MySql": {
"Enabled": true
}
}
}
},
"Server": {
"BaseUrl": "http://127.0.0.1:30000"
}
},
"Quartz": {
"UsePersistentStore": false,
"Properties": {
"quartz.jobStore.dataSource": "tkm",
"quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz",
"quartz.dataSource.tkm.connectionStringName": "Default",
"quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.MySQLDelegate,Quartz",
"quartz.dataSource.tkm.connectionString": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456",
"quartz.dataSource.tkm.provider": "MySqlConnector",
// "quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.PostgreSQLDelegate,Quartz",
// "quartz.dataSource.tkm.connectionString": "Host=127.0.0.1;Database=Platform-V70;Username=postgres;Password=123456;",
// "quartz.dataSource.tkm.provider": "Npgsql",
"quartz.jobStore.clustered": "true",
"quartz.serializer.type": "json"
}
},
"Redis": {
"IsEnabled": true,
"Configuration": "127.0.0.1,defaultDatabase=15",
"InstanceName": "LINGYUN.Abp.Application"
},
"Features": {
"Validation": {
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=13",
"InstanceName": "LINGYUN.Abp.Application"
}
}
},
"AuthServer": {
"UseOpenIddict": true,
"Authority": "http://127.0.0.1:30001/",
"Audience": "lingyun-abp-application",
"RequireHttpsMetadata": false,
"SwaggerClientId": "InternalServiceClient",
"SwaggerClientSecret": "1q2w3E*"
},
"IdentityServer": {
"Clients": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:3100/"
},
"InternalService": {
"ClientId": "InternalServiceClient"
}
}
},
"OpenIddict": {
"Applications": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:3100/"
},
"InternalService": {
"ClientId": "InternalServiceClient"
}
},
"Lifetime": {
"AuthorizationCode": "00:05:00",
"AccessToken": "14:00:00",
"DeviceCode": "00:10:00",
"IdentityToken": "00:20:00",
"RefreshToken": "14:00:00",
"RefreshTokenReuseLeeway": "00:00:30",
"UserCode": "00:10:00"
}
},
"Identity": {
"Password": {
"RequiredLength": 6,
"RequiredUniqueChars": 0,
"RequireNonAlphanumeric": false,
"RequireLowercase": false,
"RequireUppercase": false,
"RequireDigit": false
},
"Lockout": {
"AllowedForNewUsers": false,
"LockoutDuration": 5,
"MaxFailedAccessAttempts": 5
},
"SignIn": {
"RequireConfirmedEmail": false,
"RequireConfirmedPhoneNumber": false
}
},
"FeatureManagement": {
"IsDynamicStoreEnabled": true
},
"SettingManagement": {
"IsDynamicStoreEnabled": true
},
"PermissionManagement": {
"IsDynamicStoreEnabled": true
},
"TextTemplating": {
"IsDynamicStoreEnabled": true
},
"WebhooksManagement": {
"IsDynamicStoreEnabled": true
},
"Logging": {
"Serilog": {
"Elasticsearch": {
"IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}"
}
}
},
"AuditLogging": {
"Elasticsearch": {
"IndexPrefix": "abp.dev.auditing"
}
},
"Elasticsearch": {
"NodeUris": "http://127.0.0.1:9200"
},
"Minio": {
"WithSSL": false,
"BucketName": "blobs",
"EndPoint": "127.0.0.1:19000",
"AccessKey": "ZD43kNpimiJf9mCuomTP",
"SecretKey": "w8IqMgi4Tnz0DGzN8jZ7IJWq7OEdbUnAU0jlZxQK",
"CreateBucketIfNotExists": false
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"System": "Warning",
"Microsoft": "Warning",
"DotNetCore": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"restrictedToMinimumLevel": "Debug",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "http://127.0.0.1:9200",
"indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}",
"autoRegisterTemplate": true,
"autoRegisterTemplateVersion": "ESv7"
}
}
]
}
}

89
aspnet-core/services/LY.AIO.Applications.Single/appsettings.json

@ -0,0 +1,89 @@
{
"Clock": {
"Kind": "Local"
},
"Forwarded": {
"ForwardedHeaders": "XForwardedFor,XForwardedProto"
},
"StringEncryption": {
"DefaultPassPhrase": "s46c5q55nxpeS8Ra",
"InitVectorBytes": "s83ng0abvd02js84",
"DefaultSalt": "sf&5)s3#"
},
"Json": {
"OutputDateTimeFormat": "yyyy-MM-dd HH:mm:ss",
"InputDateTimeFormats": [
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-ddTHH:mm:ss"
]
},
"AllowedHosts": "*",
"Hosting": {
"BasePath": ""
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"System": "Warning",
"Microsoft": "Warning",
"DotNetCore": "Information"
}
},
"Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"restrictedToMinimumLevel": "Debug",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Debug-.log",
"restrictedToMinimumLevel": "Debug",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Info-.log",
"restrictedToMinimumLevel": "Information",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Warn-.log",
"restrictedToMinimumLevel": "Warning",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Error-.log",
"restrictedToMinimumLevel": "Error",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Fatal-.log",
"restrictedToMinimumLevel": "Fatal",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
}
]
}
}

10
aspnet-core/services/LY.AIO.Applications.Single/gulpfile.js

@ -0,0 +1,10 @@
"use strict";
var gulp = require("gulp"),
path = require('path'),
copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
exports.default = function(done){
copyResources(path.resolve('./'));
done();
};

30
aspnet-core/templates/aio/PackageName.CompanyName.ProjectName.AIO.csproj

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>LINGYUN.Abp.AllInOne.Templates</PackageId>
<Version>8.3.0</Version>
<Authors>colin.in@foxmail.com</Authors>
<Description>Abp framework all-in-one template</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageProjectUrl>https://github.com/colinin/abp-next-admin</PackageProjectUrl>
<PackageTags>allinone webapi cloud</PackageTags>
<PackageType>Template</PackageType>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/colinin/abp-next-admin</RepositoryUrl>
<DevelopmentDependency>true</DevelopmentDependency>
<IsPackable>true</IsPackable>
<IsShipping>true</IsShipping>
<IsShippingPackage>true</IsShippingPackage>
<IncludeBuildOutput>False</IncludeBuildOutput>
<IncludeSource>False</IncludeSource>
</PropertyGroup>
<ItemGroup>
<Content Include="content\**" Exclude="**/bin/**;**/obj/**;**/LocalNuget/**;**/.vs/**;**/.vscode/**;">
<Pack>true</Pack>
<PackagePath>content</PackagePath>
</Content>
</ItemGroup>
</Project>

115
aspnet-core/templates/aio/content/.template.config/template.json

@ -0,0 +1,115 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "colin.in@foxmail.com",
"classifications": ["allinone", "webapi", "cloud"],
"name": "LINGYUN.Abp.AllInOne",
"identity": "LINGYUN.Abp.AllInOne",
"description": "Abp framework all-in-one template",
"groupIdentity": "LINGYUN.Abp",
"shortName": "laa",
"tags": {
"language": "C#",
"type": "project"
},
"sources": [
{
"modifiers": [
{
"exclude": [
"**/[Bb]in/**",
"**/[Oo]bj/**",
"**/[Ll]ocalNuget/**",
".template.config/**/*",
".vs/**/*"
]
}
]
}
],
"sourceName": "ProjectName",
"preferNameDirectory": true,
"symbols": {
"AuthenticationScheme": {
"type": "parameter",
"description": "Authentication Scheme",
"datatype": "choice",
"defaultValue": "IdentityServer4",
"isRequired": false,
"choices": [
{
"choice": "IdentityServer4",
"description": "IdentityServer4"
},
{
"choice": "OpenIddict",
"description": "OpenIddict"
}
]
},
"DatabaseManagement": {
"type": "parameter",
"description": "Database Management",
"dataType": "choice",
"defaultValue": "MySQL",
"isRequired": false,
"choices": [
{
"choice": "SqlServer",
"description": "Sql Server"
},
{
"choice": "MySQL",
"description": "My SQL"
},
{
"choice": "Sqlite",
"description": "Sqlite"
},
{
"choice": "Oracle",
"description": "Oracle"
},
{
"choice": "OracleDevart",
"description": "Oracle Devart Driver"
},
{
"choice": "PostgreSql",
"description": "Postgre Sql"
}
]
},
"SqlServer": {
"type": "computed",
"value": "(DatabaseManagement == \"SqlServer\")"
},
"MySQL": {
"type": "computed",
"value": "(DatabaseManagement == \"MySQL\")"
},
"Sqlite": {
"type": "computed",
"value": "(DatabaseManagement == \"Sqlite\")"
},
"Oracle": {
"type": "computed",
"value": "(DatabaseManagement == \"Oracle\")"
},
"OracleDevart": {
"type": "computed",
"value": "(DatabaseManagement == \"Oracle.Devart\")"
},
"PostgreSql": {
"type": "computed",
"value": "(DatabaseManagement == \"PostgreSql\")"
},
"IdentityServer4": {
"type": "computed",
"value": "(AuthenticationScheme == \"IdentityServer4\")"
},
"OpenIddict": {
"type": "computed",
"value": "(AuthenticationScheme == \"OpenIddict\")"
}
}
}

0
aspnet-core/templates/content/.template.config/template.zh-Hans.json → aspnet-core/templates/aio/content/.template.config/template.zh-Hans.json

26
aspnet-core/templates/content/Directory.Build.props → aspnet-core/templates/aio/content/Directory.Build.props

@ -1,13 +1,13 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<IsTestProject Condition="$(MSBuildProjectFullPath.Contains('test')) and ($(MSBuildProjectName.EndsWith('.Tests')) or $(MSBuildProjectName.EndsWith('.TestBase')))">true</IsTestProject> <IsTestProject Condition="$(MSBuildProjectFullPath.Contains('test')) and ($(MSBuildProjectName.EndsWith('.Tests')) or $(MSBuildProjectName.EndsWith('.TestBase')))">true</IsTestProject>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Condition="'$(IsTestProject)' == 'true'" Include="coverlet.collector"> <PackageReference Condition="'$(IsTestProject)' == 'true'" Include="coverlet.collector">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

537
aspnet-core/templates/aio/content/Directory.Packages.props

@ -0,0 +1,537 @@
<Project>
<PropertyGroup>
<DotNetCoreCAPPackageVersion>8.2.0</DotNetCoreCAPPackageVersion>
<ElsaPackageVersion>2.14.1</ElsaPackageVersion>
<VoloAbpPackageVersion>8.3.0</VoloAbpPackageVersion>
<LINGYUNAbpPackageVersion>8.3.0</LINGYUNAbpPackageVersion>
<MicrosoftExtensionsPackageVersion>8.0.0</MicrosoftExtensionsPackageVersion>
<MicrosoftAspNetCorePackageVersion>8.0.0</MicrosoftAspNetCorePackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>8.0.0</MicrosoftEntityFrameworkCorePackageVersion>
<SerilogPackageVersion>3.1.1</SerilogPackageVersion>
<SerilogAspNetCorePackageVersion>8.0.0</SerilogAspNetCorePackageVersion>
<XunitPackageVersion>2.6.1</XunitPackageVersion>
<OpenTelemetryPackageVersion>1.8.1</OpenTelemetryPackageVersion>
<FodyPackageVersion>6.8.0</FodyPackageVersion>
<MicrosoftTestSdkPackageVersion>17.8.0</MicrosoftTestSdkPackageVersion>
<DaprPackageVersion>1.12.0</DaprPackageVersion>
<IdentityModelPackageVersion>6.2.0</IdentityModelPackageVersion>
<PollyPackageVersion>8.2.0</PollyPackageVersion>
<QuartzPackageVersion>3.7.0</QuartzPackageVersion>
<HangfirePackageVersion>1.8.6</HangfirePackageVersion>
<DistributedLockPackageVersion>1.0.5</DistributedLockPackageVersion>
<DistributedLockRedisPackageVersion>1.0.2</DistributedLockRedisPackageVersion>
<SenparcWeixinPackageVersion>16.18.9</SenparcWeixinPackageVersion>
<ImageSharpPackageVersion>3.0.2</ImageSharpPackageVersion>
<CoverletPackageVersion>6.0.0</CoverletPackageVersion>
<MoqPackageVersion>3.0.0</MoqPackageVersion>
<NSubstitutePackageVersion>5.1.0</NSubstitutePackageVersion>
<ShouldlyPackageVersion>4.2.1</ShouldlyPackageVersion>
<XunitRunnerPackageVersion>2.5.3</XunitRunnerPackageVersion>
<AliyunSdkPackageVersion>1.5.10</AliyunSdkPackageVersion>
<AliyunOssPackageVersion>2.13.0</AliyunOssPackageVersion>
<AgileConfigPackageVersion>1.6.9</AgileConfigPackageVersion>
<MarkdigPackageVersion>0.34.0</MarkdigPackageVersion>
<NewtonsoftJsonPackageVersion>13.0.3</NewtonsoftJsonPackageVersion>
<NestPackageVersion>7.15.1</NestPackageVersion>
<NRulesPackageVersion>0.9.2</NRulesPackageVersion>
<OcelotPackageVersion>20.0.0</OcelotPackageVersion>
<RulesEnginePackageVersion>4.0.0</RulesEnginePackageVersion>
<JetBrainsAnnotationsPackageVersion>2023.3.0</JetBrainsAnnotationsPackageVersion>
<ImageSharpDrawingPackageVersion>2.0.1</ImageSharpDrawingPackageVersion>
<StackExchangeRedisPackageVersion>2.7.4</StackExchangeRedisPackageVersion>
<SwashbucklePackageVersion>6.5.0</SwashbucklePackageVersion>
<HangfireMySqlPackageVersion>2.0.3</HangfireMySqlPackageVersion>
<OpenTelemetryEfCorePackageVersion>1.0.0-beta.11</OpenTelemetryEfCorePackageVersion>
<SystemComponentModelPackageVersion>5.0.0</SystemComponentModelPackageVersion>
<TencentCloudCosPackageVersion>5.4.37</TencentCloudCosPackageVersion>
<TencentCloudSdkPackageVersion>3.0.712</TencentCloudSdkPackageVersion>
<YarpReverseProxyPackageVersion>2.1.0</YarpReverseProxyPackageVersion>
<OpenIddictDataProtectionPackageVersion>5.5.0</OpenIddictDataProtectionPackageVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<!-- LINGYUN Abp Framework -->
<ItemGroup>
<PackageVersion Include="LINGYUN.Abp.AspNetCore.HttpOverrides" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.Mvc.Localization" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.Mvc.Wrapper" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AuditLogging" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AuditLogging.Elasticsearch" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Authorization.OrganizationUnits" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Abstractions" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Jobs" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Data.DbMigrator" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtection" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtection.Abstractions" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtection.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.DataProtectionManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dapr.Client" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dapr.Client.Wrapper" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dynamic.Queryable.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dynamic.Queryable.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Dynamic.Queryable.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elasticsearch" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.EntityChange.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.EntityChange.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.EntityChange.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.EventBus.CAP" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.ExceptionHandling" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.ExceptionHandling.Emailing" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Http.Client.Wrapper" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdGenerator" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Session" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Session.AspNetCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Localization.CultureMap" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MultiTenancy" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Core" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.SignalR" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.WxPusher" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Rules" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Rules.RulesEngine" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.SettingManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Serilog.Enrichers.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Serilog.Enrichers.UniqueId" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.UI.Navigation" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.Core" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.EventBus" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Linq.Dynamic.Queryable" Version="$(LINGYUNAbpPackageVersion)" />
</ItemGroup>
<!-- Abp Framework -->
<ItemGroup>
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="3.2.0" />
<PackageVersion Include="Volo.Abp.Core" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Web.IdentityServer" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Web.OpenIddict" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.MultiTenancy" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.Client.Common" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.NewtonsoftJson" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.Serilog" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.SignalR" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AspNetCore.TestBase" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Auditing" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Auditing.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AuditLogging.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AuditLogging.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Authorization" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Authorization.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Autofac" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.AutoMapper" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.BackgroundJobs" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.BackgroundJobs.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.BackgroundWorkers" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.BlobStoring" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.BlobStoring.FileSystem" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Caching" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Caching.StackExchangeRedis" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Cli.Core" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Data" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Ddd.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Ddd.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Ddd.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.DistributedLocking.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.DistributedLocking" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.MySql" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.Sqlite" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.Oracle" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.Oracle.Devart" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Features" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.FeatureManagement.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Emailing" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EventBus" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.EventBus.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.ExceptionHandling" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Guids" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.GlobalFeatures" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.HangFire" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Http.Client" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Http.Client.IdentityModel.Web" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.AspNetCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.IdentityServer.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.IdentityServer.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.IdentityServer.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.IdentityServer.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.IdentityServer.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Identity.HttpApi.Client" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Imaging.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Imaging.ImageSharp" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Json" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Json.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Localization" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.MemoryDb" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.MultiTenancy" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.MultiTenancy.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.ObjectExtending" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.AspNetCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.OpenIddict.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.Identity" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Quartz" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Security" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Settings" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.SettingManagement.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.SettingManagement.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.SettingManagement.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.SettingManagement.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.SettingManagement.HttpApi" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Swashbuckle" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Sms" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.TestBase" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.TextTemplating.Core" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.TextTemplating.Scriban" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Timing" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Threading" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Users.Abstractions" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Users.Domain.Shared" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Validation" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<!-- .NET -->
<ItemGroup>
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(MicrosoftEntityFrameworkCorePackageVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="$(MicrosoftEntityFrameworkCorePackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftTestSdkPackageVersion)" />
</ItemGroup>
<!-- Elsa -->
<ItemGroup>
<PackageVersion Include="Elsa" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Activities.Email" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Activities.Http" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Activities.UserTask" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Activities.Temporal.Quartz" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Core" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Designer.Components.Web" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Rebus.RabbitMq" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Server.Api" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Webhooks.Api" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Webhooks.Persistence.EntityFramework.Core" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.WorkflowSettings.Persistence.EntityFramework.Core" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.Webhooks.Persistence.EntityFramework.MySql" Version="$(ElsaPackageVersion)" />
<PackageVersion Include="Elsa.WorkflowSettings.Persistence.EntityFramework.MySql" Version="$(ElsaPackageVersion)" />
</ItemGroup>
<!-- DotNetCore.CAP -->
<ItemGroup>
<PackageVersion Include="DotNetCore.CAP" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.Dashboard" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.MySql" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.OpenTelemetry" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.Oracle" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.PostgreSql" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.RabbitMQ" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.SqlServer" Version="$(DotNetCoreCAPPackageVersion)" />
<PackageVersion Include="DotNetCore.CAP.Sqlite" Version="$(DotNetCoreCAPPackageVersion)" />
</ItemGroup>
<!-- Serilog -->
<ItemGroup>
<PackageVersion Include="Serilog" Version="$(SerilogPackageVersion)" />
<PackageVersion Include="Serilog.AspNetCore" Version="$(SerilogAspNetCorePackageVersion)" />
<PackageVersion Include="Serilog.Enrichers.Environment" Version="2.3.0" />
<PackageVersion Include="Serilog.Enrichers.Assembly" Version="2.0.0" />
<PackageVersion Include="Serilog.Enrichers.Process" Version="2.0.2" />
<PackageVersion Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageVersion Include="Serilog.Extensions.Hosting" Version="$(SerilogAspNetCorePackageVersion)" />
<PackageVersion Include="Serilog.Extensions.Logging" Version="$(SerilogAspNetCorePackageVersion)" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="$(SerilogAspNetCorePackageVersion)" />
<PackageVersion Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="5.0.0" />
<PackageVersion Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>
<!-- Test -->
<ItemGroup>
<PackageVersion Include="coverlet.collector" Version="$(CoverletPackageVersion)" />
<PackageVersion Include="xunit" Version="$(XunitPackageVersion)" />
<PackageVersion Include="xunit.extensibility.execution" Version="$(XunitPackageVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitRunnerPackageVersion)" />
<PackageVersion Include="Moq.AutoMock" Version="$(MoqPackageVersion)" />
<PackageVersion Include="NSubstitute" Version="$(NSubstitutePackageVersion)" />
<PackageVersion Include="Shouldly" Version="$(ShouldlyPackageVersion)" />
</ItemGroup>
<!-- Fody -->
<ItemGroup>
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="$(FodyPackageVersion)" />
</ItemGroup>
<!-- Other -->
<ItemGroup>
<PackageVersion Include="aliyun-net-sdk-core" Version="$(AliyunSdkPackageVersion)" />
<PackageVersion Include="Aliyun.OSS.SDK.NetCore" Version="$(AliyunOssPackageVersion)" />
<PackageVersion Include="AgileConfig.Client" Version="$(AgileConfigPackageVersion)" />
<PackageVersion Include="Dapr.Client" Version="$(DaprPackageVersion)" />
<PackageVersion Include="Dapr.Actors" Version="$(DaprPackageVersion)" />
<PackageVersion Include="Dapr.Actors.AspNetCore" Version="$(DaprPackageVersion)" />
<PackageVersion Include="DistributedLock.Core" Version="$(DistributedLockPackageVersion)" />
<PackageVersion Include="DistributedLock.Redis" Version="$(DistributedLockRedisPackageVersion)" />
<PackageVersion Include="Hangfire.MySqlStorage" Version="$(HangfireMySqlPackageVersion)" />
<PackageVersion Include="HangFire.SqlServer" Version="$(HangfirePackageVersion)" />
<PackageVersion Include="IdentityModel" Version="$(IdentityModelPackageVersion)" />
<PackageVersion Include="JetBrains.Annotations" Version="$(JetBrainsAnnotationsPackageVersion)" />
<PackageVersion Include="Markdig" Version="$(MarkdigPackageVersion)" />
<PackageVersion Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
<PackageVersion Include="NEST" Version="$(NestPackageVersion)" />
<PackageVersion Include="NRules" Version="$(NRulesPackageVersion)" />
<PackageVersion Include="Ocelot.Provider.Polly" Version="$(OcelotPackageVersion)" />
<PackageVersion Include="Volo.Abp.EntityFrameworkCore.PostgreSql" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AuditLogging.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Authentication.QQ" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Authentication.WeChat" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Aliyun.SettingManagement" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Aliyun" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Tencent.QQ" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Tencent.SettingManagement" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Tencent" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Features.LimitValidation.Redis.Client" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Features.LimitValidation.Redis" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Features.LimitValidation" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.RealTime" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Wrapper" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Exporter.MiniExcel" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.FeatureManagement.Client" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Localization.Persistence" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Logging.Serilog.Elasticsearch" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Logging" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Sms.Aliyun" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenApi.Authorization" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MultiTenancy.Editions" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.WeChat" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.MiniProgram" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official.Handlers" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Official.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.SettingManagement" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work.Handlers" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat.Work" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WeChat" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Account.Templates" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Auditing.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Auditing.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Auditing.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.CachingManagement.StackExchangeRedis" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.BlobStoring" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Emailing" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.IM" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Notifications" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Sms" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Activities.Webhooks" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa.Server" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Elsa" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.FeatureManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.FeatureManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Session" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.AspNetCore.Session" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.Notifications" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Identity.OrganizaztionUnits" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.LinkUser" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.Portal" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.SmsValidator" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IdentityServer.WeChat.Work" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.LocalizationManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.AspNetCore.Session" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.AspNetCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IM.SignalR" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.IM" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.MessageService.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.ExceptionHandling.Notifications" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Common" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Emailing" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.WeChat.MiniProgram" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Notifications.WeChat.Work" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.LinkUser" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Sms" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.Portal" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.WeChat" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OpenIddict.WeChat.Work" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.FileSystem" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.OssManagement.SettingManagement" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.PermissionManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.PermissionManagement.Domain.OrganizationUnits" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.PermissionManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.UI.Navigation.VueVbenAdmin" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Settings.VueVbenAdmin" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Theme.VueVbenAdmin" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Saas.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.SettingManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.SettingManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Activities" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.DistributedLocking" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.EventBus" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.ExceptionHandling" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Notifications" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks.Quartz" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.BackgroundTasks" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TaskManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.TextTemplating.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.Identity" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.Webhooks.Saas" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Domain.Shared" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.Domain" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Abp.WebhooksManagement.HttpApi" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="LINGYUN.Platform.Application" Version="$(LINGYUNAbpPackageVersion)" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="$(SystemComponentModelPackageVersion)" />
<PackageVersion Include="Tencent.QCloud.Cos.Sdk" Version="$(TencentCloudCosPackageVersion)" />
<PackageVersion Include="TencentCloudSDK" Version="$(TencentCloudSdkPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Exporter.Zipkin" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="$(OpenTelemetryEfCorePackageVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="$(OpenTelemetryPackageVersion)" />
<PackageVersion Include="Polly" Version="$(PollyPackageVersion)" />
<PackageVersion Include="Quartz.Serialization.Json" Version="$(QuartzPackageVersion)" />
<PackageVersion Include="RulesEngine" Version="$(RulesEnginePackageVersion)" />
<PackageVersion Include="Senparc.Weixin.MP" Version="$(SenparcWeixinPackageVersion)" />
<PackageVersion Include="SixLabors.ImageSharp" Version="$(ImageSharpPackageVersion)" />
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="$(ImageSharpDrawingPackageVersion)" />
<PackageVersion Include="StackExchange.Redis" Version="$(StackExchangeRedisPackageVersion)" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="$(SwashbucklePackageVersion)" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="$(SystemComponentModelPackageVersion)" />
<PackageVersion Include="Tencent.QCloud.Cos.Sdk" Version="$(TencentCloudCosPackageVersion)" />
<PackageVersion Include="TencentCloudSDK" Version="$(TencentCloudSdkPackageVersion)" />
<PackageVersion Include="Yarp.ReverseProxy" Version="$(YarpReverseProxyPackageVersion)" />
<PackageVersion Include="OpenIddict.Server.DataProtection" Version="$(OpenIddictDataProtectionPackageVersion)" />
<PackageVersion Include="OpenIddict.Validation.DataProtection" Version="$(OpenIddictDataProtectionPackageVersion)" />
</ItemGroup>
</Project>

0
aspnet-core/templates/content/NuGet.Config → aspnet-core/templates/aio/content/NuGet.Config

135
aspnet-core/templates/aio/content/README.md

@ -0,0 +1,135 @@
# LINGYUN.Abp.Templates
[English](README.md) | [中文](README.zh-CN.md)
## Introduction
LINGYUN.Abp.Templates provides two types of project templates based on ABP Framework:
1. **Microservice Template**: A complete microservice architecture template with distributed services.
2. **All-in-One Template**: A single-application template that combines all services into one project.
## Features
### Common Features
- Integrated authentication (IdentityServer4/OpenIddict)
- Database integration (multiple databases supported)
- Unified configuration management
- Distributed event bus support
- Background job processing
### Microservice Template Features
- Complete microservice project structure
- Service discovery and registration
- Distributed deployment support
### All-in-One Template Features
- Simplified deployment
- Easier maintenance
- Lower resource requirements
## How to Use
### Install labp CLI Tool
```bash
dotnet tool install --global LINGYUN.Abp.Cli
```
### Install Templates
```bash
# Install Microservice Template
dotnet new install LINGYUN.Abp.MicroService.Templates
# Install All-in-One Template
dotnet new install LINGYUN.Abp.AllInOne.Templates
```
### Create New Project
#### For Microservice Project
```bash
# Short name: lam (LINGYUN Abp Microservice)
labp create YourCompanyName.YourProjectName -pk YourPackageName -t lam -o /path/to/output --dbms MySql --cs "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None" --no-random-port
```
#### For All-in-One Project
```bash
# Short name: laa (LINGYUN Abp AllInOne)
labp create YourCompanyName.YourProjectName -pk YourPackageName -t laa -o /path/to/output --dbms MySql --cs "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None" --no-random-port
```
## How to Run
After creating your project, you can run it using the following command:
### For Microservice Project
```bash
cd /path/to/output/host/YourPackageName.YourCompanyName.YourProjectName.HttpApi.Host
dotnet run --launch-profile "YourPackageName.YourCompanyName.YourProjectName.Development"
```
### For All-in-One Project
```bash
cd /path/to/output/host/YourPackageName.YourCompanyName.YourProjectName.AIO.Host
dotnet run --launch-profile "YourPackageName.YourCompanyName.YourProjectName.Development"
```
## How to Package and Publish
1. Clone the Project
```bash
git clone <repository-url>
cd <repository-path>/aspnet-core/templates/content
```
2. Modify Version
Edit the project files to update versions:
- For Microservice: `../PackageName.CompanyName.ProjectName.csproj`
- For All-in-One: `../PackageName.CompanyName.ProjectName.AIO.csproj`
```xml
<Version>8.3.0</Version>
```
3. Execute Packaging Script
```powershell
# Windows PowerShell
.\pack.ps1
# PowerShell Core (Windows/Linux/macOS)
pwsh pack.ps1
```
The script will prompt you to choose which template to package:
1. Microservice Template
2. All-in-One Template
3. Both Templates
## Supported Databases
- SqlServer
- MySQL
- PostgreSQL
- Oracle
- SQLite
## Notes
- Ensure .NET SDK 8.0 or higher is installed
- Choose the appropriate template based on your needs:
- Microservice Template: For large-scale distributed applications
- All-in-One Template: For smaller applications or simpler deployment requirements
- Pay attention to NuGet publish address and key when packaging
- Complete testing is recommended before publishing

135
aspnet-core/templates/aio/content/README.zh-CN.md

@ -0,0 +1,135 @@
# LINGYUN.Abp.Templates
[English](README.md) | [中文](README.zh-CN.md)
## 简介
LINGYUN.Abp.Templates 基于 ABP Framework 提供两种项目模板:
1. **微服务模板**:完整的分布式微服务架构模板
2. **单体应用模板**:将所有服务集成到一个项目中的单体应用模板
## 特性
### 共同特性
- 集成身份认证(支持 IdentityServer4/OpenIddict)
- 数据库集成(支持多种数据库)
- 统一配置管理
- 分布式事件总线支持
- 后台作业处理
### 微服务模板特性
- 完整的微服务项目结构
- 服务发现与注册
- 支持分布式部署
### 单体应用模板特性
- 简化的部署流程
- 更容易的维护
- 更低的资源需求
## 使用方法
### 安装模板
```bash
# 安装微服务模板:lam
dotnet new install LINGYUN.Abp.MicroService.Templates
# 安装单体应用模板:laa
dotnet new install LINGYUN.Abp.AllInOne.Templates
```
### 安装 labp 命令行工具
```bash
dotnet tool install --global LINGYUN.Abp.Cli
```
### 创建新项目
#### 创建微服务项目
```bash
# 简写名称:lam (LINGYUN Abp Microservice)
labp create YourCompanyName.YourProjectName -pk YourPackageName -t lam -o /path/to/output --dbms MySql --cs "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None" --no-random-port
```
#### 创建单体应用项目
```bash
# 简写名称:laa (LINGYUN Abp AllInOne)
labp create YourCompanyName.YourProjectName -pk YourPackageName -t laa -o /path/to/output --dbms MySql --cs "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456;SslMode=None" --no-random-port
```
## 运行项目
创建项目后,可以使用以下命令运行:
### 运行微服务项目
```bash
cd /path/to/output/host/YourPackageName.YourCompanyName.YourProjectName.HttpApi.Host
dotnet run --launch-profile "YourPackageName.YourCompanyName.YourProjectName.Development"
```
### 运行单体应用项目
```bash
cd /path/to/output/host/YourPackageName.YourCompanyName.YourProjectName.AIO.Host
dotnet run --launch-profile "YourPackageName.YourCompanyName.YourProjectName.Development"
```
## 打包与发布
1. 克隆项目
```bash
git clone <repository-url>
cd <repository-path>/aspnet-core/templates/content
```
2. 修改版本号
编辑项目文件更新版本号:
- 微服务模板:`../PackageName.CompanyName.ProjectName.csproj`
- 单体应用模板:`../PackageName.CompanyName.ProjectName.AIO.csproj`
```xml
<Version>8.3.0</Version>
```
3. 执行打包脚本
```powershell
# Windows PowerShell
.\pack.ps1
# PowerShell Core (Windows/Linux/macOS)
pwsh pack.ps1
```
脚本会提示您选择要打包的模板:
1. 微服务模板
2. 单体应用模板
3. 两种模板都打包
## 支持的数据库
- SqlServer
- MySQL
- PostgreSQL
- Oracle
- SQLite
## 注意事项
- 确保已安装 .NET SDK 8.0 或更高版本
- 根据需求选择合适的模板:
- 微服务模板:适用于大规模分布式应用
- 单体应用模板:适用于小型应用或简单部署需求
- 打包时注意 NuGet 发布地址和密钥
- 发布前建议进行完整测试

74
aspnet-core/templates/content/common.props → aspnet-core/templates/aio/content/common.props

@ -1,38 +1,38 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Version>8.2.1</Version> <Version>8.2.1</Version>
<Authors>colin</Authors> <Authors>colin</Authors>
<NoWarn>$(NoWarn);CS1591;CS0436;CS8618;NU1803</NoWarn> <NoWarn>$(NoWarn);CS1591;CS0436;CS8618;NU1803</NoWarn>
<PackageProjectUrl>https://github.com/colinin/abp-next-admin</PackageProjectUrl> <PackageProjectUrl>https://github.com/colinin/abp-next-admin</PackageProjectUrl>
<PackageOutputPath>$(SolutionDir)LocalNuget</PackageOutputPath> <PackageOutputPath>$(SolutionDir)LocalNuget</PackageOutputPath>
<PackageVersion>8.2.1</PackageVersion> <PackageVersion>8.2.1</PackageVersion>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/colinin/abp-next-admin</RepositoryUrl> <RepositoryUrl>https://github.com/colinin/abp-next-admin</RepositoryUrl>
<GeneratePackageOnBuild Condition="$(AssemblyName.StartsWith('LINGYUN'))">true</GeneratePackageOnBuild> <GeneratePackageOnBuild Condition="$(AssemblyName.StartsWith('LINGYUN'))">true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="LocalNuget\**" /> <Compile Remove="LocalNuget\**" />
<EmbeddedResource Remove="LocalNuget\**" /> <EmbeddedResource Remove="LocalNuget\**" />
<None Remove="LocalNuget\**" /> <None Remove="LocalNuget\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Logs\**" /> <Compile Remove="Logs\**" />
<EmbeddedResource Remove="Logs\**" /> <EmbeddedResource Remove="Logs\**" />
<None Remove="Logs\**" /> <None Remove="Logs\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Modules\**" /> <Compile Remove="Modules\**" />
<EmbeddedResource Remove="Modules\**" /> <EmbeddedResource Remove="Modules\**" />
<None Remove="Modules\**" /> <None Remove="Modules\**" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>$(SolutionDir)LocalNuget</OutputPath> <OutputPath>$(SolutionDir)LocalNuget</OutputPath>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

0
aspnet-core/templates/content/configureawait.props → aspnet-core/templates/aio/content/configureawait.props

12
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/.config/dotnet-tools.json

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "7.0.3",
"commands": [
"dotnet-ef"
]
}
}
}

2
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/.gitignore

@ -0,0 +1,2 @@
wwwroot
package*.json

89
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Authentication/AbpCookieAuthenticationHandler.cs

@ -0,0 +1,89 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;
namespace PackageName.CompanyName.ProjectName.AIO.Host.Authentication;
public class AbpCookieAuthenticationHandler : CookieAuthenticationHandler
{
public AbpCookieAuthenticationHandler(
IOptionsMonitor<CookieAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder) : base(options, logger, encoder)
{
}
public AbpCookieAuthenticationHandler(
IOptionsMonitor<CookieAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected const string XRequestFromHeader = "X-Request-From";
protected const string DontRedirectRequestFromHeader = "vben";
protected override Task InitializeEventsAsync()
{
var events = new CookieAuthenticationEvents
{
OnRedirectToLogin = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
},
OnRedirectToAccessDenied = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
},
OnRedirectToLogout = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
},
OnRedirectToReturnUrl = ctx =>
{
if (string.Equals(ctx.Request.Headers[XRequestFromHeader], DontRedirectRequestFromHeader, StringComparison.Ordinal))
{
// ctx.Response.Headers.Location = ctx.RedirectUri;
ctx.Response.StatusCode = 401;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
}
};
Events = events;
return Task.CompletedTask;
}
}

38
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/BackgroundJobs/NotificationPublishJob.cs

@ -0,0 +1,38 @@
using LINGYUN.Abp.Notifications;
using Microsoft.Extensions.Options;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
namespace PackageName.CompanyName.ProjectName.AIO.Host.BackgroundJobs;
public class NotificationPublishJob : AsyncBackgroundJob<NotificationPublishJobArgs>, ITransientDependency
{
protected AbpNotificationsPublishOptions Options { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected INotificationDataSerializer NotificationDataSerializer { get; }
public NotificationPublishJob(
IOptions<AbpNotificationsPublishOptions> options,
IServiceScopeFactory serviceScopeFactory,
INotificationDataSerializer notificationDataSerializer)
{
Options = options.Value;
ServiceScopeFactory = serviceScopeFactory;
NotificationDataSerializer = notificationDataSerializer;
}
public override async Task ExecuteAsync(NotificationPublishJobArgs args)
{
var providerType = Type.GetType(args.ProviderType);
using (var scope = ServiceScopeFactory.CreateScope())
{
if (scope.ServiceProvider.GetRequiredService(providerType) is INotificationPublishProvider publishProvider)
{
var store = scope.ServiceProvider.GetRequiredService<INotificationStore>();
var notification = await store.GetNotificationOrNullAsync(args.TenantId, args.NotificationId);
notification.Data = NotificationDataSerializer.Serialize(notification.Data);
await publishProvider.PublishAsync(notification, args.UserIdentifiers);
}
}
}
}

22
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/BackgroundJobs/NotificationPublishJobArgs.cs

@ -0,0 +1,22 @@
using LINGYUN.Abp.Notifications;
namespace PackageName.CompanyName.ProjectName.AIO.Host.BackgroundJobs;
public class NotificationPublishJobArgs
{
public Guid? TenantId { get; set; }
public long NotificationId { get; set; }
public string ProviderType { get; set; }
public List<UserIdentifier> UserIdentifiers { get; set; }
public NotificationPublishJobArgs()
{
UserIdentifiers = new List<UserIdentifier>();
}
public NotificationPublishJobArgs(long id, string providerType, List<UserIdentifier> userIdentifiers, Guid? tenantId = null)
{
NotificationId = id;
ProviderType = providerType;
UserIdentifiers = userIdentifiers;
TenantId = tenantId;
}
}

11
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Controllers/HomeController.cs

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Mvc;
namespace PackageName.CompanyName.ProjectName.AIO.Host.Controllers;
public class HomeController : Controller
{
public IActionResult Index()
{
return Redirect("/swagger");
}
}

70
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Controllers/SettingMergeController.cs

@ -0,0 +1,70 @@
using LINGYUN.Abp.SettingManagement;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace PackageName.CompanyName.ProjectName.AIO.Host.Controllers;
[ExposeServices(
typeof(SettingController),
typeof(SettingMergeController))]
public class SettingMergeController : SettingController
{
private readonly SettingManagementMergeOptions _mergeOptions;
public SettingMergeController(
ISettingAppService settingAppService,
ISettingTestAppService settingTestAppService,
IOptions<SettingManagementMergeOptions> mergeOptions)
: base(settingAppService, settingTestAppService)
{
_mergeOptions = mergeOptions.Value;
}
[HttpGet]
[Route("by-current-tenant")]
public async override Task<SettingGroupResult> GetAllForCurrentTenantAsync()
{
var result = new SettingGroupResult();
var markTypeMap = new List<Type>
{
typeof(SettingMergeController),
};
foreach (var serviceType in _mergeOptions.GlobalSettingProviders
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType))))
{
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>();
var currentResult = await settingService.GetAllForCurrentTenantAsync();
foreach (var group in currentResult.Items)
{
result.AddGroup(group);
}
markTypeMap.Add(serviceType);
}
return result;
}
[HttpGet]
[Route("by-global")]
public async override Task<SettingGroupResult> GetAllForGlobalAsync()
{
var result = new SettingGroupResult();
var markTypeMap = new List<Type>
{
typeof(SettingMergeController),
};
foreach (var serviceType in _mergeOptions.GlobalSettingProviders
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType))))
{
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>();
var currentResult = await settingService.GetAllForGlobalAsync();
foreach (var group in currentResult.Items)
{
result.AddGroup(group);
}
markTypeMap.Add(serviceType);
}
return result;
}
}

45
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Controllers/UserSettingMergeController.cs

@ -0,0 +1,45 @@
using LINGYUN.Abp.SettingManagement;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace PackageName.CompanyName.ProjectName.AIO.Host.Controllers;
[ExposeServices(
typeof(UserSettingController),
typeof(UserSettingMergeController))]
public class UserSettingMergeController : UserSettingController
{
private readonly SettingManagementMergeOptions _mergeOptions;
public UserSettingMergeController(
IUserSettingAppService service,
IOptions<SettingManagementMergeOptions> mergeOptions)
: base(service)
{
_mergeOptions = mergeOptions.Value;
}
[HttpGet]
[Route("by-current-user")]
public async override Task<SettingGroupResult> GetAllForCurrentUserAsync()
{
var result = new SettingGroupResult();
var markTypeMap = new List<Type>
{
typeof(UserSettingMergeController),
};
foreach (var serviceType in _mergeOptions.UserSettingProviders
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType))))
{
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IUserSettingAppService>();
var currentResult = await settingService.GetAllForCurrentUserAsync();
foreach (var group in currentResult.Items)
{
result.AddGroup(group);
}
markTypeMap.Add(serviceType);
}
return result;
}
}

19
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/Dockerfile

@ -0,0 +1,19 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0
LABEL maintainer="colin.in@foxmail.com"
WORKDIR /app
COPY . /app
#东8区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
EXPOSE 80/tcp
VOLUME [ "./app/blobs" ]
VOLUME [ "./app/Logs" ]
VOLUME [ "./app/Modules" ]
RUN apt update
RUN apt install wget -y
ENTRYPOINT ["dotnet", "PackageName.CompanyName.ProjectName.AIO.dll"]

59
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/EventBus/Distributed/ChatMessageEventHandler.cs

@ -0,0 +1,59 @@
using LINGYUN.Abp.IM;
using LINGYUN.Abp.IM.Messages;
using LINGYUN.Abp.RealTime;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
namespace PackageName.CompanyName.ProjectName.AIO.Host.EventBus.Distributed
{
public class ChatMessageEventHandler : IDistributedEventHandler<RealTimeEto<ChatMessage>>, ITransientDependency
{
/// <summary>
/// Reference to <see cref="ILogger<DefaultNotificationDispatcher>"/>.
/// </summary>
public ILogger<ChatMessageEventHandler> Logger { get; set; }
/// <summary>
/// Reference to <see cref="AbpIMOptions"/>.
/// </summary>
protected AbpIMOptions Options { get; }
protected IMessageStore MessageStore { get; }
protected IMessageBlocker MessageBlocker { get; }
protected IMessageSenderProviderManager MessageSenderProviderManager { get; }
public ChatMessageEventHandler(
IOptions<AbpIMOptions> options,
IMessageStore messageStore,
IMessageBlocker messageBlocker,
IMessageSenderProviderManager messageSenderProviderManager)
{
Options = options.Value;
MessageStore = messageStore;
MessageBlocker = messageBlocker;
MessageSenderProviderManager = messageSenderProviderManager;
Logger = NullLogger<ChatMessageEventHandler>.Instance;
}
public async virtual Task HandleEventAsync(RealTimeEto<ChatMessage> eventData)
{
Logger.LogDebug($"Persistent chat message.");
var message = eventData.Data;
// 消息拦截
// 扩展敏感词汇过滤
await MessageBlocker.InterceptAsync(message);
await MessageStore.StoreMessageAsync(message);
// 发送消息
foreach (var provider in MessageSenderProviderManager.Providers)
{
Logger.LogDebug($"Sending message with provider {provider.Name}");
await provider.SendMessageAsync(message);
}
}
}
}

470
aspnet-core/templates/aio/content/host/PackageName.CompanyName.ProjectName.AIO.Host/EventBus/Distributed/NotificationEventHandler.cs

@ -0,0 +1,470 @@
using LINGYUN.Abp.Notifications;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using PackageName.CompanyName.ProjectName.AIO.Host.BackgroundJobs;
using PackageName.CompanyName.ProjectName.AIO.Host.MultiTenancy;
using System.Globalization;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Json;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.TextTemplating;
using Volo.Abp.Uow;
namespace PackageName.CompanyName.ProjectName.AIO.Host.EventBus.Distributed
{
/// <summary>
/// 订阅通知发布事件,统一发布消息
/// </summary>
/// <remarks>
/// 作用在于SignalR客户端只会与一台服务器建立连接,
/// 只有启用了SignlR服务端的才能真正将消息发布到客户端
/// </remarks>
public class NotificationEventHandler :
IDistributedEventHandler<NotificationEto<NotificationData>>,
IDistributedEventHandler<NotificationEto<NotificationTemplate>>,
ITransientDependency
{
/// <summary>
/// Reference to <see cref="ILogger<DefaultNotificationDispatcher>"/>.
/// </summary>
public ILogger<NotificationEventHandler> Logger { get; set; }
/// <summary>
/// Reference to <see cref="AbpNotificationsPublishOptions"/>.
/// </summary>
protected AbpNotificationsPublishOptions Options { get; }
/// <summary>
/// Reference to <see cref="ICurrentTenant"/>.
/// </summary>
protected ICurrentTenant CurrentTenant { get; }
/// <summary>
/// Reference to <see cref="ITenantConfigurationCache"/>.
/// </summary>
protected ITenantConfigurationCache TenantConfigurationCache { get; }
/// <summary>
/// Reference to <see cref="IJsonSerializer"/>.
/// </summary>
protected IJsonSerializer JsonSerializer { get; }
/// <summary>
/// Reference to <see cref="IBackgroundJobManager"/>.
/// </summary>
protected IBackgroundJobManager BackgroundJobManager { get; }
/// <summary>
/// Reference to <see cref="ITemplateRenderer"/>.
/// </summary>
protected ITemplateRenderer TemplateRenderer { get; }
/// <summary>
/// Reference to <see cref="INotificationStore"/>.
/// </summary>
protected INotificationStore NotificationStore { get; }
/// <summary>
/// Reference to <see cref="IStringLocalizerFactory"/>.
/// </summary>
protected IStringLocalizerFactory StringLocalizerFactory { get; }
/// <summary>
/// Reference to <see cref="INotificationDataSerializer"/>.
/// </summary>
protected INotificationDataSerializer NotificationDataSerializer { get; }
/// <summary>
/// Reference to <see cref="INotificationDefinitionManager"/>.
/// </summary>
protected INotificationDefinitionManager NotificationDefinitionManager { get; }
/// <summary>
/// Reference to <see cref="INotificationSubscriptionManager"/>.
/// </summary>
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; }
/// <summary>
/// Reference to <see cref="INotificationPublishProviderManager"/>.
/// </summary>
protected INotificationPublishProviderManager NotificationPublishProviderManager { get; }
/// <summary>
/// Initializes a new instance of the <see cref="NotificationEventHandler"/> class.
/// </summary>
public NotificationEventHandler(
ICurrentTenant currentTenant,
ITenantConfigurationCache tenantConfigurationCache,
IJsonSerializer jsonSerializer,
ITemplateRenderer templateRenderer,
IBackgroundJobManager backgroundJobManager,
IStringLocalizerFactory stringLocalizerFactory,
IOptions<AbpNotificationsPublishOptions> options,
INotificationStore notificationStore,
INotificationDataSerializer notificationDataSerializer,
INotificationDefinitionManager notificationDefinitionManager,
INotificationSubscriptionManager notificationSubscriptionManager,
INotificationPublishProviderManager notificationPublishProviderManager)
{
Options = options.Value;
TenantConfigurationCache = tenantConfigurationCache;
CurrentTenant = currentTenant;
JsonSerializer = jsonSerializer;
TemplateRenderer = templateRenderer;
BackgroundJobManager = backgroundJobManager;
StringLocalizerFactory = stringLocalizerFactory;
NotificationStore = notificationStore;
NotificationDataSerializer = notificationDataSerializer;
NotificationDefinitionManager = notificationDefinitionManager;
NotificationSubscriptionManager = notificationSubscriptionManager;
NotificationPublishProviderManager = notificationPublishProviderManager;
Logger = NullLogger<NotificationEventHandler>.Instance;
}
[UnitOfWork]
public async virtual Task HandleEventAsync(NotificationEto<NotificationTemplate> eventData)
{
var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name);
if (notification == null)
{
return;
}
var culture = eventData.Data.Culture;
if (culture.IsNullOrWhiteSpace())
{
culture = CultureInfo.CurrentCulture.Name;
}
using (CultureHelper.Use(culture, culture))
{
if (notification.NotificationType == NotificationType.System)
{
using (CurrentTenant.Change(null))
{
await SendToTenantAsync(null, notification, eventData);
var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync();
foreach (var activeTenant in allActiveTenants)
{
await SendToTenantAsync(activeTenant.Id, notification, eventData);
}
}
}
else
{
await SendToTenantAsync(eventData.TenantId, notification, eventData);
}
}
}
[UnitOfWork]
public async virtual Task HandleEventAsync(NotificationEto<NotificationData> eventData)
{
var notification = await NotificationDefinitionManager.GetOrNullAsync(eventData.Name);
if (notification == null)
{
return;
}
if (notification.NotificationType == NotificationType.System)
{
using (CurrentTenant.Change(null))
{
await SendToTenantAsync(null, notification, eventData);
var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync();
foreach (var activeTenant in allActiveTenants)
{
await SendToTenantAsync(activeTenant.Id, notification, eventData);
}
}
}
else
{
await SendToTenantAsync(eventData.TenantId, notification, eventData);
}
}
protected async virtual Task SendToTenantAsync(
Guid? tenantId,
NotificationDefinition notification,
NotificationEto<NotificationTemplate> eventData)
{
using (CurrentTenant.Change(tenantId))
{
var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers);
// 过滤用户指定提供者
if (eventData.UseProviders.Any())
{
providers = providers.Where(p => eventData.UseProviders.Contains(p.Name));
}
else if (notification.Providers.Any())
{
providers = providers.Where(p => notification.Providers.Contains(p.Name));
}
var notificationInfo = new NotificationInfo
{
Name = notification.Name,
TenantId = tenantId,
Severity = eventData.Severity,
Type = notification.NotificationType,
ContentType = notification.ContentType,
CreationTime = eventData.CreationTime,
Lifetime = notification.NotificationLifetime,
};
notificationInfo.SetId(eventData.Id);
var title = notification.DisplayName.Localize(StringLocalizerFactory);
var message = "";
try
{
// 由于模板通知受租户影响, 格式化失败的消息将被丢弃.
message = await TemplateRenderer.RenderAsync(
templateName: eventData.Data.Name,
model: eventData.Data.ExtraProperties,
cultureName: eventData.Data.Culture,
globalContext: new Dictionary<string, object>
{
// 模板不支持 $ 字符, 改为普通关键字
{ NotificationKeywords.Name, notification.Name },
{ NotificationKeywords.FormUser, eventData.Data.FormUser },
{ NotificationKeywords.Id, eventData.Id },
{ NotificationKeywords.Title, title.ToString() },
{ NotificationKeywords.CreationTime, eventData.CreationTime.ToString(Options.DateTimeFormat) },
});
}
catch(Exception ex)
{
Logger.LogWarning("Formatting template notification failed, message will be discarded, cause :{message}", ex.Message);
return;
}
var notificationData = new NotificationData();
notificationData.WriteStandardData(
title: title.ToString(),
message: message,
createTime: eventData.CreationTime,
formUser: eventData.Data.FormUser);
notificationData.ExtraProperties.AddIfNotContains(eventData.Data.ExtraProperties);
notificationInfo.Data = notificationData;
var subscriptionUsers = await GerSubscriptionUsersAsync(
notificationInfo.Name,
eventData.Users,
tenantId);
await PersistentNotificationAsync(
notificationInfo,
subscriptionUsers,
providers);
if (subscriptionUsers.Any())
{
// 发布通知
foreach (var provider in providers)
{
await PublishToSubscriberAsync(provider, notificationInfo, subscriptionUsers);
}
}
}
}
protected async virtual Task SendToTenantAsync(
Guid? tenantId,
NotificationDefinition notification,
NotificationEto<NotificationData> eventData)
{
using (CurrentTenant.Change(tenantId))
{
var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers);
// 过滤用户指定提供者
if (eventData.UseProviders.Any())
{
providers = providers.Where(p => eventData.UseProviders.Contains(p.Name));
}
else if (notification.Providers.Any())
{
providers = providers.Where(p => notification.Providers.Contains(p.Name));
}
var notificationInfo = new NotificationInfo
{
Name = notification.Name,
CreationTime = eventData.CreationTime,
Data = eventData.Data,
Severity = eventData.Severity,
Lifetime = notification.NotificationLifetime,
TenantId = tenantId,
Type = notification.NotificationType,
ContentType = notification.ContentType,
};
notificationInfo.SetId(eventData.Id);
notificationInfo.Data = NotificationDataSerializer.Serialize(notificationInfo.Data);
// 获取用户订阅
var subscriptionUsers = await GerSubscriptionUsersAsync(
notificationInfo.Name,
eventData.Users,
tenantId);
// 持久化通知
await PersistentNotificationAsync(
notificationInfo,
subscriptionUsers,
providers);
if (subscriptionUsers.Any())
{
// 发布订阅通知
foreach (var provider in providers)
{
await PublishToSubscriberAsync(provider, notificationInfo, subscriptionUsers);
}
}
}
}
/// <summary>
/// 获取用户订阅列表
/// </summary>
/// <param name="notificationName">通知名称</param>
/// <param name="sendToUsers">接收用户列表</param>
/// <param name="tenantId">租户标识</param>
/// <returns>用户订阅列表</returns>
protected async Task<IEnumerable<UserIdentifier>> GerSubscriptionUsersAsync(
string notificationName,
IEnumerable<UserIdentifier> sendToUsers,
Guid? tenantId = null)
{
try
{
// 获取用户订阅列表
var userSubscriptions = await NotificationSubscriptionManager.GetUsersSubscriptionsAsync(
tenantId,
notificationName,
sendToUsers);
return userSubscriptions.Select(us => new UserIdentifier(us.UserId, us.UserName));
}
catch(Exception ex)
{
Logger.LogWarning("Failed to get user subscription, message will not be received by the user, reason: {message}", ex.Message);
}
return new List<UserIdentifier>();
}
/// <summary>
/// 持久化通知并返回订阅用户列表
/// </summary>
/// <param name="notificationInfo">通知实体</param>
/// <param name="subscriptionUsers">订阅用户列表</param>
/// <param name="sendToProviders">通知发送提供者</param>
/// <returns>返回订阅者列表</returns>
protected async Task PersistentNotificationAsync(
NotificationInfo notificationInfo,
IEnumerable<UserIdentifier> subscriptionUsers,
IEnumerable<INotificationPublishProvider> sendToProviders)
{
try
{
// 持久化通知
await NotificationStore.InsertNotificationAsync(notificationInfo);
if (!subscriptionUsers.Any())
{
return;
}
// 持久化用户通知
await NotificationStore.InsertUserNotificationsAsync(notificationInfo, subscriptionUsers.Select(u => u.UserId));
if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne)
{
// 一次性通知取消用户订阅
await NotificationStore.DeleteUserSubscriptionAsync(
notificationInfo.TenantId,
subscriptionUsers,
notificationInfo.Name);
}
}
catch (Exception ex)
{
Logger.LogWarning("Failed to persistent notification failed, reason: {message}", ex.Message);
foreach (var provider in sendToProviders)
{
// 处理持久化失败进入后台队列
await ProcessingFailedToQueueAsync(provider, notificationInfo, subscriptionUsers);
}
}
}
/// <summary>
/// 发布订阅者通知
/// </summary>
/// <param name="provider">通知发布者</param>
/// <param name="notificationInfo">通知信息</param>
/// <param name="subscriptionUserIdentifiers">订阅用户列表</param>
/// <returns></returns>
protected async Task PublishToSubscriberAsync(
INotificationPublishProvider provider,
NotificationInfo notificationInfo,
IEnumerable<UserIdentifier> subscriptionUsers)
{
try
{
Logger.LogDebug($"Sending notification with provider {provider.Name}");
// 2024-10-10: 框架层面应该取消通知数据转换,而是交给提供商来实现
//var notifacationDataMapping = Options.NotificationDataMappings
// .GetMapItemOrDefault(provider.Name, notificationInfo.Name);
//if (notifacationDataMapping != null)
//{
// notificationInfo.Data = notifacationDataMapping.MappingFunc(notificationInfo.Data);
//}
// 发布
await provider.PublishAsync(notificationInfo, subscriptionUsers);
Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful");
}
catch (Exception ex)
{
Logger.LogWarning($"Send notification error with provider {provider.Name}");
Logger.LogWarning($"Error message:{ex.Message}");
Logger.LogDebug($"Failed to send notification {notificationInfo.Name}. Try to push notification to background job");
// 发送失败的消息进入后台队列
await ProcessingFailedToQueueAsync(provider, notificationInfo, subscriptionUsers);
}
}
/// <summary>
/// 处理失败的消息进入后台队列
/// </summary>
/// <remarks>
/// 注: 如果入队失败,消息将被丢弃.
/// </remarks>
/// <param name="provider"></param>
/// <param name="notificationInfo"></param>
/// <param name="subscriptionUsers"></param>
/// <returns></returns>
protected async Task ProcessingFailedToQueueAsync(
INotificationPublishProvider provider,
NotificationInfo notificationInfo,
IEnumerable<UserIdentifier> subscriptionUsers)
{
try
{
// 发送失败的消息进入后台队列
await BackgroundJobManager.EnqueueAsync(
new NotificationPublishJobArgs(
notificationInfo.GetId(),
provider.GetType().AssemblyQualifiedName,
subscriptionUsers.ToList(),
notificationInfo.TenantId));
}
catch(Exception ex)
{
Logger.LogWarning("Failed to push to background job, notification will be discarded, error cause: {message}", ex.Message);
}
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save