Browse Source

Merge branch 'dev' into timezone

pull/16861/head
maliming 3 years ago
parent
commit
606c608e83
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 4
      .github/scripts/update_versions.py
  2. 3
      Directory.Build.props
  3. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json
  4. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  5. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json
  6. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json
  7. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json
  8. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
  9. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  10. 8
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  11. 10
      docs/en/CLI.md
  12. 41
      docs/en/Getting-Started-React-Native.md
  13. 4
      docs/en/Image-Manipulation.md
  14. 14
      docs/en/Module-Entity-Extensions.md
  15. 25
      docs/en/Repositories.md
  16. BIN
      docs/en/images/generic-repositories.png
  17. 29
      framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs
  18. 28
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs
  19. 51
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs
  20. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
  21. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToNightlyCommand.cs
  22. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToPreviewCommand.cs
  23. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToStableCommand.cs
  24. 33
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs
  25. 177
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackagePreviewSwitcher.cs
  26. 6
      framework/src/Volo.Abp.Core/Volo/Abp/Studio/AbpStudioAnalyzeHelper.cs
  27. 18
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs
  28. 7
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs
  29. 2
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs
  30. 5
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs
  31. 9
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs
  32. 9
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs
  33. 8
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs
  34. 11
      framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs
  35. 13
      framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs
  36. 6
      framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/EventBusConsts.cs
  37. 55
      framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs
  38. 23
      framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventData.cs
  39. 75
      framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs
  40. 82
      framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs
  41. 12
      framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/MessageExtensions.cs
  42. 88
      framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs
  43. 62
      framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs
  44. 55
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs
  45. 5
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
  46. 9
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs
  47. 9
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs
  48. 3
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs
  49. 5
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiConfiguration.cs
  50. 1
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs
  51. 3
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs
  52. 5
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs
  53. 69
      framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs
  54. 39
      framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js
  55. 17
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProviderController.cs
  56. 48
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProvider_Tests.cs
  57. 33
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/CorrelationIdProvider/CorrelationIdProvider_Tests.cs
  58. 2
      modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpmdl.json
  59. 1
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json
  60. 3
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json
  61. 1
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json
  62. 3
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json
  63. 14
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs
  64. 6
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo.Abp.OpenIddict.AspNetCore.csproj
  65. 20
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs
  66. 2
      modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj
  67. 2
      modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj
  68. 2
      npm/lerna.json
  69. 26
      npm/ng-packs/package.json
  70. 131
      npm/ng-packs/packages/account-core/README.md
  71. 22
      npm/ng-packs/packages/account-core/package.json
  72. 130
      npm/ng-packs/packages/account/README.md
  73. 22
      npm/ng-packs/packages/account/package.json
  74. 1
      npm/ng-packs/packages/account/src/public-api.ts
  75. 131
      npm/ng-packs/packages/components/README.md
  76. 22
      npm/ng-packs/packages/components/package.json
  77. 131
      npm/ng-packs/packages/core/README.md
  78. 20
      npm/ng-packs/packages/core/package.json
  79. 4
      npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts
  80. 1
      npm/ng-packs/packages/core/src/lib/services/index.ts
  81. 20
      npm/ng-packs/packages/core/src/lib/services/window.service.ts
  82. 131
      npm/ng-packs/packages/feature-management/README.md
  83. 4
      npm/ng-packs/packages/feature-management/package.json
  84. 2
      npm/ng-packs/packages/generators/package.json
  85. 131
      npm/ng-packs/packages/identity/README.md
  86. 8
      npm/ng-packs/packages/identity/package.json
  87. 131
      npm/ng-packs/packages/oauth/README.md
  88. 22
      npm/ng-packs/packages/oauth/package.json
  89. 131
      npm/ng-packs/packages/permission-management/README.md
  90. 20
      npm/ng-packs/packages/permission-management/package.json
  91. 131
      npm/ng-packs/packages/schematics/README.md
  92. 23
      npm/ng-packs/packages/schematics/package.json
  93. 131
      npm/ng-packs/packages/setting-management/README.md
  94. 22
      npm/ng-packs/packages/setting-management/package.json
  95. 131
      npm/ng-packs/packages/tenant-management/README.md
  96. 22
      npm/ng-packs/packages/tenant-management/package.json
  97. 131
      npm/ng-packs/packages/theme-basic/README.md
  98. 22
      npm/ng-packs/packages/theme-basic/package.json
  99. 131
      npm/ng-packs/packages/theme-shared/README.md
  100. 14
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html

4
.github/scripts/update_versions.py

@ -46,9 +46,9 @@ def create_pr():
except Exception as e:
print(f"Error while creating PR: {e}")
pr.create_review_request(reviewers=["gizemmutukurt"])
pr.create_review_request(reviewers=["ebicoglu", "gizemmutukurt", "skoc10"])
if __name__ == "__main__":
should_create_pr = update_latest_versions()
if should_create_pr:
create_pr()
create_pr()

3
Directory.Build.props

@ -42,6 +42,9 @@
<IsTestProject Condition="$(MSBuildProjectFullPath.Contains('test')) and ($(MSBuildProjectName.EndsWith('.Tests')) or $(MSBuildProjectName.EndsWith('.TestBase')))">true</IsTestProject>
<!-- OpenIddict https://www.nuget.org/packages/OpenIddict.Core -->
<OpenIddictPackageVersion>4.5.0</OpenIddictPackageVersion>
</PropertyGroup>
<ItemGroup>

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json

@ -137,6 +137,7 @@
"Address": "العنوان",
"Homepage": "الصفحة الرئيسية",
"Year": "السنة",
"Year_Plural": "سنوات",
"Copyright": "حقوق النشر © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "التصميم المُقاد بالنطاق DDD",
"CrossCuttingConcerns": "اهتمامات مشتركة",

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json

@ -141,6 +141,7 @@
"Address": "Address",
"Homepage": "Homepage",
"Year": "Year",
"Year_Plural": "Years",
"Copyright": "Copyright © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Domain Driven Design",
"CrossCuttingConcerns": "Cross Cutting Concerns",
@ -214,7 +215,7 @@
"AboutUs": "About Us",
"HowItWorks": "How it works?",
"ReleaseNotes": "Release Notes",
"DetailedChangeNotes" : "Detailed change notes",
"DetailedChangeNotes" : "Detailed Change Notes",
"SeeTrainings": "See Trainings"
}
}

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json

@ -140,6 +140,7 @@
"Address": "Osoite",
"Homepage": "Kotisivu",
"Year": "vuosi",
"Year_Plural": "vuotta",
"Copyright": "Tekijänoikeus © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Domain Driven Design",
"CrossCuttingConcerns": "Cross Cutting Concerns",

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json

@ -138,6 +138,7 @@
"Address": "Cím",
"Homepage": "Kezdőlap",
"Year": "Év",
"Year_Plural": "Év",
"Copyright": "Copyright © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Domainvezérelt tervezés",
"CrossCuttingConcerns": "Cross Cutting Concerns",

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json

@ -132,6 +132,7 @@
"Address": "Adres",
"Homepage": "Anasayfa",
"Year": "Yıl",
"Year_Plural": "Yıl",
"Copyright": "Telif hakkı © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Alan Odaklı Tasarım",
"CrossCuttingConcerns": "Cross Cutting Concerns",

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json

@ -140,6 +140,7 @@
"Address": "地址",
"Homepage": "主页",
"Year": "年份",
"Year_Plural": "年份",
"Copyright": "版权所有 © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "领域驱动设计",
"CrossCuttingConcerns": "横切关注点",

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -893,6 +893,7 @@
"WeAreHereToHelp_Description1": "You can browse our help topics or search in the frequently asked questions, \n or you can ask us a question by using the contact form.",
"OtherModules": "Other Modules",
"OtherModules_Description1": "Account, Audit Logging, Chat , CMS Kit,File Management , Forms, GDPR, Identity, Language Management, Payment , Saas and more...",
"HowItWorks_DatabaseProviderOptions": "Database provider options"
"HowItWorks_DatabaseProviderOptions": "Database provider options",
"SeeFAQ" : "See FAQ"
}
}

8
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -21,7 +21,7 @@
"SetDefault": "Varsayılan olarak ayarla",
"DefaultOrganization": "Varsayılan",
"StartDate": "Başlangıç tarihi",
"EndDate": "bitiş tarihi",
"EndDate": "Bitiş tarihi",
"Modules": "Modüller",
"LicenseExtendMessage": "Lisans bitiş tarihiniz {0} tarihine kadar uzatıldı",
"LicenseUpgradeMessage": "Lisansınız {0} lisansa yükseltildi",
@ -129,8 +129,8 @@
"TellUsWhatYouNeed": "Bize neye ihtiyacın olduğunu söyle.",
"YourMessage": "Mesajın",
"YourFullName": "Tam adınız",
"EmailField": "E",
"YourEmailAddress": "E",
"EmailField": "E-posta Adresi",
"YourEmailAddress": "E-posta adresiniz",
"HowMayWeHelpYou": "Size nasıl yardımcı olabiliriz?",
"SendMessage": "Mesaj gönder",
"Success": "Başarı",
@ -808,4 +808,4 @@
"BlazoriseLicense": "Blazorise lisansı satın almamız gerekiyor mu?",
"BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Ticari ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor."
}
}
}

10
docs/en/CLI.md

@ -419,7 +419,7 @@ abp remove-proxy -t csharp --folder MyProxies/InnerFolder
### switch-to-preview
You can use this command to switch your project to latest preview version of the ABP framework.
You can use this command to switch your solution or project to latest preview version of the ABP framework.
Usage:
@ -429,12 +429,12 @@ abp switch-to-preview [options]
#### Options
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory.
* `--directory` or `-d`: Specifies the directory. The solution or project should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-nightly
You can use this command to switch your project to latest [nightly](Nightly-Builds.md) preview version of the ABP framework packages.
You can use this command to switch your solution or project to latest [nightly](Nightly-Builds.md) preview version of the ABP framework packages.
Usage:
@ -444,7 +444,7 @@ abp switch-to-nightly [options]
#### Options
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory.
* `--directory` or `-d`: Specifies the directory. The solution or project should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-stable
@ -457,7 +457,7 @@ abp switch-to-stable [options]
````
#### Options
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory.
* `--directory` or `-d`: Specifies the directory. The solution or project should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-local

41
docs/en/Getting-Started-React-Native.md

@ -36,17 +36,9 @@ abp new MyCompanyName.MyProjectName -csf -u <angular or mvc> -m react-native
This command will prepare a solution with an **Angular** or an **MVC** (depends on your choice), a **.NET Core**, and a **React Native** project in it.
### 2. Direct Download
### 2. Generating a CLI Command from Get Started Page
You may [download a solution scaffold directly on ABP.io](https://abp.io/get-started) if you are more comfortable with GUI or simply want to try ABP without installing the CLI.
Please do the following:
1. Click on the "DIRECT DOWNLOAD" tab.
2. Fill out the short form about your project.
3. Click on the "Create now" button.
...and a customized download will start in a few seconds.
You can generate a CLI command on the [get started page of the abp.io website](https://abp.io/get-started). Then, use the command on your terminal to create a new [Startup Template](./Startup-Templates/Index.md).
## How to Configure & Run the Backend
@ -54,26 +46,6 @@ Please do the following:
> When you are using OpenIddict, You should remove 'clientSecret' on Environment.js (if exists) and disable "HTTPS-only" settings. (Openiddict has default since Version 6.0)
### How to disable Https-only in Openiddict.
You should add this code on {{ if Tiered == "No" }}`MyProjectNameHttpApiHostModule`{{ else if Tiered == "Yes" }}`MyProjectNameAuthServerModule`{{ end }}.
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
#if DEBUG
PreConfigure<OpenIddictServerBuilder>(options =>
{
options
.UseAspNetCore()
.DisableTransportSecurityRequirement();
});
#endif
//....
}
```
A React Native application running on an Android emulator or a physical phone **can not connect to the backend** on `localhost`. To fix this problem, it is necessary to run the backend application on your **local IP address**.
{{ if Tiered == "No"}}
@ -99,13 +71,14 @@ Run the backend application as described in the [getting started document](Getti
## How to disable the Https-only settings of OpenIddict
Go to MyProjectNameHttpApiHostModule.cs under the host project. And put these codes under the `PreConfigureServices` function.
Open the {{ if Tiered == "No" }}`MyProjectNameHttpApiHostModule`{{ else if Tiered == "Yes" }}`MyProjectNameAuthServerModule`{{ end }} project and copy-paste the below code-block to the `PreConfigureServices` method:
```csharp
#if DEBUG
PreConfigure<OpenIddictServerBuilder>(options => {
options.UseAspNetCore()
.DisableTransportSecurityRequirement();
PreConfigure<OpenIddictServerBuilder>(options =>
{
options.UseAspNetCore()
.DisableTransportSecurityRequirement();
});
#endif
```

4
docs/en/Image-Manipulation.md

@ -41,7 +41,7 @@ public class YourModule : AbpModule
ABP Framework provides two image resizer/compressor implementations out of the box:
* [Magick.NET](#magicknet-provider)
* [Magick.NET](#magick-net-provider)
* [ImageSharp](#imagesharp-provider)
You should install one of these provides to make it actually working.
@ -377,4 +377,4 @@ public async Task<IActionResult> Upload(IFormFile file)
{
//...
}
```
```

14
docs/en/Module-Entity-Extensions.md

@ -255,6 +255,20 @@ property =>
Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement.
### UI Order
When you define a property, it appears on the data table, create and edit forms on the related UI page. However, you can control its order. Example:
````csharp
property =>
{
property.UI.Order = 1;
//...other configurations
}
````
Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement.
### HTTP API Availability
Even if you disable a property on UI, it can be still available through the HTTP API. By default, a property is available on all APIs.

25
docs/en/Repositories.md

@ -192,6 +192,31 @@ Major vendors, like Entity Framework, NHibernate or MongoDB already support `IQu
There are also `IReadOnlyRepository<TEntity, TKey>` and `IReadOnlyBasicRepository<Tentity, TKey>` interfaces for who only want to depend on querying capabilities of the repositories.
The `IReadOnlyRepository<TEntity, TKey>` derives the `IReadOnlyBasicRepository<Tentity, TKey>` and provides the following properties and methods as well:
Properties:
`AsyncExecuter`: a service that is used to execute an `IQueryable<T>` object asynchronously **without depending on the actual database provider**.
Methods:
- `GetListAsync()`
- `GetQueryableAsync()`
- `WithDetails()` 1 overload
- `WithDetailsAsync()` 1 overload
Where as the `IReadOnlyBasicRepository<Tentity, TKey>` provides the following methods:
- `GetCountAsync()`
- `GetListAsync()`
- `GetPagedListAsync()`
They can all be seen as below:
![generic-repositories](\images\generic-repositories.png)
### Generic Repository without a Primary Key
If your entity does not have an Id primary key (it may have a composite primary key for instance) then you cannot use the `IRepository<TEntity, TKey>` (or basic/readonly versions) defined above. In that case, you can inject and use `IRepository<TEntity>` for your entity.

BIN
docs/en/images/generic-repositories.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

29
framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
@ -21,7 +22,6 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
var daprSerializer = HttpContext.RequestServices.GetRequiredService<IDaprSerializer>();
var body = (await JsonDocument.ParseAsync(HttpContext.Request.Body));
var id = body.RootElement.GetProperty("id").GetString();
var pubSubName = body.RootElement.GetProperty("pubsubname").GetString();
var topic = body.RootElement.GetProperty("topic").GetString();
var data = body.RootElement.GetProperty("data").GetRawText();
@ -32,8 +32,31 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
}
var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>();
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(id, distributedEventBus.GetEventType(topic), eventData);
if (IsAbpDaprEventData(data))
{
var daprEventData = daprSerializer.Deserialize(data, typeof(AbpDaprEventData)).As<AbpDaprEventData>();
var eventData = daprSerializer.Deserialize(daprEventData.JsonData, distributedEventBus.GetEventType(daprEventData.Topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(daprEventData.Topic), eventData, daprEventData.MessageId, daprEventData.CorrelationId);
}
else
{
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(topic), eventData);
}
return Ok();
}
protected virtual bool IsAbpDaprEventData(string data)
{
var document = JsonDocument.Parse(data);
var objects = document.RootElement.EnumerateObject().ToList();
return objects.Count == 5 &&
objects.Any(x => x.Name.Equals("PubSubName", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("Topic", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("MessageId", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("JsonData", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("CorrelationId", StringComparison.CurrentCultureIgnoreCase));
}
}

28
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Http;
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@ -20,16 +21,31 @@ public class AbpCorrelationIdMiddleware : IMiddleware, ITransientDependency
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var correlationId = _correlationIdProvider.Get();
var correlationId = GetCorrelationIdFromRequest(context);
try
using (_correlationIdProvider.Change(correlationId))
{
await next(context);
try
{
await next(context);
}
finally
{
CheckAndSetCorrelationIdOnResponse(context, _options, correlationId);
}
}
finally
}
protected virtual string GetCorrelationIdFromRequest(HttpContext context)
{
string correlationId = context.Request.Headers[_options.HttpHeaderName];
if (correlationId.IsNullOrEmpty())
{
CheckAndSetCorrelationIdOnResponse(context, _options, correlationId);
correlationId = Guid.NewGuid().ToString("N");
context.Request.Headers[_options.HttpHeaderName] = correlationId;
}
return correlationId;
}
protected virtual void CheckAndSetCorrelationIdOnResponse(

51
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs

@ -1,51 +0,0 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Tracing;
namespace Volo.Abp.AspNetCore.Tracing;
[Dependency(ReplaceServices = true)]
public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency
{
protected IHttpContextAccessor HttpContextAccessor { get; }
protected AbpCorrelationIdOptions Options { get; }
public AspNetCoreCorrelationIdProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<AbpCorrelationIdOptions> options)
{
HttpContextAccessor = httpContextAccessor;
Options = options.Value;
}
public virtual string Get()
{
if (HttpContextAccessor.HttpContext?.Request?.Headers == null)
{
return CreateNewCorrelationId();
}
string correlationId = HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName];
if (correlationId.IsNullOrEmpty())
{
lock (HttpContextAccessor.HttpContext.Request.Headers)
{
if (correlationId.IsNullOrEmpty())
{
correlationId = CreateNewCorrelationId();
HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName] = correlationId;
}
}
}
return correlationId;
}
protected virtual string CreateNewCorrelationId()
{
return Guid.NewGuid().ToString("N");
}
}

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.Cli.Commands;
public class LoginCommand : IConsoleCommand, ITransientDependency
{
public const string Name = "login";
public ILogger<LoginCommand> Logger { get; set; }
protected AuthService AuthService { get; }
@ -122,6 +122,12 @@ public class LoginCommand : IConsoleCommand, ITransientDependency
return;
}
if (ex.Message.Contains("RequiresTwoFactor"))
{
Logger.LogError("Two factor authentication is enabled for your account. Please use `abp login --device` command to login.");
return;
}
if (TryGetErrorMessageFromHtmlPage(ex.Message, out var errorMsg))
{
Logger.LogError(errorMsg);

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToNightlyCommand.cs

@ -31,7 +31,7 @@ public class SwitchToNightlyCommand : IConsoleCommand, ITransientDependency
sb.AppendLine(" abp switch-to-nightly [options]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("-sd|--solution-directory");
sb.AppendLine("-d|--directory");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToPreviewCommand.cs

@ -31,7 +31,7 @@ public class SwitchToPreviewCommand : IConsoleCommand, ITransientDependency
sb.AppendLine(" abp switch-to-preview [options]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("-sd|--solution-directory");
sb.AppendLine("-d|--directory");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToStableCommand.cs

@ -31,7 +31,7 @@ public class SwitchToStableCommand : IConsoleCommand, ITransientDependency
sb.AppendLine(" abp switch-to-stable [options]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("-sd|--solution-directory");
sb.AppendLine("-d|--directory");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");

33
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs

@ -566,28 +566,37 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
private static void ChangeThemeToBasicForMvcProjects(ProjectBuildContext context, string defaultThemeName)
{
var projects = new Dictionary<string, string>
{
{".Web", "MyProjectNameWebModule"},
{".HttpApi.Host", "MyProjectNameHttpApiHostModule"},
{".AuthServer", "MyProjectNameAuthServerModule"},
{".Web.Public", "MyProjectNameWebPublicModule"},
{".Web.Public.Host", "MyProjectNameWebPublicModule"},
{"", "MyProjectNameWebModule"}
var projectNames = new[]
{
".Web", ".HttpApi.Host", ".AuthServer", ".Web.Public", ".Web.Public.Host",
"" //for app-nolayers-mvc
};
foreach (var project in projects)
foreach (var projectName in projectNames)
{
var projectPath = $"/MyCompanyName.MyProjectName{projectName}/MyCompanyName.MyProjectName{projectName}.csproj";
var projectFile = context.Files.FirstOrDefault(x => x.Name.Contains(projectPath));
if (projectFile == null)
{
continue;
}
var moduleFile = ConvertProjectFileToModuleFile(context, projectFile);
if (moduleFile == null)
{
continue;
}
ReplacePackageReferenceWithProjectReference(
context,
$"/MyCompanyName.MyProjectName{project.Key}/MyCompanyName.MyProjectName{project.Key}.csproj",
projectFile.Name,
$"Volo.Abp.AspNetCore.Mvc.UI.Theme.{defaultThemeName}",
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj"
);
ReplaceAllKeywords(
context,
$"/MyCompanyName.MyProjectName{project.Key}/{project.Value}.cs",
moduleFile.Name,
defaultThemeName,
Basic
);

177
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackagePreviewSwitcher.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
@ -32,6 +33,37 @@ public class PackagePreviewSwitcher : ITransientDependency
{
var solutionPaths = GetSolutionPaths(commandLineArgs);
if (solutionPaths.Any())
{
await SwitchSolutionsToPreview(solutionPaths);
}
else
{
var projectPaths = GetProjectPaths(commandLineArgs);
await SwitchProjectsToPreview(projectPaths);
}
}
private async Task SwitchProjectsToPreview(List<string> projects)
{
foreach (var project in projects)
{
var folder = Path.GetDirectoryName(project);
await _nugetPackagesVersionUpdater.UpdateProjectAsync(
project,
includeReleaseCandidates: true);
await _npmPackagesUpdater.Update(
folder,
false,
true);
}
}
private async Task SwitchSolutionsToPreview(List<string> solutionPaths)
{
foreach (var solutionPath in solutionPaths)
{
var solutionFolder = Path.GetDirectoryName(solutionPath);
@ -56,69 +88,134 @@ public class PackagePreviewSwitcher : ITransientDependency
}
}
public async Task SwitchToNightlyPreview(CommandLineArgs commandLineArgs)
public async Task SwitchToStable(CommandLineArgs commandLineArgs)
{
var solutionPaths = GetSolutionPaths(commandLineArgs);
if (solutionPaths.Any())
{
await SwitchSolutionsToStable(solutionPaths);
}
else
{
var projectPaths = GetProjectPaths(commandLineArgs);
await SwitchProjectsToStable(projectPaths);
}
}
private async Task SwitchProjectsToStable(List<string> projects)
{
foreach (var project in projects)
{
var folder = Path.GetDirectoryName(project);
await _nugetPackagesVersionUpdater.UpdateProjectAsync(
project,
false,
false,
true);
await _npmPackagesUpdater.Update(
folder,
false,
false,
true);
}
}
private async Task SwitchSolutionsToStable(List<string> solutionPaths)
{
foreach (var solutionPath in solutionPaths)
{
var solutionFolder = Path.GetDirectoryName(solutionPath);
var solutionAngularFolder = GetSolutionAngularFolder(solutionFolder);
_packageSourceManager.Add(solutionFolder, "ABP Nightly", "https://www.myget.org/F/abp-nightly/api/v3/index.json");
_packageSourceManager.Remove(solutionFolder, "ABP Nightly");
if (solutionPath != null)
{
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(
solutionPath,
true);
}
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(
solutionPath,
false,
false,
true);
await _npmPackagesUpdater.Update(
solutionFolder,
false,
false,
true);
if (solutionAngularFolder != null)
{
await _npmPackagesUpdater.Update(
solutionAngularFolder,
false,
false,
true);
}
}
}
public async Task SwitchToStable(CommandLineArgs commandLineArgs)
public async Task SwitchToNightlyPreview(CommandLineArgs commandLineArgs)
{
var solutionPaths = GetSolutionPaths(commandLineArgs);
if (solutionPaths.Any())
{
await SwitchSolutionsToNightlyPreview(solutionPaths);
}
else
{
var projectPaths = GetProjectPaths(commandLineArgs);
await SwitchProjectsToNightlyPreview(projectPaths);
}
}
private async Task SwitchProjectsToNightlyPreview(List<string> projects)
{
foreach (var project in projects)
{
var folder = Path.GetDirectoryName(project);
_packageSourceManager.Add(FindSolutionFolder(project) ?? folder, "ABP Nightly",
"https://www.myget.org/F/abp-nightly/api/v3/index.json");
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(
project,
true);
await _npmPackagesUpdater.Update(
folder,
true);
}
}
private async Task SwitchSolutionsToNightlyPreview(List<string> solutionPaths)
{
foreach (var solutionPath in solutionPaths)
{
var solutionFolder = Path.GetDirectoryName(solutionPath);
var solutionAngularFolder = GetSolutionAngularFolder(solutionFolder);
_packageSourceManager.Remove(solutionFolder, "ABP Nightly");
_packageSourceManager.Add(solutionFolder, "ABP Nightly",
"https://www.myget.org/F/abp-nightly/api/v3/index.json");
if (solutionPath != null)
{
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(
solutionPath,
false,
false,
true);
}
await _npmPackagesUpdater.Update(
solutionFolder,
false,
false,
true);
if (solutionAngularFolder != null)
{
await _npmPackagesUpdater.Update(
solutionAngularFolder,
false,
false,
true);
}
}
@ -126,22 +223,18 @@ public class PackagePreviewSwitcher : ITransientDependency
private List<string> GetSolutionPaths(CommandLineArgs commandLineArgs)
{
var directory = commandLineArgs.Options.GetOrNull(Options.SolutionDirectory.Short, Options.SolutionDirectory.Long)
?? Directory.GetCurrentDirectory();
var solutionPaths = Directory.GetFiles(directory, "*.sln", SearchOption.AllDirectories);
if (!solutionPaths.Any())
{
Logger.LogWarning("No solution (.sln) found to change version.");
}
return Directory.GetFiles(GetDirectory(commandLineArgs), "*.sln", SearchOption.AllDirectories).ToList();
}
return solutionPaths.ToList();
private List<string> GetProjectPaths(CommandLineArgs commandLineArgs)
{
return Directory.GetFiles(GetDirectory(commandLineArgs), "*.csproj", SearchOption.AllDirectories).ToList();
}
private string GetSolutionFolder(CommandLineArgs commandLineArgs)
private string GetDirectory(CommandLineArgs commandLineArgs)
{
return commandLineArgs.Options.GetOrNull(Options.SolutionDirectory.Short, Options.SolutionDirectory.Long)
?? commandLineArgs.Options.GetOrNull(Options.Directory.Short, Options.Directory.Long)
?? Directory.GetCurrentDirectory();
}
@ -160,6 +253,31 @@ public class PackagePreviewSwitcher : ITransientDependency
}
return null;
}
[CanBeNull]
private string FindSolutionFolder(string projectFile)
{
var targetFolder = Path.GetDirectoryName(projectFile);
do
{
if (Directory.GetParent(targetFolder) != null)
{
targetFolder = Directory.GetParent(targetFolder).FullName;
}
else
{
return Path.GetDirectoryName(projectFile);
}
if (Directory.GetFiles(targetFolder, "*.sln", SearchOption.TopDirectoryOnly).Any())
{
break;
}
} while (targetFolder != null);
return targetFolder;
}
public static class Options
@ -169,5 +287,10 @@ public class PackagePreviewSwitcher : ITransientDependency
public const string Short = "sd";
public const string Long = "solution-directory";
}
public static class Directory
{
public const string Short = "d";
public const string Long = "directory";
}
}
}

6
framework/src/Volo.Abp.Core/Volo/Abp/Studio/AbpStudioAnalyzeHelper.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.Studio;
public static class AbpStudioAnalyzeHelper
{
public static bool IsInAnalyzeMode { get; set; }
}

18
framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs

@ -1,17 +1,27 @@
using System;
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Tracing;
public class DefaultCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency
{
public string Get()
private readonly AsyncLocal<string?> _currentCorrelationId = new AsyncLocal<string?>();
private string? CorrelationId => _currentCorrelationId.Value;
public virtual string? Get()
{
return CreateNewCorrelationId();
return CorrelationId;
}
protected virtual string CreateNewCorrelationId()
public virtual IDisposable Change(string? correlationId)
{
return Guid.NewGuid().ToString("N");
var parent = CorrelationId;
_currentCorrelationId.Value = correlationId;
return new DisposeAction(() =>
{
_currentCorrelationId.Value = parent;
});
}
}

7
framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs

@ -1,9 +1,10 @@
using JetBrains.Annotations;
using System;
namespace Volo.Abp.Tracing;
public interface ICorrelationIdProvider
{
[NotNull]
string Get();
string? Get();
IDisposable Change(string? correlationId);
}

2
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs

@ -6,6 +6,8 @@ public interface IDaprSerializer
{
byte[] Serialize(object obj);
string SerializeToString(object obj);
object Deserialize(byte[] value, Type type);
object Deserialize(string value, Type type);

5
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs

@ -19,6 +19,11 @@ public class Utf8JsonDaprSerializer : IDaprSerializer, ITransientDependency
return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj));
}
public string SerializeToString(object obj)
{
return _jsonSerializer.Serialize(obj);
}
public object Deserialize(byte[] value, Type type)
{
return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value));

9
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs

@ -48,13 +48,20 @@ public class IncomingEventRecord :
public IncomingEventInfo ToIncomingEventInfo()
{
return new IncomingEventInfo(
var info = new IncomingEventInfo(
Id,
MessageId,
EventName,
EventData,
CreationTime
);
foreach (var property in ExtraProperties)
{
info.SetProperty(property.Key, property.Value);
}
return info;
}
public void MarkAsProcessed(DateTime processedTime)

9
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs

@ -41,11 +41,18 @@ public class OutgoingEventRecord :
public OutgoingEventInfo ToOutgoingEventInfo()
{
return new OutgoingEventInfo(
var info = new OutgoingEventInfo(
Id,
EventName,
EventData,
CreationTime
);
foreach (var property in ExtraProperties)
{
info.SetProperty(property.Key, property.Value);
}
return info;
}
}

8
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/DatabaseMigrationEventHandlerBase.cs → framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs

@ -14,7 +14,7 @@ using Volo.Abp.Uow;
namespace Volo.Abp.EntityFrameworkCore.Migrations;
public abstract class DatabaseMigrationEventHandlerBase<TDbContext> :
public abstract class EfCoreDatabaseMigrationEventHandlerBase<TDbContext> :
IDistributedEventHandler<TenantCreatedEto>,
IDistributedEventHandler<TenantConnectionStringUpdatedEto>,
IDistributedEventHandler<ApplyDatabaseMigrationsEto>,
@ -41,9 +41,9 @@ public abstract class DatabaseMigrationEventHandlerBase<TDbContext> :
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected ITenantStore TenantStore { get; }
protected IDistributedEventBus DistributedEventBus { get; }
protected ILogger<DatabaseMigrationEventHandlerBase<TDbContext>> Logger { get; }
protected ILogger<EfCoreDatabaseMigrationEventHandlerBase<TDbContext>> Logger { get; }
protected DatabaseMigrationEventHandlerBase(
protected EfCoreDatabaseMigrationEventHandlerBase(
string databaseName,
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager,
@ -57,7 +57,7 @@ public abstract class DatabaseMigrationEventHandlerBase<TDbContext> :
DatabaseName = databaseName;
DistributedEventBus = distributedEventBus;
Logger = loggerFactory.CreateLogger<DatabaseMigrationEventHandlerBase<TDbContext>>();
Logger = loggerFactory.CreateLogger<EfCoreDatabaseMigrationEventHandlerBase<TDbContext>>();
}
public virtual async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData)

11
framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Data;
namespace Volo.Abp.EventBus.Distributed;
@ -40,4 +41,14 @@ public class IncomingEventInfo : IHasExtraProperties
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
}
public void SetCorrelationId(string correlationId)
{
ExtraProperties[EventBusConsts.CorrelationIdHeaderName] = correlationId;
}
public string GetCorrelationId()
{
return ExtraProperties.GetOrDefault(EventBusConsts.CorrelationIdHeaderName)?.ToString();
}
}

13
framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Data;
namespace Volo.Abp.EventBus.Distributed;
@ -36,4 +37,14 @@ public class OutgoingEventInfo : IHasExtraProperties
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
}
}
public void SetCorrelationId(string correlationId)
{
ExtraProperties[EventBusConsts.CorrelationIdHeaderName] = correlationId;
}
public string GetCorrelationId()
{
return ExtraProperties.GetOrDefault(EventBusConsts.CorrelationIdHeaderName)?.ToString();
}
}

6
framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/EventBusConsts.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.EventBus;
public static class EventBusConsts
{
public const string CorrelationIdHeaderName = "X-Correlation-Id";
}

55
framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
@ -14,6 +15,7 @@ using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Volo.Abp.EventBus.Azure;
@ -42,7 +44,8 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
IAzureServiceBusMessageConsumerFactory messageConsumerFactory,
IPublisherPool publisherPool,
IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus)
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider)
: base(serviceScopeFactory,
currentTenant,
unitOfWorkManager,
@ -50,7 +53,8 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
guidGenerator,
clock,
eventHandlerInvoker,
localEventBus)
localEventBus,
correlationIdProvider)
{
Options = abpAzureEventBusOptions.Value;
Serializer = serializer;
@ -86,24 +90,30 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(message.Body.ToArray(), eventType);
if (await AddToInboxAsync(message.MessageId, eventName, eventType, eventData))
if (await AddToInboxAsync(message.MessageId, eventName, eventType, eventData, message.CorrelationId))
{
return;
}
await TriggerHandlersDirectAsync(eventType, eventData);
using (CorrelationIdProvider.Change(message.CorrelationId))
{
await TriggerHandlersDirectAsync(eventType, eventData);
}
}
public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, outgoingEvent.Id);
await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, outgoingEvent.GetCorrelationId(), outgoingEvent.Id);
}
public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
@ -125,18 +135,23 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
message.MessageId = outgoingEvent.Id.ToString();
}
message.CorrelationId = outgoingEvent.GetCorrelationId();
if (!messageBatch.TryAddMessage(message))
{
throw new AbpException(
"The message is too large to fit in the batch. Set AbpEventBusBoxesOptions.OutboxWaitingEventMaxCount to reduce the number");
}
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
}
await publisher.SendMessagesAsync(messageBatch);
@ -152,7 +167,10 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>();
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId()))
{
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
}
if (exceptions.Any())
{
ThrowOriginalExceptions(eventType, exceptions);
@ -244,12 +262,13 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
{
var body = Serializer.Serialize(eventData);
return PublishAsync(eventName, body, null);
return PublishAsync(eventName, body, CorrelationIdProvider.Get(), null);
}
protected virtual async Task PublishAsync(
string eventName,
byte[] body,
[CanBeNull] string correlationId,
Guid? eventId)
{
var message = new ServiceBusMessage(body)
@ -262,6 +281,8 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen
message.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N");
}
message.CorrelationId = correlationId;
var publisher = await PublisherPool.GetAsync(
Options.TopicName,
Options.ConnectionName);

23
framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventData.cs

@ -0,0 +1,23 @@
namespace Volo.Abp.EventBus.Dapr;
public class AbpDaprEventData
{
public string PubSubName { get; set; }
public string Topic { get; set; }
public string MessageId { get; set; }
public string JsonData { get; set; }
public string CorrelationId { get; set; }
public AbpDaprEventData(string pubSubName, string topic, string messageId, string jsonData, string correlationId)
{
PubSubName = pubSubName;
Topic = topic;
MessageId = messageId;
JsonData = jsonData;
CorrelationId = correlationId;
}
}

75
framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs

@ -13,6 +13,7 @@ using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Volo.Abp.EventBus.Dapr;
@ -39,8 +40,17 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
IDaprSerializer serializer,
IOptions<AbpDaprEventBusOptions> daprEventBusOptions,
IAbpDaprClientFactory daprClientFactory,
ILocalEventBus localEventBus)
: base(serviceScopeFactory, currentTenant, unitOfWorkManager, abpDistributedEventBusOptions, guidGenerator, clock, eventHandlerInvoker, localEventBus)
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider)
: base(serviceScopeFactory,
currentTenant,
unitOfWorkManager,
abpDistributedEventBusOptions,
guidGenerator,
clock,
eventHandlerInvoker,
localEventBus,
correlationIdProvider)
{
Serializer = serializer;
DaprEventBusOptions = daprEventBusOptions.Value;
@ -119,9 +129,9 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
}
protected override async Task PublishToEventBusAsync(Type eventType, object eventData)
protected async override Task PublishToEventBusAsync(Type eventType, object eventData)
{
await PublishToDaprAsync(eventType, eventData);
await PublishToDaprAsync(eventType, eventData, null, CorrelationIdProvider.Get());
}
protected override void AddToUnitOfWork(IUnitOfWork unitOfWork, UnitOfWorkEventRecord eventRecord)
@ -141,43 +151,52 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
return handlerFactoryList.ToArray();
}
public override async Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig)
public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)));
await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)), outgoingEvent.Id, outgoingEvent.GetCorrelationId());
}
public override async Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
{
var outgoingEventArray = outgoingEvents.ToArray();
foreach (var outgoingEvent in outgoingEventArray)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)));
await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)), outgoingEvent.Id, outgoingEvent.GetCorrelationId());
}
}
public virtual async Task TriggerHandlersAsync(string messageId, Type eventType, object eventData)
public virtual async Task TriggerHandlersAsync(Type eventType, object eventData, string messageId = null, string correlationId = null)
{
if (await AddToInboxAsync(messageId, EventNameAttribute.GetNameOrDefault(eventType), eventType, eventData))
if (await AddToInboxAsync(messageId, EventNameAttribute.GetNameOrDefault(eventType), eventType, eventData, correlationId))
{
return;
}
await TriggerHandlersDirectAsync(eventType, eventData);
using (CorrelationIdProvider.Change(correlationId))
{
await TriggerHandlersDirectAsync(eventType, eventData);
}
}
public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig)
@ -190,7 +209,10 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>();
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId()))
{
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
}
if (exceptions.Any())
{
ThrowOriginalExceptions(eventType, exceptions);
@ -226,15 +248,16 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend
return EventTypes.GetOrDefault(eventName);
}
protected virtual async Task PublishToDaprAsync(Type eventType, object eventData)
protected virtual async Task PublishToDaprAsync(Type eventType, object eventData, Guid? messageId = null, string correlationId = null)
{
await PublishToDaprAsync(EventNameAttribute.GetNameOrDefault(eventType), eventData);
await PublishToDaprAsync(EventNameAttribute.GetNameOrDefault(eventType), eventData, messageId, correlationId);
}
protected virtual async Task PublishToDaprAsync(string eventName, object eventData)
protected virtual async Task PublishToDaprAsync(string eventName, object eventData, Guid? messageId = null, string correlationId = null)
{
var client = DaprClientFactory.Create();
await client.PublishEventAsync(pubsubName: DaprEventBusOptions.PubSubName, topicName: eventName, data: eventData);
var data = new AbpDaprEventData(DaprEventBusOptions.PubSubName, eventName, (messageId ?? GuidGenerator.Create()).ToString("N"), Serializer.SerializeToString(eventData), correlationId);
await client.PublishEventAsync(pubsubName: DaprEventBusOptions.PubSubName, topicName: eventName, data: data);
}
private static bool ShouldTriggerEventForHandler(Type targetEventType, Type handlerEventType)

82
framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs

@ -14,6 +14,7 @@ using Volo.Abp.Kafka;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Volo.Abp.EventBus.Kafka;
@ -42,7 +43,8 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
IGuidGenerator guidGenerator,
IClock clock,
IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus)
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider)
: base(
serviceScopeFactory,
currentTenant,
@ -51,7 +53,8 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
guidGenerator,
clock,
eventHandlerInvoker,
localEventBus)
localEventBus,
correlationIdProvider)
{
AbpKafkaEventBusOptions = abpKafkaEventBusOptions.Value;
MessageConsumerFactory = messageConsumerFactory;
@ -84,13 +87,17 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var messageId = message.GetMessageId();
var eventData = Serializer.Deserialize(message.Value, eventType);
var correlationId = message.GetCorrelationId();
if (await AddToInboxAsync(messageId, eventName, eventType, eventData))
if (await AddToInboxAsync(messageId, eventName, eventType, eventData, correlationId))
{
return;
}
await TriggerHandlersDirectAsync(eventType, eventData);
using (CorrelationIdProvider.Change(correlationId))
{
await TriggerHandlersDirectAsync(eventType, eventData);
}
}
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
@ -163,14 +170,21 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
protected async override Task PublishToEventBusAsync(Type eventType, object eventData)
{
var headers = new Headers
{
{ "messageId", System.Text.Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N")) }
};
if (CorrelationIdProvider.Get() != null)
{
headers.Add(EventBusConsts.CorrelationIdHeaderName, System.Text.Encoding.UTF8.GetBytes(CorrelationIdProvider.Get()!));
}
await PublishAsync(
AbpKafkaEventBusOptions.TopicName,
eventType,
eventData,
new Headers
{
{ "messageId", System.Text.Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N")) }
}
headers
);
}
@ -179,25 +193,34 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
unitOfWork.AddOrReplaceDistributedEvent(eventRecord);
}
public override async Task PublishFromOutboxAsync(
public async override Task PublishFromOutboxAsync(
OutgoingEventInfo outgoingEvent,
OutboxConfig outboxConfig)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
var headers = new Headers
{
{ "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) }
};
if (outgoingEvent.GetCorrelationId() != null)
{
headers.Add(EventBusConsts.CorrelationIdHeaderName, System.Text.Encoding.UTF8.GetBytes(outgoingEvent.GetCorrelationId()!));
}
await PublishAsync(
AbpKafkaEventBusOptions.TopicName,
outgoingEvent.EventName,
outgoingEvent.EventData,
new Headers
{
{ "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) }
}
headers
);
}
@ -214,12 +237,20 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
{ "messageId", System.Text.Encoding.UTF8.GetBytes(messageId)}
};
await TriggerDistributedEventSentAsync(new DistributedEventSent()
if (outgoingEvent.GetCorrelationId() != null)
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
headers.Add(EventBusConsts.CorrelationIdHeaderName, System.Text.Encoding.UTF8.GetBytes(outgoingEvent.GetCorrelationId()!));
}
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
producer.Produce(
AbpKafkaEventBusOptions.TopicName,
@ -244,7 +275,10 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>();
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId()))
{
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
}
if (exceptions.Any())
{
ThrowOriginalExceptions(eventType, exceptions);

12
framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/MessageExtensions.cs

@ -15,4 +15,16 @@ public static class MessageExtensions
return messageId;
}
public static string GetCorrelationId<TKey, TValue>(this Message<TKey, TValue> message)
{
string correlationId = null;
if (message.Headers.TryGetLastBytes(EventBusConsts.CorrelationIdHeaderName, out var correlationIdBytes))
{
correlationId = System.Text.Encoding.UTF8.GetString(correlationIdBytes);
}
return correlationId;
}
}

88
framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs

@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
@ -15,6 +16,7 @@ using Volo.Abp.MultiTenancy;
using Volo.Abp.RabbitMQ;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Volo.Abp.EventBus.RabbitMq;
@ -49,7 +51,8 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
IGuidGenerator guidGenerator,
IClock clock,
IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus)
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider)
: base(
serviceScopeFactory,
currentTenant,
@ -58,7 +61,8 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
guidGenerator,
clock,
eventHandlerInvoker,
localEventBus)
localEventBus,
correlationIdProvider)
{
ConnectionPool = connectionPool;
Serializer = serializer;
@ -103,12 +107,16 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
var eventData = Serializer.Deserialize(ea.Body.ToArray(), eventType);
if (await AddToInboxAsync(ea.BasicProperties.MessageId, eventName, eventType, eventData))
var correlationId = ea.BasicProperties.CorrelationId;
if (await AddToInboxAsync(ea.BasicProperties.MessageId, eventName, eventType, eventData, correlationId))
{
return;
}
await TriggerHandlersDirectAsync(eventType, eventData);
using (CorrelationIdProvider.Change(correlationId))
{
await TriggerHandlersDirectAsync(eventType, eventData);
}
}
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
@ -186,7 +194,7 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
protected async override Task PublishToEventBusAsync(Type eventType, object eventData)
{
await PublishAsync(eventType, eventData, null);
await PublishAsync(eventType, eventData, correlationId: CorrelationIdProvider.Get());
}
protected override void AddToUnitOfWork(IUnitOfWork unitOfWork, UnitOfWorkEventRecord eventRecord)
@ -194,18 +202,21 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
unitOfWork.AddOrReplaceDistributedEvent(eventRecord);
}
public override async Task PublishFromOutboxAsync(
public async override Task PublishFromOutboxAsync(
OutgoingEventInfo outgoingEvent,
OutboxConfig outboxConfig)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, null, eventId: outgoingEvent.Id);
await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, eventId: outgoingEvent.Id, correlationId: outgoingEvent.GetCorrelationId());
}
public async override Task PublishManyFromOutboxAsync(
@ -219,19 +230,22 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
foreach (var outgoingEvent in outgoingEventArray)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishAsync(
channel,
outgoingEvent.EventName,
outgoingEvent.EventData,
properties: null,
eventId: outgoingEvent.Id);
eventId: outgoingEvent.Id,
correlationId: outgoingEvent.GetCorrelationId());
}
channel.WaitForConfirmsOrDie();
@ -250,7 +264,10 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>();
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId()))
{
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
}
if (exceptions.Any())
{
ThrowOriginalExceptions(eventType, exceptions);
@ -262,28 +279,29 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
return Serializer.Serialize(eventData);
}
public Task PublishAsync(
public virtual Task PublishAsync(
Type eventType,
object eventData,
IBasicProperties properties,
Dictionary<string, object> headersArguments = null)
Dictionary<string, object> headersArguments = null,
Guid? eventId = null,
[CanBeNull] string correlationId = null)
{
var eventName = EventNameAttribute.GetNameOrDefault(eventType);
var body = Serializer.Serialize(eventData);
return PublishAsync(eventName, body, properties, headersArguments);
return PublishAsync( eventName, body, headersArguments, eventId, correlationId);
}
protected virtual Task PublishAsync(
string eventName,
byte[] body,
IBasicProperties properties,
Dictionary<string, object> headersArguments = null,
Guid? eventId = null)
Guid? eventId = null,
[CanBeNull] string correlationId = null)
{
using (var channel = ConnectionPool.Get(AbpRabbitMqEventBusOptions.ConnectionName).CreateModel())
{
return PublishAsync(channel, eventName, body, properties, headersArguments, eventId);
return PublishAsync(channel, eventName, body, headersArguments, eventId, correlationId);
}
}
@ -291,23 +309,25 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe
IModel channel,
string eventName,
byte[] body,
IBasicProperties properties,
Dictionary<string, object> headersArguments = null,
Guid? eventId = null)
Guid? eventId = null,
[CanBeNull] string correlationId = null)
{
EnsureExchangeExists(channel);
if (properties == null)
{
properties = channel.CreateBasicProperties();
properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent;
}
var properties = channel.CreateBasicProperties();
properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent;
if (properties.MessageId.IsNullOrEmpty())
{
properties.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N");
}
if (correlationId != null)
{
properties.CorrelationId = correlationId;
}
SetEventMessageHeaders(properties, headersArguments);
channel.BasicPublish(

62
framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs

@ -16,6 +16,7 @@ using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Volo.Abp.EventBus.Rebus;
@ -43,7 +44,8 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
IGuidGenerator guidGenerator,
IClock clock,
IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus) :
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider) :
base(
serviceScopeFactory,
currentTenant,
@ -52,7 +54,8 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
guidGenerator,
clock,
eventHandlerInvoker,
localEventBus)
localEventBus,
correlationIdProvider)
{
Rebus = rebus;
Serializer = serializer;
@ -144,18 +147,27 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
{
var messageId = MessageContext.Current.TransportMessage.GetMessageId();
var eventName = EventNameAttribute.GetNameOrDefault(eventType);
var correlationId = MessageContext.Current.Headers.GetOrDefault(EventBusConsts.CorrelationIdHeaderName);
if (await AddToInboxAsync(messageId, eventName, eventType, eventData))
if (await AddToInboxAsync(messageId, eventName, eventType, eventData, correlationId))
{
return;
}
await TriggerHandlersDirectAsync(eventType, eventData);
using (CorrelationIdProvider.Change(correlationId))
{
await TriggerHandlersDirectAsync(eventType, eventData);
}
}
protected async override Task PublishToEventBusAsync(Type eventType, object eventData)
{
await PublishAsync(eventType, eventData);
var headers = new Dictionary<string, string>();
if (CorrelationIdProvider.Get() != null)
{
headers.Add(EventBusConsts.CorrelationIdHeaderName, CorrelationIdProvider.Get());
}
await PublishAsync(eventType, eventData, headersArguments: headers);
}
protected virtual async Task PublishAsync(
@ -234,21 +246,29 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
return false;
}
public override async Task PublishFromOutboxAsync(
public async override Task PublishFromOutboxAsync(
OutgoingEventInfo outgoingEvent,
OutboxConfig outboxConfig)
{
var eventType = EventTypes.GetOrDefault(outgoingEvent.EventName);
var eventData = Serializer.Deserialize(outgoingEvent.EventData, eventType);
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent() {
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishAsync(eventType, eventData, eventId: outgoingEvent.Id);
var headers = new Dictionary<string, string>();
if (outgoingEvent.GetCorrelationId() != null)
{
headers.Add(EventBusConsts.CorrelationIdHeaderName, outgoingEvent.GetCorrelationId());
}
await PublishAsync(eventType, eventData, eventId: outgoingEvent.Id, headersArguments: headers);
}
public async override Task PublishManyFromOutboxAsync(IEnumerable<OutgoingEventInfo> outgoingEvents, OutboxConfig outboxConfig)
@ -259,12 +279,15 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
{
foreach (var outgoingEvent in outgoingEventArray)
{
await TriggerDistributedEventSentAsync(new DistributedEventSent()
using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId()))
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
await TriggerDistributedEventSentAsync(new DistributedEventSent()
{
Source = DistributedEventSource.Outbox,
EventName = outgoingEvent.EventName,
EventData = outgoingEvent.EventData
});
}
await PublishFromOutboxAsync(outgoingEvent, outboxConfig);
}
@ -285,7 +308,10 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen
var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType);
var exceptions = new List<Exception>();
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId()))
{
await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig);
}
if (exceptions.Any())
{
ThrowOriginalExceptions(eventType, exceptions);

55
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs

@ -2,12 +2,14 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Volo.Abp.EventBus.Distributed;
@ -18,6 +20,7 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
protected IClock Clock { get; }
protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; }
protected ILocalEventBus LocalEventBus { get; }
protected ICorrelationIdProvider CorrelationIdProvider { get; }
protected DistributedEventBusBase(
IServiceScopeFactory serviceScopeFactory,
@ -27,7 +30,8 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
IGuidGenerator guidGenerator,
IClock clock,
IEventHandlerInvoker eventHandlerInvoker,
ILocalEventBus localEventBus) : base(
ILocalEventBus localEventBus,
ICorrelationIdProvider correlationIdProvider) : base(
serviceScopeFactory,
currentTenant,
unitOfWorkManager,
@ -37,6 +41,7 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
Clock = clock;
AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value;
LocalEventBus = localEventBus;
CorrelationIdProvider = correlationIdProvider;
}
public IDisposable Subscribe<TEvent>(IDistributedEventHandler<TEvent> handler) where TEvent : class
@ -129,14 +134,14 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
EventData = eventData
});
await eventOutbox.EnqueueAsync(
new OutgoingEventInfo(
GuidGenerator.Create(),
eventName,
Serialize(eventData),
Clock.Now
)
var outgoingEventInfo = new OutgoingEventInfo(
GuidGenerator.Create(),
eventName,
Serialize(eventData),
Clock.Now
);
outgoingEventInfo.SetCorrelationId(CorrelationIdProvider.Get());
await eventOutbox.EnqueueAsync(outgoingEventInfo);
return true;
}
}
@ -153,7 +158,8 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
string messageId,
string eventName,
Type eventType,
object eventData)
object eventData,
[CanBeNull] string correlationId)
{
if (AbpDistributedEventBusOptions.Inboxes.Count <= 0)
{
@ -177,22 +183,25 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB
}
}
await TriggerDistributedEventReceivedAsync(new DistributedEventReceived
using (CorrelationIdProvider.Change(correlationId))
{
Source = DistributedEventSource.Direct,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
});
await eventInbox.EnqueueAsync(
new IncomingEventInfo(
GuidGenerator.Create(),
messageId,
eventName,
Serialize(eventData),
Clock.Now
)
await TriggerDistributedEventReceivedAsync(new DistributedEventReceived
{
Source = DistributedEventSource.Direct,
EventName = EventNameAttribute.GetNameOrDefault(eventType),
EventData = eventData
});
}
var incomingEventInfo = new IncomingEventInfo(
GuidGenerator.Create(),
messageId,
eventName,
Serialize(eventData),
Clock.Now
);
incomingEventInfo.SetCorrelationId(correlationId);
await eventInbox.EnqueueAsync(incomingEventInfo);
}
}
}

5
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs

@ -245,8 +245,9 @@ public class IdentityModelAuthenticationService : IIdentityModelAuthenticationSe
throw new AbpException(response.ErrorDescription);
}
Logger.LogInformation($"First copy your one-time code: {response.UserCode}");
Logger.LogInformation($"Open {response.VerificationUri} in your browser...");
Logger.LogInformation($"Open your browser, go to: \"{response.VerificationUri}\"");
Logger.LogInformation($"and enter the following one-time code:");
Logger.LogInformation(response.UserCode);
for (var i = 0; i < ((response.ExpiresIn ?? 300) / response.Interval + 1); i++)
{

9
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs

@ -48,13 +48,20 @@ public class IncomingEventRecord :
public IncomingEventInfo ToIncomingEventInfo()
{
return new IncomingEventInfo(
var info = new IncomingEventInfo(
Id,
MessageId,
EventName,
EventData,
CreationTime
);
foreach (var property in ExtraProperties)
{
info.SetProperty(property.Key, property.Value);
}
return info;
}
public void MarkAsProcessed(DateTime processedTime)

9
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs

@ -41,11 +41,18 @@ public class OutgoingEventRecord :
public OutgoingEventInfo ToOutgoingEventInfo()
{
return new OutgoingEventInfo(
var info = new OutgoingEventInfo(
Id,
EventName,
EventData,
CreationTime
);
foreach (var property in ExtraProperties)
{
info.SetProperty(property.Key, property.Value);
}
return info;
}
}

3
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using JetBrains.Annotations;
using Volo.Abp.Localization;
@ -74,7 +75,7 @@ public class EntityExtensionConfiguration
[NotNull]
public virtual ImmutableList<ExtensionPropertyConfiguration> GetProperties()
{
return Properties.Values.ToImmutableList();
return Properties.Values.OrderBy(t => t.UI.Order).ToImmutableList();
}
private static void NormalizeProperty(ExtensionPropertyConfiguration propertyInfo)

5
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiConfiguration.cs

@ -4,6 +4,8 @@ namespace Volo.Abp.ObjectExtending.Modularity;
public class ExtensionPropertyUiConfiguration
{
public const int DefaultOrder = 1000;
[NotNull]
public ExtensionPropertyUiTableConfiguration OnTable { get; }
@ -15,6 +17,8 @@ public class ExtensionPropertyUiConfiguration
[NotNull]
public ExtensionPropertyLookupConfiguration Lookup { get; set; }
public int Order { get; set; }
public ExtensionPropertyUiConfiguration()
{
@ -22,5 +26,6 @@ public class ExtensionPropertyUiConfiguration
OnCreateForm = new ExtensionPropertyUiFormConfiguration();
OnEditForm = new ExtensionPropertyUiFormConfiguration();
Lookup = new ExtensionPropertyLookupConfiguration();
Order = DefaultOrder;
}
}

1
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs

@ -174,6 +174,7 @@ public static class ModuleExtensionConfigurationHelper
property.DefaultValue = propertyConfig.DefaultValue;
property.DefaultValueFactory = propertyConfig.DefaultValueFactory;
property.Lookup = propertyConfig.UI.Lookup;
property.Order = propertyConfig.UI.Order;
foreach (var configuration in propertyConfig.Configuration)
{
property.Configuration[configuration.Key] = configuration.Value;

3
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs

@ -69,8 +69,7 @@ public class ObjectExtensionInfo
[NotNull]
public virtual ImmutableList<ObjectExtensionPropertyInfo> GetProperties()
{
return Properties.OrderBy(t => t.Key)
.Select(t => t.Value)
return Properties.OrderBy(t => t.Value.Order).Select(t => t.Value)
.ToImmutableList();
}

5
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs

@ -59,6 +59,11 @@ public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, I
[NotNull]
public ExtensionPropertyLookupConfiguration Lookup { get; set; }
/// <summary>
/// The Display order of the Property.
/// </summary>
public int Order { get; set; }
public ObjectExtensionPropertyInfo(
[NotNull] ObjectExtensionInfo objectExtension,

69
framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;
using Volo.Abp.Content;
namespace Microsoft.Extensions.DependencyInjection;
@ -61,20 +62,70 @@ public static class AbpSwaggerGenServiceCollectionExtensions
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
new OpenApiSecurityScheme
Reference = new OpenApiReference
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "oauth2"
}
},
Array.Empty<string>()
}
Type = ReferenceType.SecurityScheme,
Id = "oauth2"
}
},
Array.Empty<string>()
}
});
setupAction?.Invoke(options);
});
}
public static IServiceCollection AddAbpSwaggerGenWithOidc(
this IServiceCollection services,
[NotNull] string authority,
string[] scopes = null,
string[] flows = null,
string discoveryEndpoint = null,
Action<SwaggerGenOptions> setupAction = null)
{
var discoveryUrl = discoveryEndpoint != null ?
new Uri(discoveryEndpoint) :
new Uri($"{authority.TrimEnd('/')}/.well-known/openid-configuration");
flows ??= new [] { "authorization_code" };
services.Configure<SwaggerUIOptions>(swaggerUiOptions =>
{
swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedFlows"] = flows;
swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedScopes"] = scopes;
swaggerUiOptions.ConfigObject.AdditionalItems["oidcDiscoveryEndpoint"] = discoveryEndpoint;
});
return services
.AddAbpSwaggerGen()
.AddSwaggerGen(
options =>
{
options.AddSecurityDefinition("oidc", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OpenIdConnect,
OpenIdConnectUrl = discoveryUrl
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "oidc"
}
},
Array.Empty<string>()
}
});
setupAction?.Invoke(options);
});
}
}

39
framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js

@ -1,16 +1,20 @@
var abp = abp || {};
(function() {
(function () {
abp.SwaggerUIBundle = function(configObject) {
abp.SwaggerUIBundle = function (configObject) {
var excludeUrl = ["swagger.json", "connect/token"]
var firstRequest = true;
var oidcSupportedFlows = configObject.oidcSupportedFlows || [];
var oidcSupportedScopes = configObject.oidcSupportedScopes || [];
var oidcDiscoveryEndpoint = configObject.oidcDiscoveryEndpoint || [];
abp.appPath = configObject.baseUrl || abp.appPath;
var requestInterceptor = configObject.requestInterceptor;
var responseInterceptor = configObject.responseInterceptor;
configObject.requestInterceptor = async function(request) {
configObject.requestInterceptor = async function (request) {
if (request.url.includes(excludeUrl[1])) {
firstRequest = true;
@ -22,6 +26,10 @@ var abp = abp || {};
});
firstRequest = false;
}
// Intercept .well-known request when the discoveryEndpoint is provided
if (!firstRequest && oidcDiscoveryEndpoint.length !== 0 && request.url.includes(".well-known/openid-configuration")) {
request.url = oidcDiscoveryEndpoint;
}
var antiForgeryToken = abp.security.antiForgery.getToken();
if (antiForgeryToken) {
@ -38,6 +46,31 @@ var abp = abp || {};
return request;
};
configObject.responseInterceptor = async function (response) {
if (response.url.endsWith(".well-known/openid-configuration") && response.status === 200) {
var openIdConnectData = JSON.parse(response.text);
if (oidcDiscoveryEndpoint.length > 0) {
openIdConnectData.grant_types_supported = oidcSupportedFlows;
}
if (oidcSupportedFlows.length > 0) {
openIdConnectData.grant_types_supported = oidcSupportedFlows;
}
if (oidcSupportedScopes.length > 0) {
openIdConnectData.scopes_supported = oidcSupportedScopes;
}
response.text = JSON.stringify(openIdConnectData);
}
if (responseInterceptor) {
responseInterceptor(response);
}
return response;
};
return SwaggerUIBundle(configObject);
}
})();

17
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProviderController.cs

@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Tracing;
namespace Volo.Abp.AspNetCore.CorrelationIdProvider;
[Route("api/correlation")]
public class CorrelationIdProviderController : AbpController
{
[HttpGet]
[Route("get")]
public string Get()
{
return this.HttpContext.RequestServices.GetRequiredService<ICorrelationIdProvider>().Get();
}
}

48
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProvider_Tests.cs

@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.AspNetCore.Mvc;
using Xunit;
namespace Volo.Abp.AspNetCore.CorrelationIdProvider;
public class CorrelationIdProvider_Tests : AspNetCoreMvcTestBase
{
[Fact]
public async Task Test()
{
// Test AbpCorrelationIdMiddleware without X-Correlation-Id header
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/correlation/404"))
{
var response = await Client.SendAsync(requestMessage);
response.StatusCode.ShouldBe(HttpStatusCode.NotFound);
response.Headers.ShouldContain(x => x.Key == "X-Correlation-Id" && x.Value.First() != null);
}
var correlationId = Guid.NewGuid().ToString("N");
// Test AbpCorrelationIdMiddleware
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/correlation/404"))
{
requestMessage.Headers.Add("X-Correlation-Id", correlationId);
var response = await Client.SendAsync(requestMessage);
response.StatusCode.ShouldBe(HttpStatusCode.NotFound);
response.Headers.ShouldContain(x => x.Key == "X-Correlation-Id" && x.Value.First() == correlationId);
}
// Test AspNetCoreCorrelationIdProvider
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/correlation/get"))
{
requestMessage.Headers.Add("X-Correlation-Id", correlationId);
var response = await Client.SendAsync(requestMessage);
response.StatusCode.ShouldBe(HttpStatusCode.OK);
(await response.Content.ReadAsStringAsync()).ShouldBe(correlationId);
}
}
}

33
framework/test/Volo.Abp.Core.Tests/Volo/Abp/CorrelationIdProvider/CorrelationIdProvider_Tests.cs

@ -0,0 +1,33 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Modularity;
using Volo.Abp.Tracing;
using Xunit;
namespace Volo.Abp.CorrelationIdProvider;
public class CorrelationIdProvider_Tests
{
[Fact]
public async Task Test()
{
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>())
{
await application.InitializeAsync();
var correlationIdProvider = application.ServiceProvider.GetRequiredService<ICorrelationIdProvider>();
correlationIdProvider.Get().ShouldBeNull();
var correlationId = Guid.NewGuid().ToString("N");
using (correlationIdProvider.Change(correlationId))
{
correlationIdProvider.Get().ShouldBe(correlationId);
}
correlationIdProvider.Get().ShouldBeNull();
}
}
}

2
modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpmdl.json

@ -18,7 +18,7 @@
"BlobStoring.Database.Host.ConsoleApp.ConsoleApp": {
"path": "host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.ConsoleApp.abppkg.json",
"folder": "host/BlobStoring.Database.Host.ConsoleApp/src"
}i
},
"Volo.Abp.BlobStoring.Database.Domain": {
"path": "src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.abppkg.json",
"folder": "src"

1
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json

@ -10,6 +10,7 @@
"LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.",
"InvalidUsername": "Invalid username or password!",
"InvalidAuthenticatorCode": "Invalid authenticator code!",
"InvalidRecoveryCode": "Invalid recovery code!",
"TheTargetUserIsNotLinkedToYou": "The target user is not linked to you!"
}
}

3
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json

@ -10,6 +10,7 @@
"LoginIsNotAllowed": "Giriş yapmanıza izin verilmiyor! Hesabınız etkin değil veya e-postanızı/telefon numaranızı onaylamanız gerekiyor.",
"InvalidUsername": "Kullanıcı adı ya da şifre geçersiz!",
"InvalidAuthenticatorCode": "Geçersiz kimlik doğrulama kodu!",
"InvalidRecoveryCode": "Geçersiz kurtarma kodu!",
"TheTargetUserIsNotLinkedToYou": "Hedef kullanıcı sizinle bağlantılı değil!"
}
}
}

1
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json

@ -10,6 +10,7 @@
"LoginIsNotAllowed": "无法登录!你的账号未激活或者需要验证邮箱地址/手机号.",
"InvalidUsername": "用户名或密码错误!",
"InvalidAuthenticatorCode": "验证码无效!",
"InvalidRecoveryCode": "恢复代码无效!",
"TheTargetUserIsNotLinkedToYou": "目标用户未和你有关联!"
}
}

3
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json

@ -10,6 +10,7 @@
"LoginIsNotAllowed": "無法登入!你的賬號未激活或者需要驗證郵箱地址/手機號碼.",
"InvalidUsername": "用戶名或密碼錯誤!",
"InvalidAuthenticatorCode": "驗證碼無效!",
"InvalidRecoveryCode": "恢復碼無效!",
"TheTargetUserIsNotLinkedToYou": "目標用戶與您無關!"
}
}
}

14
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -178,6 +178,20 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
protected virtual async Task HandleTwoFactorLoginAsync(ResourceOwnerPasswordValidationContext context, IdentityUser user)
{
var recoveryCode = context.Request?.Raw?["RecoveryCode"];
if (!recoveryCode.IsNullOrWhiteSpace())
{
var result = await UserManager.RedeemTwoFactorRecoveryCodeAsync(user, recoveryCode);
if (result.Succeeded)
{
await SetSuccessResultAsync(context, user);
return;
}
Logger.LogInformation("Authentication failed for username: {username}, reason: InvalidRecoveryCode", context.UserName);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, Localizer["InvalidRecoveryCode"]);
}
var twoFactorProvider = context.Request?.Raw?["TwoFactorProvider"];
var twoFactorCode = context.Request?.Raw?["TwoFactorCode"];
if (!twoFactorProvider.IsNullOrWhiteSpace() && !twoFactorCode.IsNullOrWhiteSpace())

6
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo.Abp.OpenIddict.AspNetCore.csproj

@ -20,8 +20,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenIddict.Server.AspNetCore" Version="4.4.0" />
<PackageReference Include="OpenIddict.Validation.AspNetCore" Version="4.4.0" />
<PackageReference Include="OpenIddict.Validation.ServerIntegration" Version="4.4.0" />
<PackageReference Include="OpenIddict.Server.AspNetCore" Version="$(OpenIddictPackageVersion)" />
<PackageReference Include="OpenIddict.Validation.AspNetCore" Version="$(OpenIddictPackageVersion)" />
<PackageReference Include="OpenIddict.Validation.ServerIntegration" Version="$(OpenIddictPackageVersion)" />
</ItemGroup>
</Project>

20
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs

@ -175,8 +175,26 @@ public partial class TokenController
protected virtual async Task<IActionResult> HandleTwoFactorLoginAsync(OpenIddictRequest request, IdentityUser user)
{
var recoveryCode = request.GetParameter("RecoveryCode")?.ToString();
if (!recoveryCode.IsNullOrWhiteSpace())
{
var result = await UserManager.RedeemTwoFactorRecoveryCodeAsync(user, recoveryCode);
if (result.Succeeded)
{
return await SetSuccessResultAsync(request, user);
}
var properties = new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "Invalid recovery code!"
});
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
var twoFactorProvider = request.GetParameter("TwoFactorProvider")?.ToString();
var twoFactorCode = request.GetParameter("TwoFactorCode")?.ToString();;
var twoFactorCode = request.GetParameter("TwoFactorCode")?.ToString();
if (!twoFactorProvider.IsNullOrWhiteSpace() && !twoFactorCode.IsNullOrWhiteSpace())
{
var providers = await UserManager.GetValidTwoFactorProvidersAsync(user);

2
modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj

@ -14,7 +14,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenIddict.Abstractions" Version="4.4.0" />
<PackageReference Include="OpenIddict.Abstractions" Version="$(OpenIddictPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="$(MicrosoftPackageVersion)" />
</ItemGroup>

2
modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj

@ -17,7 +17,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenIddict.Core" Version="4.4.0" />
<PackageReference Include="OpenIddict.Core" Version="$(OpenIddictPackageVersion)" />
</ItemGroup>
</Project>

2
npm/lerna.json

@ -1,5 +1,5 @@
{
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"packages": [
"packs/*"
],

26
npm/ng-packs/package.json

@ -44,20 +44,20 @@
},
"private": true,
"devDependencies": {
"@abp/ng.account": "~7.3.0-rc.1",
"@abp/ng.account.core": "~7.3.0-rc.1",
"@abp/ng.core": "~7.3.0-rc.1",
"@abp/ng.feature-management": "~7.3.0-rc.1",
"@abp/ng.identity": "~7.3.0-rc.1",
"@abp/ng.oauth": "~7.3.0-rc.1",
"@abp/ng.permission-management": "~7.3.0-rc.1",
"@abp/ng.schematics": "~7.3.0-rc.1",
"@abp/ng.setting-management": "~7.3.0-rc.1",
"@abp/ng.tenant-management": "~7.3.0-rc.1",
"@abp/ng.theme.basic": "~7.3.0-rc.1",
"@abp/ng.account": "~7.3.0-rc.2",
"@abp/ng.account.core": "~7.3.0-rc.2",
"@abp/ng.core": "~7.3.0-rc.2",
"@abp/ng.feature-management": "~7.3.0-rc.2",
"@abp/ng.identity": "~7.3.0-rc.2",
"@abp/ng.oauth": "~7.3.0-rc.2",
"@abp/ng.permission-management": "~7.3.0-rc.2",
"@abp/ng.schematics": "~7.3.0-rc.2",
"@abp/ng.setting-management": "~7.3.0-rc.2",
"@abp/ng.tenant-management": "~7.3.0-rc.2",
"@abp/ng.theme.basic": "~7.3.0-rc.2",
"@abp/ng.theme.lepton-x": "^2.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/utils": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"@abp/utils": "~7.3.0-rc.2",
"@angular-devkit/build-angular": "16.0.1",
"@angular-devkit/core": "16.0.1",
"@angular-devkit/schematics": "16.0.1",

131
npm/ng-packs/packages/account-core/README.md

@ -1,3 +1,130 @@
# @abp/ng.account.core
## ℹ️ Description
Visit the [ABP documentation](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/account-core/package.json

@ -1,14 +1,14 @@
{
"name": "@abp/ng.account.core",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"peerDependencies": {
"@abp/ng.core": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.core": "~7.3.0-rc.2",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0"
},
@ -17,5 +17,19 @@
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

130
npm/ng-packs/packages/account/README.md

@ -1,3 +1,129 @@
<h1> @abp/ng.account </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/account/package.json

@ -1,17 +1,31 @@
{
"name": "@abp/ng.account",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.account.core": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.account.core": "~7.3.0-rc.2",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

1
npm/ng-packs/packages/account/src/public-api.ts

@ -5,3 +5,4 @@ export * from './lib/guards';
export * from './lib/models';
export * from './lib/services';
export * from './lib/tokens';
export * from './lib/utils';

131
npm/ng-packs/packages/components/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.components </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/components/package.json

@ -1,14 +1,14 @@
{
"name": "@abp/ng.components",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"peerDependencies": {
"@abp/ng.core": ">=7.3.0-rc.1",
"@abp/ng.theme.shared": ">=7.3.0-rc.1"
"@abp/ng.core": ">=7.3.0-rc.2",
"@abp/ng.theme.shared": ">=7.3.0-rc.2"
},
"dependencies": {
"chart.js": "^3.5.1",
@ -17,5 +17,19 @@
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/core/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.core </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

20
npm/ng-packs/packages/core/package.json

@ -1,13 +1,13 @@
{
"name": "@abp/ng.core",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/utils": "~7.3.0-rc.1",
"@abp/utils": "~7.3.0-rc.2",
"angular-oauth2-oidc": "^15.0.1",
"just-clone": "^6.1.1",
"just-compare": "^2.3.0",
@ -16,5 +16,19 @@
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

4
npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts

@ -5,7 +5,7 @@ import { Directive, EventEmitter, HostListener, Output } from '@angular/core';
selector: '[abpCapsLock]',
})
export class TrackCapsLockDirective {
@Output('abpCapsLock') capsLock = new EventEmitter<Boolean>();
@Output('abpCapsLock') capsLock = new EventEmitter<boolean>();
@HostListener('window:keydown', ['$event'])
onKeyDown(event: KeyboardEvent): void {
@ -17,7 +17,7 @@ export class TrackCapsLockDirective {
}
isCapsLockOpen(e): boolean {
var s = String.fromCharCode(e.which);
const s = String.fromCharCode(e.which);
if (
(s.toUpperCase() === s && s.toLowerCase() !== s && e.shiftKey) ||
(s.toUpperCase() !== s && s.toLowerCase() === s && e.shiftKey) ||

1
npm/ng-packs/packages/core/src/lib/services/index.ts

@ -19,3 +19,4 @@ export * from './session-state.service';
export * from './subscription.service';
export * from './track-by.service';
export * from './local-storage.service';
export * from './window.service';

20
npm/ng-packs/packages/core/src/lib/services/window.service.ts

@ -0,0 +1,20 @@
import { Injectable, inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({ providedIn: 'root' })
export class AbpWindowService {
protected readonly window = inject(DOCUMENT).defaultView;
protected readonly navigator = this.window.navigator;
copyToClipboard(text: string): Promise<void> {
return this.navigator.clipboard.writeText(text);
}
open(url?: string | URL, target?: string, features?: string): Window {
return this.window.open(url, target, features);
}
reloadPage(): void {
this.window.location.reload();
}
}

131
npm/ng-packs/packages/feature-management/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.feature-management </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

4
npm/ng-packs/packages/feature-management/package.json

@ -1,13 +1,13 @@
{
"name": "@abp/ng.feature-management",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {

2
npm/ng-packs/packages/generators/package.json

@ -1,6 +1,6 @@
{
"name": "@abp/nx.generators",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"generators": "./generators.json",
"type": "commonjs",

131
npm/ng-packs/packages/identity/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.identity </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

8
npm/ng-packs/packages/identity/package.json

@ -1,15 +1,15 @@
{
"name": "@abp/ng.identity",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.components": "~7.3.0-rc.1",
"@abp/ng.permission-management": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.components": "~7.3.0-rc.2",
"@abp/ng.permission-management": "~7.3.0-rc.2",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {

131
npm/ng-packs/packages/oauth/README.md

@ -1,7 +1,130 @@
# oauth
## ℹ️ Description
This library was generated with [Nx](https://nx.dev).
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
## Running unit tests
🔗Official Website: https://abp.io
Run `nx test oauth` to execute the unit tests.
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/oauth/package.json

@ -1,14 +1,14 @@
{
"name": "@abp/ng.oauth",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.core": "~7.3.0-rc.1",
"@abp/utils": "~7.3.0-rc.1",
"@abp/ng.core": "~7.3.0-rc.2",
"@abp/utils": "~7.3.0-rc.2",
"angular-oauth2-oidc": "^15.0.1",
"just-clone": "^6.1.1",
"just-compare": "^2.3.0",
@ -16,5 +16,19 @@
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/permission-management/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.permission-management </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

20
npm/ng-packs/packages/permission-management/package.json

@ -1,16 +1,30 @@
{
"name": "@abp/ng.permission-management",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/schematics/README.md

@ -1,3 +1,130 @@
# ABP Suite Schematics
## ℹ️ Description
TODO: Add usage and development information
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

23
npm/ng-packs/packages/schematics/package.json

@ -1,12 +1,7 @@
{
"name": "@abp/ng.schematics",
"version": "7.3.0-rc.1",
"description": "Schematics that works with ABP Backend",
"keywords": [
"schematics"
],
"version": "7.3.0-rc.2",
"author": "",
"license": "MIT",
"schematics": "./collection.json",
"dependencies": {
"@angular-devkit/core": "16.0.1",
@ -26,5 +21,19 @@
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/setting-management/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.setting-management </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/setting-management/package.json

@ -1,17 +1,31 @@
{
"name": "@abp/ng.setting-management",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.components": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.components": "~7.3.0-rc.2",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/tenant-management/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.tenant-management </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/tenant-management/package.json

@ -1,17 +1,31 @@
{
"name": "@abp/ng.tenant-management",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.feature-management": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.feature-management": "~7.3.0-rc.2",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/theme-basic/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.theme.basic </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

22
npm/ng-packs/packages/theme-basic/package.json

@ -1,17 +1,31 @@
{
"name": "@abp/ng.theme.basic",
"version": "7.3.0-rc.1",
"version": "7.3.0-rc.2",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.account.core": "~7.3.0-rc.1",
"@abp/ng.theme.shared": "~7.3.0-rc.1",
"@abp/ng.account.core": "~7.3.0-rc.2",
"@abp/ng.theme.shared": "~7.3.0-rc.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
},
"license": "LGPL-3.0",
"keywords": [
"aspnetcore",
"boilerplate",
"framework",
"web",
"best-practices",
"angular",
"maui",
"blazor",
"mvc",
"csharp",
"webapp"
]
}

131
npm/ng-packs/packages/theme-shared/README.md

@ -1,3 +1,130 @@
<h1> @abp/ng.theme.shared </h1>
## ℹ️ Description
[docs.abp.io](https://docs.abp.io)
ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files.
For more information, check out the below links:
🔗Official Website: https://abp.io
🔗Commercial Website: https://commercial.abp.io
🔗Commercial Demo: https://commercial.abp.io/demo
🔗GitHub Repository: https://github.com/abpframework/abp
🔗Official Theme: https://www.LeptonTheme.com
🔗Documentation: https://docs.abp.io
🔗Community: https://community.abp.io
🔗Blog: https://blog.abp.io
🔗Books: https://abp.io/books
🔗Twitter: https://twitter.com/abpframework
🔗Discord: https://community.abp.io/discord
🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp
🔗YouTube: https://www.youtube.com/@Volosoft
## 🤔 Why ABP Platform?
Why should you use the ABP.IO Platform instead of creating a new solution from scratch?
You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform)
## 🚀 Key Features of the ABP Framework
🟡 Modularity
🟡 Multi-Tenancy
🟡 Bootstrap Tag Helpers
🟡 Dynamic Forms
🟡 Authentication
🟡 Authorization
🟡 Distributed Event Bus
🟡 BLOB Storing
🟡 Text Templating
🟡 Tooling: ABP CLI
🟡 Cross-Cutting Concerns
🟡 Bundling & Minification
🟡 Virtual File System
🟡 Theming
🟡 Background Jobs
🟡 DDD Infrastructure
🟡 Auto REST APIs
🟡 Dynamic Client Proxies
🟡 Multiple Database Providers
🟡 Data filtering
🟡 Test Infrastructure
🟡 Audit Logging
🟡 Object to Object Mapping
🟡 Email & SMS Abstractions
🟡 Localization
🟡 Setting Management
🟡 Extension Methods
🟡 Aspect Oriented Programming
🟡 Dependency Injection
## 🧐 How It Works?
The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works)
### 📘 Supported Database Providers
🔵 Entity Framework Core
🔵 MongoDB
🔵 Dapper
### 🎴 Supported UI Frameworks
🔵 Angular
🔵 Razor Pages
🔵 Blazor Web Assembly
🔵 Blazor Server
🔵 MAUI with Blazor Hybrid
## 📫 Bug & Support
Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io).

14
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html

@ -25,10 +25,22 @@
<ng-container *ngFor="let prop of propList; let i = index; trackBy: trackByFn">
<ngx-datatable-column
[width]="columnWidths[i + 1] || 200"
[name]="prop.displayName | abpLocalization"
[name]="prop.displayName | abpLocalization "
[prop]="prop.name"
[sortable]="prop.sortable"
>
<ng-template ngx-datatable-header-template let-column="column" >
<span
*ngIf="prop.tooltip; else elseBlock"
[ngbTooltip]="prop.tooltip | abpLocalization"
container="body"
>
{{column.name}} <i class="fa fa-info-circle" aria-hidden="true"></i>
</span>
<ng-template #elseBlock>
{{column.name}}
</ng-template>
</ng-template>
<ng-template let-row="row" let-i="index" ngx-datatable-cell-template>
<ng-container *abpPermission="prop.permission; runChangeDetection: false">
<ng-container *ngIf="row['_' + prop.name]?.visible">

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

Loading…
Cancel
Save