diff --git a/Directory.Packages.props b/Directory.Packages.props index 0fe367c59e..8cd134d1d8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -37,6 +37,10 @@ + + + + @@ -111,11 +115,11 @@ - + - + diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 08e1687357..3fba33369c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -535,7 +535,7 @@ "WhenShouldIRenewMyLicenseExplanation3": "{0} for Business and Enterprise Licenses;", "WhenShouldIRenewMyLicenseExplanation4": "However, if you renew your license more than {0} days after the expiry date, the renewal price will be the same as the initial purchase price of the license, with no discounts applied to your renewal.", "DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal": "ABP Platform allows you to auto-renew your license. This is an optional free service. You can toggle this feature when you purchase a new license or later enable it from your organization management page. If you want to turn on or off the auto-renewal, visit the organization management page, go to the 'Payments Method' section and either check or uncheck the 'Automatic Renewal' checkbox. When you turn off the auto-renewal feature, it will be your responsibility to renew your license manually.", - "TrialPlanExplanation": "Yes, to start your free trial, please contact marketing@volosoft.com. We also offer a 30-day money-back guarantee for the Team license, with no questions asked! You can request a full refund within the first 30 days of purchasing the license. For Business and Enterprise licenses, we provide a 60% refund if requested within 30 days of purchase. This policy is due to the inclusion of the full source code for all modules and themes in the Business and Enterprise licenses.", + "TrialPlanExplanation": "Yes, to start your free trial, please contact sales@volosoft.com. We also offer a 30-day money-back guarantee for the Team license, with no questions asked! You can request a full refund within the first 30 days of purchasing the license. For Business and Enterprise licenses, we provide a 60% refund if requested within 30 days of purchase. This policy is due to the inclusion of the full source code for all modules and themes in the Business and Enterprise licenses.", "BlazoriseLicenseExplanation": "We have an agreement between Volosoft and Megabit, according to which the Blazorise license is bundled with the ABP Platform’s commercial licenses. Therefore, our paid users do not need to purchase an additional Blazorise license.", "HowToUpgradeExplanation1": "When you create a new application using the ABP startup templates, all the modules and themes are used as NuGet and NPM packages. This setup allows for easy upgrades to newer versions of the packages.", "HowToUpgradeExplanation2": "In addition to the standard NuGet/NPM upgrades, ABP CLI provides an update command that automatically finds and upgrades all ABP-related packages in your solution.", diff --git a/build/common.ps1 b/build/common.ps1 index 85f18edb21..51ab56d972 100644 --- a/build/common.ps1 +++ b/build/common.ps1 @@ -34,11 +34,13 @@ if ($full -eq "-f") "../templates/module/aspnet-core", "../templates/app/aspnet-core", "../templates/console", - "../templates/wpf", "../templates/app-nolayers/aspnet-core", "../abp_io/AbpIoLocalization", "../source-code" - ) + ) + if ($env:OS -eq "Windows_NT") { + $solutionPaths += "../templates/wpf" + } }else{ Write-host "" Write-host ":::::::::::::: !!! You are in development mode !!! ::::::::::::::" -ForegroundColor red -BackgroundColor yellow diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md new file mode 100644 index 0000000000..bb8bfdf4c7 --- /dev/null +++ b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md @@ -0,0 +1,147 @@ +# ABP Platform 9.1 RC Has Been Released + +We are happy to release [ABP](https://abp.io) version **9.1 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. + +Try this version and provide feedback for a more stable version of ABP v9.1! Thanks to you in advance. + +## Get Started with the 9.1 RC + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). + +By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: + +![studio-switch-to-preview.png](studio-switch-to-preview.png) + +## Migration Guide + +There are no breaking changes in this version that would affect your application. Only you might need to update some constant names due to the OpenIddict 6.0 upgrade, which is explained in the [OpenIddict 6.0 migration guide](https://abp.io/docs/9.1/release-info/migration-guides/openiddict5-to-6). + +## What's New with ABP v9.1? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Upgraded to Angular 19 +* Upgraded to OpenIddict 6.0 +* New Blazor WASM Bundling System +* Idle Session Warning +* Lazy Expandable Feature for Documentation + +### Upgraded to Angular 19 + +We've upgraded the Angular templates and packages to **Angular 19**. This upgrade brings the latest features and improvements from the Angular ecosystem to ABP-based applications, including better performance and development experience. + +### Upgraded to OpenIddict 6.0 + +OpenIddict 6.0 has been released and we've upgraded the OpenIddict packages to version 6.0 in ABP 9.1. This brings enhanced security features and improved authentication capabilities. The migration is straightforward and mainly involves updating some constant names: + +- `OpenIddictConstants.Permissions.Endpoints.Logout` is now `OpenIddictConstants.Permissions.Endpoints.EndSession` +- `OpenIddictConstants.Permissions.Endpoints.Device` is now `OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization` + +If you're using IdentityModel packages directly, you'll need to upgrade them to the latest stable version (8.3.0). This update ensures your applications stay current with the latest security standards and best practices. + +> Please refer to the [OpenIddict 6.0 migration guide](https://abp.io/docs/9.1/release-info/migration-guides/openiddict5-to-6) for more information. + +### New Blazor WASM Bundling System + +We've implemented a new bundling system for Blazor WebAssembly applications that eliminates the need to manually run the `abp bundle` command. This system automatically handles JavaScript and CSS file bundling at runtime, significantly improving both development experience and application loading performance. + +**Key improvements include:** + +- Automatic bundling of JavaScript and CSS files without manual intervention +- Dynamic file generation through the host application +- Better integration with the ABP module system +- Improved asset management through virtual file system + +The new system is particularly beneficial for modular applications, as it allows modules to contribute their assets automatically to the global bundles. This results in a more maintainable and efficient asset management system for Blazor WebAssembly applications. + +> Please refer to [this documentation](https://abp.io/docs/9.1/framework/ui/blazor/global-scripts-styles) for more information. + +### Idle Session Warning + +We've introduced a new idle session warning feature for the [Account (Pro) Module](https://abp.io/docs/latest/modules/account-pro) that helps manage user sessions more effectively. This security enhancement automatically monitors user activity and manages session timeouts in a user-friendly way. + +![idle-session-settings.png](idle-session-settings.png) + +The feature can be easily configured through the administration interface, where administrators can: + +- Enable/disable the idle session timeout +- Set custom timeout duration in minutes +- Configure when users should be signed out + +When a user becomes inactive for the configured duration, they'll receive a warning dialog: + +![session-expiration-warning.png](session-expiration-warning.png) + +**Key features and behaviors:** + +- Tracks real user activity (mouse movements, keyboard presses) across all tabs +- Works on a per-browser session basis - affects all tabs of the same session +- Maintains session if user is active in any tab of the application +- Provides a countdown timer before automatic sign-out +- Offers options to "Stay signed in" or "Sign out now" + +This feature significantly improves application security while maintaining a smooth user experience by preventing unexpected session expirations and data loss. + +### Lazy Expandable Feature for Documentation + +We've introduced a new lazy expandable feature to the documentation system that significantly improves navigation through large documentation sections. This enhancement addresses common challenges when dealing with extensive documentation hierarchies by introducing smart menu management. + +**Key benefits and features:** + +- **Cleaner Navigation:** The menu stays concise by hiding sub-items until they're needed, reducing visual clutter +- **Better Performance:** Reduces the initial load of the navigation tree by loading sub-items on demand +- **Improved Search Experience:** Makes filtering documentation items more efficient by showing only relevant top-level items +- **Context-Aware Expansion:** Automatically expands relevant sections when viewing specific documentation pages + +The feature works by marking certain documentation sections as "lazy expandable" in the navigation configuration. When users navigate to a document within a lazy expandable section, the system automatically expands the relevant menu items while keeping other sections collapsed. + +This improvement is particularly valuable for complex documentation areas like tutorials, solution templates, and extensive module documentation, where having all navigation items visible at once could be overwhelming. + +An example of lazy expandable feature from the [ABP's BookStore Tutorial](https://abp.io/docs/latest/tutorials/book-store/part-01): + +```json + { + "text": "Book Store Application", + "isLazyExpandable": true, + "path": "tutorials/book-store", + "items": [ + { + "text": "Overview", + "path": "tutorials/book-store", + "isIndex": true + }, + //other items... + ] + } +``` + +![lazy-expandable.png](lazy-expandable.png) + +### Others + +Some other highlights from this release: + +* Updated Iyzico NuGet packages to the latest version, which is used in the [ABP's Payment Module](https://abp.io/docs/latest/modules/payment#payment-module-pro). +* Removed optional _secondaryIds_ from path. See: [#21307](https://github.com/abpframework/abp/pull/21307) +* [CMS Kit Pro](https://abp.io/docs/latest/modules/cms-kit-pro): Added automatic deletion of comments when a blog post is deleted - comments are now automatically removed when their associated blog post is deleted. +* Avoiding global blocking in distributed event handlers (See [#21716](https://github.com/abpframework/abp/pull/21716)). + +## Community News + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Integrating ABP Modules in Your ASP.NET Core Web API Project. A Step-by-Step Guide](https://abp.io/community/articles/integrating-abp-modules-in-your-asp.net-core-web-api-project.-a-stepbystep-guide-jtbyosnr) by [Sajankumar Vijayan](https://abp.io/community/members/connect) +* [ABP Framework: Background Jobs vs Background Workers](https://abp.io/community/articles/abp-framework-background-jobs-vs-background-workers-when-to-use-which-t98pzjv6) — When to Use Which? by [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) +* [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming) +* [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/9.1/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.1 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/cover-image.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/cover-image.png new file mode 100644 index 0000000000..0575db3f27 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/cover-image.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/idle-session-settings.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/idle-session-settings.png new file mode 100644 index 0000000000..7cdb5df408 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/idle-session-settings.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/lazy-expandable.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/lazy-expandable.png new file mode 100644 index 0000000000..0936bcb024 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/lazy-expandable.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/session-expiration-warning.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/session-expiration-warning.png new file mode 100644 index 0000000000..1c4082874d Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/session-expiration-warning.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/studio-switch-to-preview.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/studio-switch-to-preview.png new file mode 100644 index 0000000000..32f6d01edb Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/studio-switch-to-preview.png differ diff --git a/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/POST.md b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/POST.md new file mode 100644 index 0000000000..611d8cb41b --- /dev/null +++ b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/POST.md @@ -0,0 +1,46 @@ +# ABP Studio Now Supports MacOS Intel 🚀 + +We are excited to announce that [ABP Studio, our cross-platform desktop application for ABP developers](https://abp.io/studio), now supports Intel-based Mac computers! + +This addition expands our platform compatibility, ensuring that developers using Intel-powered Macs can also benefit from the powerful features of ABP Studio. + +## What is ABP Studio? + +For those who aren't familiar, [ABP Studio](https://abp.io/studio) is a powerful desktop application that makes ABP development faster and easier. It offers: + +* Easy creation of new solutions (from simple applications to microservices) +* Visual architecture management for modular-monolith and microservice solutions +* Solution exploration tools for entities, services, and HTTP APIs +* Simplified running, debugging and monitoring of multi-application or microservice solutions +* Kubernetes cluster integration capabilities +* and more... + +## Extended Platform Support + +ABP Studio has been proudly supporting multiple platforms, and we're excited to add MacOS Intel to the our list of supported architectures. You can now use ABP Studio on: + +* Windows x64 +* Windows ARM +* MacOS Apple Silicon (M1/M2/M3) +* MacOS Intel **(New!)** + +## Why This Matters + +This update is particularly important for developers who are using Intel-based Mac computers. Previously, ABP Studio was only available for Apple Silicon Macs (for MacOS), but we understand that many developers are still using Intel-based Macs. With this release, we're ensuring that all Mac users can access our development tools, regardless of their processor architecture. + +## Getting Started + +Installing ABP Studio on your Intel-based Mac is straightforward: + +1. Go to [abp.io/studio](https://abp.io/studio) +2. Click on the download button and select "MacOS Intel" from the dropdown menu +3. Once downloaded, open the installer package +4. Follow the installation wizard to complete the setup + +![ABP Studio Download Page](abp-studio-macos-intel.png) + +## Conclusion + +As ABP team, we're always looking for ways to improve the developer experience. By supporting Intel-based Macs, we're ensuring that all Mac users can access our development tools, regardless of their processor architecture. + +Stay tuned for more updates and enhancements as we continue to optimize ABP Studio and please provide us with your invaluable feedback. Thanks in advance! diff --git a/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/abp-studio-macos-intel.png b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/abp-studio-macos-intel.png new file mode 100644 index 0000000000..f5d5ca6987 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/abp-studio-macos-intel.png differ diff --git a/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/cover-image.png b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/cover-image.png new file mode 100644 index 0000000000..80e0d0faf0 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/cover-image.png differ diff --git a/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/Load-User-Profile.jpg b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/Load-User-Profile.jpg new file mode 100644 index 0000000000..85f736050f Binary files /dev/null and b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/Load-User-Profile.jpg differ diff --git a/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/POST.md b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/POST.md new file mode 100644 index 0000000000..cea4bb82eb --- /dev/null +++ b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/POST.md @@ -0,0 +1,77 @@ +# Fixing OpenIddict Certificate Issues in IIS or Azure + +When deploying an ABP application with OpenIddict to IIS or Azure, you may encounter issues with loading PFX/PKCS12 certificates. This article explains how to properly configure certificate loading to ensure it works correctly in these environments. + +## The Problem + +When running under IIS or Azure, the application pool identity may not have sufficient permissions to access certificate private keys. This commonly results in errors such as: + +- `System.Security.Cryptography.CryptographicException: Access denied.` +- `WindowsCryptographicException: Access is denied.` +- `System.Security.Cryptography.CryptographicException: The system cannot find the file specified.` + +## The Solution + +### Using AddDevelopmentEncryptionAndSigningCertificate + +For development environments using `DevelopmentEncryptionAndSigningCertificate`, you must configure the application pool to load a user profile. + +> Note: We strongly recommend using `DevelopmentEncryptionAndSigningCertificate` only in development environments. For production, always create and use a separate certificate. + +![Application Pool Configuration](Load-User-Profile.jpg) + +### Using AddProductionEncryptionAndSigningCertificate + +The ABP OpenIddict module provides an `AddProductionEncryptionAndSigningCertificate` extension method. By default, the template project attempts to load an `openiddict.pfx` certificate in production environments. + +To ensure proper certificate loading in IIS or Azure, you need to specify appropriate `X509KeyStorageFlags` when calling this method: + +```csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (!hostingEnvironment.IsDevelopment()) + { + PreConfigure(options => + { + options.AddDevelopmentEncryptionAndSigningCertificate = false; + }); + + PreConfigure(serverBuilder => + { + var flag = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet; + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "YourCertificatePassword", flag); + }); + } +} +``` + +## Understanding X509KeyStorageFlags + +The configuration uses two important flags: + +* `X509KeyStorageFlags.MachineKeySet`: Specifies that the key belongs to the local computer key store, binding the key pair's lifecycle to the computer rather than a specific user. +* `X509KeyStorageFlags.EphemeralKeySet`: Indicates that the key will be stored only in memory and not persisted to disk or key store, enhancing security for runtime-only certificate requirements. + +Using these flags in combination helps prevent permission-related issues in IIS and Azure environments. + +## Troubleshooting Guide + +If you continue to experience issues, verify the following: + +* Confirm that the certificate password is correct +* Verify that the `openiddict.pfx` file exists in your deployment +* Ensure the certificate is valid - you can generate a new one using: + ```bash + dotnet dev-certs https -v -ep openiddict.pfx -p YourCertificatePassword + ``` +* Check the stdout logs for related errors (See [how to get stdout-log](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/deployment-iis?UI=Blazor&DB=EF&Tiered=No#how-to-get-stdout-log)) + +## References + +- [ABP OpenIddict Deployment](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/openiddict-deployment) +- [ABP IIS Deployment](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/deployment-iis) +- [ABP Azure Deployment](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment) +- [How to Generate a New Certificate](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-dev-certs#how-to-generate-a-new-certificate) +- [Load User Profile in IIS](https://learn.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities#load-user-profile-for-an-application-pool) diff --git a/docs/en/deployment/configuring-openIddict.md b/docs/en/deployment/configuring-openIddict.md index 03db14868b..eb62f3ec3f 100644 --- a/docs/en/deployment/configuring-openIddict.md +++ b/docs/en/deployment/configuring-openIddict.md @@ -50,4 +50,13 @@ You can use the `dotnet dev-certs https -v -ep openiddict.pfx -p 00000000-0000-0 > If you encounter a deployment error on IIS that says **File not found** even though the file exists, it is recommended to set the application pool’s advanced settings **Load User Profile** to **True** to resolve the issue. +> The `X509KeyStorageFlags.MachineKeySet` and `X509KeyStorageFlags.EphemeralKeySet` flags can be set in the `AddProductionEncryptionAndSigningCertificate` method for IIS deployments. For example: + +```csharp +serverBuilder.AddProductionEncryptionAndSigningCertificate( + "openiddict.pfx", + "your-password", + X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet); +``` + For more information, please refer to: https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html#registering-a-certificate-recommended-for-production-ready-scenarios diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index e7b7a4c3b7..8253b732df 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -2292,6 +2292,10 @@ { "text": "Tenant impersonation & User impersonation", "path": "modules/account/impersonation.md" + }, + { + "text": "Idle Session Timeout", + "path": "modules/account/idle-session-timeout.md" } ] }, diff --git a/docs/en/framework/architecture/best-practices/mongodb-integration.md b/docs/en/framework/architecture/best-practices/mongodb-integration.md index 1930984e2e..c39f6443a0 100644 --- a/docs/en/framework/architecture/best-practices/mongodb-integration.md +++ b/docs/en/framework/architecture/best-practices/mongodb-integration.md @@ -114,7 +114,7 @@ public async Task FindByNormalizedUserNameAsync( bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync()) + return await (await GetQueryableAsync()) .FirstOrDefaultAsync( u => u.NormalizedUserName == normalizedUserName, GetCancellationToken(cancellationToken) @@ -125,10 +125,10 @@ public async Task FindByNormalizedUserNameAsync( `GetCancellationToken` fallbacks to the `ICancellationTokenProvider.Token` to obtain the cancellation token if it is not provided by the caller code. * **Do** ignore the `includeDetails` parameters for the repository implementation since MongoDB loads the aggregate root as a whole (including sub collections) by default. -* **Do** use the `GetMongoQueryableAsync()` method to obtain an `IQueryable` to perform queries wherever possible. Because; - * `GetMongoQueryableAsync()` method automatically uses the `ApplyDataFilters` method to filter the data based on the current data filters (like soft delete and multi-tenancy). +* **Do** use the `GetQueryableAsync()` method to obtain an `IQueryable` to perform queries wherever possible. Because; + * `GetQueryableAsync()` method automatically uses the `ApplyDataFilters` method to filter the data based on the current data filters (like soft delete and multi-tenancy). * Using `IQueryable` makes the code as much as similar to the EF Core repository implementation and easy to write and read. -* **Do** implement data filtering if it is not possible to use the `GetMongoQueryable()` method. +* **Do** implement data filtering if it is not possible to use the `GetQueryableAsync()` method. ## Module Class diff --git a/docs/en/framework/architecture/domain-driven-design/repositories.md b/docs/en/framework/architecture/domain-driven-design/repositories.md index 9050e7d3c3..04848a59e8 100644 --- a/docs/en/framework/architecture/domain-driven-design/repositories.md +++ b/docs/en/framework/architecture/domain-driven-design/repositories.md @@ -393,19 +393,6 @@ This method is suggested; * If you are developing an application and you **don't plan to change** EF Core in the future, or you can **tolerate** it if you need to change it later. We believe that's reasonable if you are developing a final application. -#### MongoDB Case - -If you are using [MongoDB](../../data/mongodb), you need to add the [Volo.Abp.MongoDB](https://www.nuget.org/packages/Volo.Abp.MongoDB) NuGet package to your project. Even in this case, you can't directly use async LINQ extensions (like `ToListAsync`) because MongoDB doesn't provide async extension methods for `IQueryable`, but provides for `IMongoQueryable`. You need to cast the query to `IMongoQueryable` first to be able to use the async extension methods. - -**Example: Cast `IQueryable` to `IMongoQueryable` and use `ToListAsync()`** - -````csharp -var queryable = await _personRepository.GetQueryableAsync(); -var people = ((IMongoQueryable) queryable - .Where(p => p.Name.Contains(nameFilter))) - .ToListAsync(); -```` - ### Option-2: Use the IRepository Async Extension Methods ABP provides async extension methods for the repositories, just similar to async LINQ extension methods. diff --git a/docs/en/framework/infrastructure/settings.md b/docs/en/framework/infrastructure/settings.md index 519d2795c3..ef164e939b 100644 --- a/docs/en/framework/infrastructure/settings.md +++ b/docs/en/framework/infrastructure/settings.md @@ -160,6 +160,39 @@ Setting values should be configured under the `Settings` section as like in this > `IConfiguration` is an .NET Core service and it can read values not only from the `appsettings.json`, but also from the environment, user secrets... etc. See [Microsoft's documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) for more. +#### Encrypting Setting Values in the Application Configuration + +You have to use the `ISettingEncryptionService` to encrypt the setting values when the `IsEncrypted` property of a setting definition is set to `true`, which means that the setting value should be encrypted in the `appsettings.json`. + +Example of injecting the `ISettingEncryptionService` into a class and encrypting the plain text: + +````csharp +public class MyService +{ + private readonly ISettingEncryptionService _encryptionService; + + public MyService(ISettingEncryptionService encryptionService) + { + _encryptionService = encryptionService; + } + + public void EncryptValue(string plainText) + { + var ciphertext = _encryptionService.Encrypt(plainText); + } +} +```` + +Then, Replace `ENCRYPTED_VALUE_HERE` with the ciphertext generated by `ISettingEncryptionService.Encrypt` method. + +````json +{ + "Settings": { + "MySetting": "ENCRYPTED_VALUE_HERE" + } +} +```` + ### Custom Setting Value Providers If you need to extend the setting system, you can define a class derived from the `SettingValueProvider` class. Example: diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md index 970d35b851..043f811d49 100644 --- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md +++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md @@ -1,6 +1,6 @@ # ASP.NET Core MVC / Razor Pages UI: JavaScript Notify API -Notify API is used to show toast style, auto disappearing UI notifications to the end user. It is implemented by the [Toastr](https://github.com/CodeSeven/toastr) library by default. +Notify API is used to show toast style, auto disappearing UI notifications to the end user. ## Quick Example @@ -26,20 +26,23 @@ There are four types of pre-defined notifications; * `abp.notify.warn(...)` * `abp.notify.error(...)` -All of the methods above gets the following parameters; +All of the methods above accept the following parameters: * `message`: A message (`string`) to show to the user. * `title`: An optional title (`string`). -* `options`: Additional options to be passed to the underlying library, to the Toastr by default. - -## Toastr Configuration - -The notification API is implemented by the [Toastr](https://github.com/CodeSeven/toastr) library by default. You can see its own configuration options. - -**Example: Show toast messages on the top right of the page** - -````js -toastr.options.positionClass = 'toast-top-right'; -```` - -> ABP sets this option to `toast-bottom-right` by default. You can override it just as shown above. \ No newline at end of file +* `options`: Additional options to customize the notification. Available options: + * `life`: Display duration in milliseconds (default: `5000`) + * `sticky`: Keep toast visible until manually closed (default: `false`) + * `closable`: Show close button (default: `true`) + * `tapToDismiss`: Click anywhere on toast to dismiss (default: `false`) + * `containerKey`: Key for multiple container support (optional) + * `iconClass`: Custom icon class (optional) + * `position`: Position configuration (optional) + * `top`: Distance from top (default: `'auto'`) + * `right`: Distance from right (default: `'30px'`) + * `bottom`: Distance from bottom (default: `'30px'`) + * `left`: Distance from left (default: `'auto'`) + +## Global Configuration + +`AbpToastService.setDefaultOptions` method can be used to set default options for all notifications. This method should be called before any notification is shown. diff --git a/docs/en/guides/microservice-mongodb.md b/docs/en/guides/microservice-mongodb.md index c9b63ecf4e..087668ba7a 100644 --- a/docs/en/guides/microservice-mongodb.md +++ b/docs/en/guides/microservice-mongodb.md @@ -97,9 +97,9 @@ Here we use `BookStore.ProductService` project as an example: int skipCount = 0, CancellationToken cancellationToken = default) { - var query = ApplyFilter(await GetMongoQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); + var query = ApplyFilter(await GetQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); query = query.OrderBy(string.IsNullOrWhiteSpace(sorting) ? ProductConsts.GetDefaultSorting(false) : sorting); - return await query.As>().PageBy>(skipCount, maxResultCount).ToListAsync(cancellationToken); + return await query.PageBy(skipCount, maxResultCount).ToListAsync(cancellationToken); } public async Task GetCountAsync( @@ -109,8 +109,8 @@ Here we use `BookStore.ProductService` project as an example: float? priceMax = null, CancellationToken cancellationToken = default) { - var query = ApplyFilter(await GetMongoQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); - return await query.As>().LongCountAsync(GetCancellationToken(cancellationToken)); + var query = ApplyFilter(await GetQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); } protected virtual IQueryable ApplyFilter( diff --git a/docs/en/images/js-notify-success.png b/docs/en/images/js-notify-success.png index d5300f3468..1068bf8621 100644 Binary files a/docs/en/images/js-notify-success.png and b/docs/en/images/js-notify-success.png differ diff --git a/docs/en/modules/account-pro.md b/docs/en/modules/account-pro.md index 0dd960e97e..490abe4bba 100644 --- a/docs/en/modules/account-pro.md +++ b/docs/en/modules/account-pro.md @@ -358,4 +358,4 @@ This module doesn't define any additional distributed event. See the [standard d * [Impersonation](./account/impersonation.md) * [Linked Accounts](./account/linkedaccounts.md) * [Session Management](./account/session-management.md) -* [Idle Session Timeout](./account/idle-session-timeout.md)] +* [Idle Session Timeout](./account/idle-session-timeout.md) diff --git a/docs/en/release-info/migration-guides/MongoDB-Driver-2-to-3.md b/docs/en/release-info/migration-guides/MongoDB-Driver-2-to-3.md new file mode 100644 index 0000000000..79c0d70573 --- /dev/null +++ b/docs/en/release-info/migration-guides/MongoDB-Driver-2-to-3.md @@ -0,0 +1,59 @@ +# Migrating from MongoDB Driver 2 to 3 + +## Introduction + +The release of MongoDB Driver 3 includes numerous user-requested fixes and improvements that were deferred in previous versions due to backward compatibility concerns. It also features internal improvements to reduce technical debt and enhance maintainability. One major update is the removal of a significant portion of the public API (primarily from `MongoDB.Driver.Core`), which was not intended for public use. The removed APIs were marked as deprecated in version 2.30.0. + +Please refer to the [upgrade guide](https://www.mongodb.com/docs/drivers/csharp/current/upgrade/v3/) for a complete list of breaking changes and upgrade guidelines. + +## Repository Changes + +Some method signatures in the `MongoDbRepository` class have been updated because the `IMongoQueryable` has been removed. The specific changes are as follows: + +- The new `GetQueryableAsync` method has been added to return `IQueryable`. +- The `GetMongoQueryable` and `GetMongoQueryableAsync` methods return `IQueryable` instead of `IMongoQueryable`, +- The `GetMongoQueryable` and `GetMongoQueryableAsync` methods are marked as obsolete, You should use the new `GetQueryableAsync` method instead. + +Please update your application by searching for and replacing these method calls. + +> The return value of the `GetQueryableAsync` method is `IQueryable`, which can be used directly to perform queries, similar to EF Core. Remove all instances of `IMongoQueryable` in your project and replace them with `IQueryable`. + +**Previous code example:** + +```csharp +var myEntity = await (await GetMongoQueryableAsync()).As>().FirstOrDefaultAsync(x => x.Id == id); +``` + +**Updated code example:** + +```csharp +var myEntity = await GetQueryableAsync().FirstOrDefaultAsync(x => x.Id == id); +``` + +## Unit Test Changes + +Previously, we used the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library for unit testing. However, it does not support the latest version of [MongoDB.Driver 3.x](https://github.com/mongodb/mongo-go-driver). You should replace it with [MongoSandbox](https://github.com/wassim-k/MongoSandbox). + +In your unit test project files, replace the following: + +```xml + + + + +``` + +With: + +```xml + + + + +``` + +In your unit test classes, replace `using EphemeralMongo` with `using MongoSandbox`. + +## Official Upgrade Guide + +We recommend reviewing the [upgrade guide](https://www.mongodb.com/docs/drivers/csharp/current/upgrade/v3/) for MongoDB Driver 3 to ensure a smooth migration process. diff --git a/docs/en/release-info/migration-guides/abp-9-1.md b/docs/en/release-info/migration-guides/abp-9-1.md new file mode 100644 index 0000000000..0e80da824a --- /dev/null +++ b/docs/en/release-info/migration-guides/abp-9-1.md @@ -0,0 +1,7 @@ +# ABP Version 9.1 Migration Guide + +This document is a guide for upgrading ABP v9.0 solutions to ABP v9.1. There are no breaking changes in this version that would affect your application. + +Only you might need to update some constant names due to the OpenIddict 6.0 upgrade, which is explained in the following migration guide: + +- [OpenIddict 5.x to 6.x Migration Guide](./openiddict5-to-6.md) \ No newline at end of file diff --git a/docs/en/release-info/migration-guides/index.md b/docs/en/release-info/migration-guides/index.md index 27c6752338..821fbf5469 100644 --- a/docs/en/release-info/migration-guides/index.md +++ b/docs/en/release-info/migration-guides/index.md @@ -2,6 +2,7 @@ The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../upgrading.md). +- [9.0 to 9.1](abp-9-1.md) - [8.x to 9.0](abp-9-0.md) - [8.x to 8.3](abp-8-3.md) - [8.1 to 8.2](abp-8-2.md) diff --git a/docs/en/release-info/release-notes.md b/docs/en/release-info/release-notes.md index b86da2c079..f89e2383d7 100644 --- a/docs/en/release-info/release-notes.md +++ b/docs/en/release-info/release-notes.md @@ -4,6 +4,16 @@ This document contains **brief release notes** for each release. Release notes o > If you want to read the release notes for each ABP Studio release, check it out from [here](../studio/release-notes.md). +## 9.1 (2025-01-16) + +This is currently a RC (release-candidate) and you can see the detailed **[blog post / announcement](https://abp.io/blog/abp-9-1-release-candidate)** for the v9.1 release. + +* Upgraded to Angular 19 +* Upgraded to OpenIddict 6.0 +* New Blazor WASM Bundling System +* Idle Session Warning +* Lazy Expandable Feature for Documentation System + ## 9.0 (2024-11-19) See the detailed **[blog post / announcement](https://abp.io/blog/abp-9-0-stable-release-with-dotnet-9-0)** for the v9.0 release. diff --git a/docs/en/release-info/road-map.md b/docs/en/release-info/road-map.md index cc9caca124..7a5a400bf4 100644 --- a/docs/en/release-info/road-map.md +++ b/docs/en/release-info/road-map.md @@ -4,15 +4,13 @@ This document provides a road map, release schedule, and planned features for th ## Next Versions -### v9.1 +### v9.2 -The next version will be 9.1 and planned to release the stable 9.1 version in January 2025. We will be mostly working on the following topics: +The next version will be 9.2 and planned to release the stable 9.2 version in June 2025. We will be mostly working on the following topics: * Framework - * Lazy expandable feature for documentation - * Unify the bundling system of Blazor and MVC - * SSR support for the Angular UI * Upgrading 3rd-party dependencies + * Enhancements in the core points * ABP Suite * Define navigation properties without target string property dependency @@ -32,12 +30,12 @@ The next version will be 9.1 and planned to release the stable 9.1 version in Ja * Modular Monolith Application Startup Template * Application modules - * Account module: Support mixed social/local login scenarios - * Idle session warning + * Account module: Support mixed social/local login scenarios & enforcing email verification in wide aspect * UI/UX improvements on existing application modules -* New tutorials +* Updating existing tutorials & documents (with other UI & DB options) * Microservice development + * Modular monolith development ## Backlog Items @@ -64,7 +62,6 @@ ABP Platform provides many (free and commercial) [pre-built application modules] * LeptonX theme: New layouts, styles and components * CMS Kit module: Meta information for SEO, media gallery, RSS feed, content versioning, social media streams -* Identity module: Idle session warning * Payment module: Invoice system * New module: User notification * New module: Dynamic dashboard @@ -108,7 +105,6 @@ Here, are some of the important planned features for the next ABP Suite versions * Allow to create pages instead of modals for CRUD page generation * View-only (detail view) modal/page for an entity * Export child/detail entity records as a part of export operation for a main (master) entity -* Allow to accept attachments (files) for an entity * Allow to add custom entity actions for an entity * Allow to inherit from an existing entity class * Custom form layouts on CRUD page generation diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md index 8555e19d18..94ec619a34 100644 --- a/docs/en/studio/release-notes.md +++ b/docs/en/studio/release-notes.md @@ -2,6 +2,20 @@ This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version. +## 0.9.22 (2025-01-22) + +* Allowed to display multiple installation notes. +* Showed **Inner Exceptions** in the Solution Runner side-panel +* Hidden logs when no selected application is present. +* Added full docker compose to template. +* Zipped microservice module template for better structuring the solution. +* Upgraded templates to version `9.0.4`. + +## 0.9.21 (2025-01-09) + +* Showed a db test connection message while testing the database connection. +* Fixed books sample's application service. + ## 0.9.20 (2025-01-08) * Upgraded templates to version `9.0.3`. diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md index 731e38a128..fe39fb7c67 100644 --- a/docs/en/studio/version-mapping.md +++ b/docs/en/studio/version-mapping.md @@ -4,7 +4,8 @@ This document provides a general overview of the relationship between various ve | **ABP Studio Version** | **ABP Version of Startup Template** | |------------------------|---------------------------| -| 0.9.20 | 9.0.3 | +| 0.9.22 | 9.0.4 | +| 0.9.20 - 0.9.21 | 9.0.3 | | 0.9.17 to 0.9.19 | 9.0.2 | | 0.9.15 - 0.9.16 | 9.0.1 | | 0.9.9 to 0.9.14 | 9.0.0 | diff --git a/docs/en/tutorials/book-store/part-07.md b/docs/en/tutorials/book-store/part-07.md index 0708ecfcb9..92108c4a35 100644 --- a/docs/en/tutorials/book-store/part-07.md +++ b/docs/en/tutorials/book-store/part-07.md @@ -180,7 +180,7 @@ public class MongoDbAuthorRepository public async Task FindByNameAsync(string name) { - var queryable = await GetMongoQueryableAsync(); + var queryable = await GetQueryableAsync(); return await queryable.FirstOrDefaultAsync(author => author.Name == name); } @@ -190,14 +190,13 @@ public class MongoDbAuthorRepository string sorting, string filter = null) { - var queryable = await GetMongoQueryableAsync(); + var queryable = await GetQueryableAsync(); return await queryable - .WhereIf>( + .WhereIf>( !filter.IsNullOrWhiteSpace(), author => author.Name.Contains(filter) ) .OrderBy(sorting) - .As>() .Skip(skipCount) .Take(maxResultCount) .ToListAsync(); diff --git a/docs/en/tutorials/modular-crm/index.md b/docs/en/tutorials/modular-crm/index.md index e4bf64fbd7..723425a230 100644 --- a/docs/en/tutorials/modular-crm/index.md +++ b/docs/en/tutorials/modular-crm/index.md @@ -29,8 +29,8 @@ This tutorial is organized as the following parts: ## Download the Source Code -You can download the completed sample solution [here](https://github.com/abpframework/abp-samples/tree/master/ModularCRM). +You can download the completed sample solution [here](https://github.com/abpframework/abp-samples/tree/master/ModularCrm). ## See Also -* [Book Store: Web Application Development Tutorial](../book-store/index.md) \ No newline at end of file +* [Book Store: Web Application Development Tutorial](../book-store/index.md) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrScriptBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrScriptBundleContributor.cs deleted file mode 100644 index 226b076b7a..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrScriptBundleContributor.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using Volo.Abp.AspNetCore.Mvc.UI.Bundling; -using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; -using Volo.Abp.Modularity; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; - -[DependsOn(typeof(JQueryScriptContributor))] -public class ToastrScriptBundleContributor : BundleContributor -{ - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files.AddIfNotContains("/libs/toastr/toastr.min.js"); - } -} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrStyleBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrStyleBundleContributor.cs deleted file mode 100644 index d00f9e3768..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrStyleBundleContributor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using Volo.Abp.AspNetCore.Mvc.UI.Bundling; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; - -public class ToastrStyleBundleContributor : BundleContributor -{ - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files.AddIfNotContains("/libs/toastr/toastr.min.css"); - } -} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs index 5d8c15ba40..4bb1d80fef 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs @@ -12,7 +12,6 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago; -using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; @@ -26,7 +25,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; typeof(Select2ScriptContributor), typeof(DatatablesNetBs5ScriptContributor), typeof(Sweetalert2ScriptContributor), - typeof(ToastrScriptBundleContributor), typeof(MalihuCustomScrollbarPluginScriptBundleContributor), typeof(LuxonScriptContributor), typeof(TimeagoScriptContributor), @@ -48,7 +46,7 @@ public class SharedThemeGlobalScriptContributor : BundleContributor "/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/authentication-state/authentication-state-listener.js" }); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs index f959d73f05..4f436a02b0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs @@ -7,7 +7,6 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs5; using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; -using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; @@ -16,7 +15,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; typeof(CoreStyleContributor), typeof(BootstrapStyleContributor), typeof(FontAwesomeStyleContributor), - typeof(ToastrStyleBundleContributor), typeof(Select2StyleContributor), typeof(MalihuCustomScrollbarPluginStyleBundleContributor), typeof(DatatablesNetBs5StyleContributor), @@ -30,7 +28,8 @@ public class SharedThemeGlobalStyleContributor : BundleContributor context.Files.AddRange(new BundleFile[] { "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.css", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-styles.css" + "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-styles.css", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css", }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css new file mode 100644 index 0000000000..b6edbb0d6f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css @@ -0,0 +1,139 @@ +.abp-toast-container { + position: fixed; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-end; + min-width: 350px; + min-height: 80px; + z-index: 1900; + right: 30px; + bottom: 30px; +} + +.abp-toast { + display: grid; + grid-template-columns: 35px 1fr; + gap: 5px; + margin: 5px 0; + padding: 10px; + width: 350px; + user-select: none; + z-index: 9999; + color: #fff; + border-radius: 8px; + font-size: 16px; + box-shadow: 0 0 20px 0 rgba(76, 87, 125, 0.02); + animation: toastIn 0.3s ease-in-out; +} + +.abp-toast-success { + border: 2px solid #4fbf67; + background-color: #4fbf67; +} + +.abp-toast-error { + border: 2px solid #c00d49; + background-color: #c00d49; +} + +.abp-toast-info { + border: 2px solid #438aa7; + background-color: #438aa7; +} + +.abp-toast-warning { + border: 2px solid #ff9f38; + background-color: #ff9f38; +} + +.abp-toast-icon { + display: flex; + align-items: center; + justify-content: center; +} + +.abp-toast-icon .icon { + font-size: 30px; +} + +.abp-toast-content { + position: relative; + display: flex; + align-self: center; + flex-direction: column; + word-break: break-word; + padding-bottom: 2px; +} + +.abp-toast-close-button { + position: absolute; + top: 0; + right: 0; + display: flex; + align-items: center; + justify-content: center; + margin: 0; + padding: 0px 5px 0 0; + width: 25px; + height: 100%; + border: none; + border-radius: 50%; + background: transparent; + color: inherit; + cursor: pointer; +} + +.abp-toast-close-button:focus { + outline: none; +} + +.abp-toast-title { + margin: 0; + padding: 0; + font-size: 1rem; + font-weight: 600; +} + +.abp-toast-message { + margin: 0; + padding: 0; + max-width: 240px; +} + +@keyframes toastIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes toastOut { + from { + transform: translateX(0); + opacity: 1; + } + to { + transform: translateX(100%); + opacity: 0; + } +} + +.toast-removing { + animation: toastOut 0.3s ease-in-out forwards; +} + +@media only screen and (max-width: 768px) { + .abp-toast-container { + min-width: 100%; + right: 0; + } + + .abp-toast { + width: 95%; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js new file mode 100644 index 0000000000..a23d844ce6 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js @@ -0,0 +1,207 @@ +function AbpToastService(globalOptions) { + // Static default configuration for all instances + if (!AbpToastService.defaultOptions) { + AbpToastService.defaultOptions = { + closable: true, + sticky: false, + life: 5000, + tapToDismiss: false, + containerKey: undefined, + iconClass: undefined, + position: { + top: 'auto', + right: '30px', + bottom: '30px', + left: 'auto' + } + }; + } + + // Find existing container or create new one + const containerId = globalOptions?.containerKey ? + `toast-container-${globalOptions.containerKey}` : + 'toast-container'; + + this.container = document.getElementById(containerId); + if (!this.container) { + this.container = document.createElement('div'); + this.container.id = containerId; + this.container.className = 'abp-toast-container'; + document.body.appendChild(this.container); + } + + this.toasts = []; + this.lastId = 0; + + // Merge user provided global options with defaults + this.globalOptions = this.extend({}, AbpToastService.defaultOptions, globalOptions); + + this.updateContainerPosition(); +} + +// Deep merge objects +AbpToastService.prototype.extend = function(target, ...sources) { + sources.forEach(source => { + for (const key in source) { + if (source[key] && typeof source[key] === 'object') { + target[key] = this.extend(target[key] || {}, source[key]); + } else { + target[key] = source[key]; + } + } + }); + return target; +}; + +// Update toast container position based on global options +AbpToastService.prototype.updateContainerPosition = function() { + const { position } = this.globalOptions; + Object.assign(this.container.style, position); +}; + +// Update global options +AbpToastService.prototype.setGlobalOptions = function(options) { + this.globalOptions = this.extend({}, this.globalOptions, options); + this.updateContainerPosition(); +}; + +// Get icon class based on severity +AbpToastService.prototype.getIconClass = function(severity, options) { + // Use custom icon class if provided + if (options.iconClass) { + return options.iconClass; + } + + const icons = { + success: 'fa fa-check', + info: 'fa fa-info-circle', + warning: 'fa fa-exclamation-triangle', + error: 'fa fa-exclamation-circle' + }; + return icons[severity] || 'fa fa-exclamation-triangle'; +}; + +// Create toast DOM element +AbpToastService.prototype.createToastElement = function(message, title, severity, options) { + const toast = document.createElement('div'); + toast.className = `abp-toast abp-toast-${severity}`; + + const closeButton = options.closable !== false ? + `` : ''; + + const titleHtml = title ? `
${title}
` : ''; + + toast.innerHTML = ` +
+ +
+
+ ${closeButton} + ${titleHtml} +

${message}

+
`; + + // Add event listeners + const closeButtonElement = toast.querySelector('.abp-toast-close-button'); + if (closeButtonElement) { + closeButtonElement.addEventListener('click', () => this.remove(toast)); + } + + if (options.tapToDismiss) { + toast.addEventListener('click', () => this.remove(toast)); + } + + return toast; +}; + +// Show a toast with given options +AbpToastService.prototype.show = function(message, title, severity = 'neutral', options = {}) { + const mergedOptions = this.extend({}, this.globalOptions, options); + const id = ++this.lastId; + const toast = this.createToastElement(message, title, severity, mergedOptions); + + // Set data attributes for non-object options + Object.entries(mergedOptions) + .filter(([_, value]) => typeof value !== 'object') + .forEach(([key, value]) => toast.dataset[key] = value); + + toast.dataset.id = id; + this.container.appendChild(toast); + this.toasts.push(toast); + + // Auto remove if not sticky + if (!mergedOptions.sticky) { + setTimeout(() => this.remove(toast), mergedOptions.life); + } + + return id; +}; + +// Remove a toast with animation +AbpToastService.prototype.remove = function(toastElement) { + toastElement.classList.add('toast-removing'); + setTimeout(() => { + if (toastElement.parentNode === this.container) { + this.container.removeChild(toastElement); + } + this.toasts = this.toasts.filter(t => t !== toastElement); + }, 300); // Match animation duration +}; + +// Convenience methods for different severities +AbpToastService.prototype.success = function(message, title, options) { + return this.show(message, title, 'success', options); +}; + +AbpToastService.prototype.error = function(message, title, options) { + return this.show(message, title, 'error', options); +}; + +AbpToastService.prototype.info = function(message, title, options) { + return this.show(message, title, 'info', options); +}; + +AbpToastService.prototype.warning = function(message, title, options) { + return this.show(message, title, 'warning', options); +}; + +// Clear all toasts +AbpToastService.prototype.clear = function(containerKey) { + if (containerKey) { + this.toasts = this.toasts.filter(toast => { + const shouldRemove = toast.dataset.containerKey === containerKey; + if (shouldRemove) { + this.remove(toast); + } + return !shouldRemove; + }); + } else { + this.toasts.forEach(toast => this.remove(toast)); + } +}; + +// Static method to set default options for all instances +AbpToastService.setDefaultOptions = function(options) { + AbpToastService.defaultOptions = this.prototype.extend({}, AbpToastService.defaultOptions, options); +}; + +var abp = abp || {}; +(function () { + abp.notify.success = function (message, title, options) { + new AbpToastService().success(message, title, options); + }; + + abp.notify.info = function (message, title, options) { + new AbpToastService().info(message, title, options); + }; + + abp.notify.warn = function (message, title, options) { + new AbpToastService().warning(message, title, options); + }; + + abp.notify.error = function (message, title, options) { + new AbpToastService().error(message, title, options); + }; +})(); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js deleted file mode 100644 index 37a7c40166..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js +++ /dev/null @@ -1,34 +0,0 @@ -var abp = abp || {}; -(function () { - - if (!toastr) { - return; - } - - /* DEFAULTS *************************************************/ - - toastr.options.positionClass = 'toast-bottom-right'; - - /* NOTIFICATION *********************************************/ - - var showNotification = function (type, message, title, options) { - toastr[type](message, title, options); - }; - - abp.notify.success = function (message, title, options) { - showNotification('success', message, title, options); - }; - - abp.notify.info = function (message, title, options) { - showNotification('info', message, title, options); - }; - - abp.notify.warn = function (message, title, options) { - showNotification('warning', message, title, options); - }; - - abp.notify.error = function (message, title, options) { - showNotification('error', message, title, options); - }; - -})(); \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs index d56660be57..63ddc222bd 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs @@ -31,6 +31,14 @@ public class AbpEfCoreNavigationHelper : ITransientDependency protected virtual void EntityEntryTrackedOrStateChanged(EntityEntry entityEntry) { + if (entityEntry.State is EntityState.Unchanged or EntityState.Modified) + { + foreach (var entry in EntityEntries.Values.Where(x => x.NavigationEntries.Any())) + { + entry.UpdateNavigationEntries(); + } + } + if (entityEntry.State != EntityState.Unchanged) { return; @@ -189,6 +197,22 @@ public class AbpEfCoreNavigationHelper : ITransientDependency return navigationEntryProperty != null && navigationEntryProperty.IsModified; } + public virtual AbpNavigationEntry? GetNavigationEntry(EntityEntry entityEntry, int navigationEntryIndex) + { + var entryId = GetEntityEntryIdentity(entityEntry); + if (entryId == null) + { + return null; + } + + if (!EntityEntries.TryGetValue(entryId, out var abpEntityEntry)) + { + return null; + } + + return abpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex); + } + protected virtual string? GetEntityEntryIdentity(EntityEntry entityEntry) { if (entityEntry.Entity is IEntity entryEntity && entryEntity.GetKeys().Length == 1) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs index 0aef48e0d1..4b8a531db1 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; @@ -32,6 +33,49 @@ public class AbpEntityEntry EntityEntry = entityEntry; NavigationEntries = EntityEntry.Navigations.Select(x => new AbpNavigationEntry(x, x.Metadata.Name)).ToList(); } + + public void UpdateNavigationEntries() + { + foreach (var navigationEntry in NavigationEntries) + { + if (IsModified || + EntityEntry.State == EntityState.Modified || + navigationEntry.IsModified || + navigationEntry.NavigationEntry.IsModified) + { + continue; + } + + var navigation = EntityEntry.Navigations.FirstOrDefault(n => n.Metadata.Name == navigationEntry.Name); + + var currentValue = AbpNavigationEntry.GetOriginalValue(navigation?.CurrentValue); + if (currentValue == null) + { + continue; + } + + switch (navigationEntry.OriginalValue) + { + case null: + navigationEntry.OriginalValue = currentValue; + break; + case IEnumerable originalValueCollection when currentValue is IEnumerable currentValueCollection: + { + var existingList = originalValueCollection.Cast().ToList(); + var newList = currentValueCollection.Cast().ToList(); + if (newList.Count > existingList.Count) + { + navigationEntry.OriginalValue = currentValue; + } + + break; + } + default: + navigationEntry.OriginalValue = currentValue; + break; + } + } + } } public class AbpNavigationEntry @@ -42,9 +86,29 @@ public class AbpNavigationEntry public bool IsModified { get; set; } + public List? OriginalValue { get; set; } + + public object? CurrentValue => NavigationEntry.CurrentValue; + public AbpNavigationEntry(NavigationEntry navigationEntry, string name) { NavigationEntry = navigationEntry; Name = name; + OriginalValue = GetOriginalValue(navigationEntry.CurrentValue); + } + + public static List? GetOriginalValue(object? currentValue) + { + if (currentValue is null) + { + return null; + } + + if (currentValue is IEnumerable enumerable) + { + return enumerable.Cast().ToList(); + } + + return new List { currentValue }; } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs index a52ac2f437..d50e6b89f6 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -193,16 +194,20 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency } } - if (Options.SaveEntityHistoryWhenNavigationChanges && AbpEfCoreNavigationHelper != null) + if (AbpEfCoreNavigationHelper != null) { foreach (var (navigationEntry, index) in entityEntry.Navigations.Select((value, i) => ( value, i ))) { if (AbpEfCoreNavigationHelper.IsNavigationEntryModified(entityEntry, index)) { + var abpNavigationEntry = AbpEfCoreNavigationHelper.GetNavigationEntry(entityEntry, index); + var isCollection = navigationEntry.Metadata.IsCollection; propertyChanges.Add(new EntityPropertyChangeInfo { PropertyName = navigationEntry.Metadata.Name, - PropertyTypeFullName = navigationEntry.Metadata.ClrType.GetFirstGenericArgumentIfNullable().FullName! + PropertyTypeFullName = navigationEntry.Metadata.ClrType.GetFirstGenericArgumentIfNullable().FullName!, + OriginalValue = GetNavigationPropertyValue(abpNavigationEntry?.OriginalValue, isCollection), + NewValue = GetNavigationPropertyValue(abpNavigationEntry?.CurrentValue, isCollection) }); } } @@ -211,6 +216,44 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency return propertyChanges; } + protected virtual string? GetNavigationPropertyValue(object? entity, bool isCollection) + { + switch (entity) + { + case null: + return null; + + case IEntity entryEntity: + var keys = entryEntity.GetKeys(); + return keys.Length == 0 ? null : string.Join(", ",keys).TruncateWithPostfix(EntityPropertyChangeInfo.MaxValueLength); + + case IEnumerable enumerable: + var keysList = new List(); + foreach (var item in enumerable) + { + var id = GetNavigationPropertyValue(item, false); + if (id != null) + { + keysList.Add(id); + } + } + + if (keysList.Count == 0) + { + return null; + } + + var serializedKeysEnumerable = keysList.Count == 1 && !isCollection + ? keysList.First() + : JsonSerializer.Serialize(keysList); + + return serializedKeysEnumerable.TruncateWithPostfix(EntityPropertyChangeInfo.MaxValueLength); + + default: + return null; + } + } + protected virtual bool IsCreated(EntityEntry entityEntry) { return entityEntry.State == EntityState.Added; diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs index 04d07259a3..90c118eca1 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs @@ -28,30 +28,6 @@ public class LocalDistributedEventBus : IDistributedEventBus, ISingletonDependen ServiceScopeFactory = serviceScopeFactory; AbpDistributedEventBusOptions = distributedEventBusOptions.Value; Subscribe(distributedEventBusOptions.Value.Handlers); - - // For unit testing - if (localEventBus is LocalEventBus eventBus) - { - eventBus.OnEventHandleInvoking = async (eventType, eventData) => - { - await localEventBus.PublishAsync(new DistributedEventReceived() - { - Source = DistributedEventSource.Direct, - EventName = EventNameAttribute.GetNameOrDefault(eventType), - EventData = eventData - }, onUnitOfWorkComplete: false); - }; - - eventBus.OnPublishing = async (eventType, eventData) => - { - await localEventBus.PublishAsync(new DistributedEventSent() - { - Source = DistributedEventSource.Direct, - EventName = EventNameAttribute.GetNameOrDefault(eventType), - EventData = eventData - }, onUnitOfWorkComplete: false); - }; - } } public virtual void Subscribe(ITypeList handlers) diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs index c24627cdc5..48f70ac8c1 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Reflection; using Volo.Abp.Threading; @@ -175,45 +174,4 @@ public class LocalEventBus : EventBusBase, ILocalEventBus, ISingletonDependency return false; } - - // Internal for unit testing - internal Func? OnEventHandleInvoking { get; set; } - - // Internal for unit testing - protected async override Task InvokeEventHandlerAsync(IEventHandler eventHandler, object eventData, Type eventType) - { - if (OnEventHandleInvoking != null && eventType != typeof(DistributedEventSent) && eventType != typeof(DistributedEventReceived)) - { - await OnEventHandleInvoking(eventType, eventData); - } - - await base.InvokeEventHandlerAsync(eventHandler, eventData, eventType); - } - - // Internal for unit testing - internal Func? OnPublishing { get; set; } - - // For unit testing - public async override Task PublishAsync( - Type eventType, - object eventData, - bool onUnitOfWorkComplete = true) - { - if (onUnitOfWorkComplete && UnitOfWorkManager.Current != null) - { - AddToUnitOfWork( - UnitOfWorkManager.Current, - new UnitOfWorkEventRecord(eventType, eventData, EventOrderGenerator.GetNext()) - ); - return; - } - - // For unit testing - if (OnPublishing != null && eventType != typeof(DistributedEventSent) && eventType != typeof(DistributedEventReceived)) - { - await OnPublishing(eventType, eventData); - } - - await PublishToEventBusAsync(eventType, eventData); - } } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs index 03aca1fc29..55891d8cd6 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs @@ -38,7 +38,7 @@ public class PropertyApiDescriptionModel JsonName = AbpApiProxyScriptingConfiguration.PropertyNameGenerator.Invoke(propertyInfo), Type = ApiTypeNameHelper.GetTypeName(propertyInfo.PropertyType), TypeSimple = ApiTypeNameHelper.GetSimpleTypeName(propertyInfo.PropertyType), - IsRequired = customAttributes.OfType().Any(), + IsRequired = customAttributes.OfType().Any() || propertyInfo.GetCustomAttributesData().Any(attr => attr.AttributeType.Name == "RequiredMemberAttribute"), Minimum = customAttributes.OfType().Select(x => x.Minimum).FirstOrDefault()?.ToString(), Maximum = customAttributes.OfType().Select(x => x.Maximum).FirstOrDefault()?.ToString(), MinLength = customAttributes.OfType().FirstOrDefault()?.Length ?? customAttributes.OfType().FirstOrDefault()?.MinimumLength, diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs index a687ba2bf9..acd905b8c6 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs @@ -1,8 +1,8 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; -using MongoDB.Driver.Linq; using Volo.Abp.Domain.Entities; namespace Volo.Abp.Domain.Repositories.MongoDB; @@ -20,10 +20,13 @@ public interface IMongoDbRepository : IRepository Task> GetCollectionAsync(CancellationToken cancellationToken = default); - [Obsolete("Use GetMongoQueryableAsync method.")] - IMongoQueryable GetMongoQueryable(); + [Obsolete("Use GetQueryable method.")] + IQueryable GetMongoQueryable(); - Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); + [Obsolete("Use GetQueryableAsync method.")] + Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); + + Task> GetQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); Task> GetAggregateAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 45629f76e5..fdc7464d6b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -455,19 +455,19 @@ public class MongoDbRepository public async override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).ToListAsync(cancellationToken); } public async override Task> GetListAsync(Expression> predicate, bool includeDetails = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(predicate).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).Where(predicate).ToListAsync(cancellationToken); } public async override Task GetCountAsync(CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)).LongCountAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).LongCountAsync(cancellationToken); } public async override Task> GetPagedListAsync( @@ -479,10 +479,9 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderByIf>(!sorting.IsNullOrWhiteSpace(), sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy>(skipCount, maxResultCount) .ToListAsync(cancellationToken); } @@ -493,14 +492,14 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - var entities = await (await GetMongoQueryableAsync(cancellationToken)) + var entities = await (await GetQueryableAsync(cancellationToken)) .Where(predicate) .ToListAsync(cancellationToken); await DeleteManyAsync(entities, autoSave, cancellationToken); } - public override async Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) + public async override Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); @@ -527,12 +526,16 @@ public class MongoDbRepository [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { - return GetMongoQueryable(); + return ApplyDataFilters( + SessionHandle != null + ? Collection.AsQueryable(SessionHandle) + : Collection.AsQueryable() + ); } public async override Task> GetQueryableAsync() { - return await GetMongoQueryableAsync(); + return await GetQueryableAsync(); } public async override Task FindAsync( @@ -542,34 +545,36 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(predicate) .SingleOrDefaultAsync(cancellationToken); } - [Obsolete("Use GetMongoQueryableAsync method.")] - public virtual IMongoQueryable GetMongoQueryable() + [Obsolete("Use GetQueryableAsync method.")] + public virtual IQueryable GetMongoQueryable() { - return ApplyDataFilters( - SessionHandle != null - ? Collection.AsQueryable(SessionHandle) - : Collection.AsQueryable() - ); + return GetQueryable(); + } + + [Obsolete("Use GetQueryableAsync method.")] + public virtual Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null) + { + return GetQueryableAsync(cancellationToken, options); } - public virtual Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) + public virtual async Task> GetQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null) { - return GetMongoQueryableAsync(cancellationToken, aggregateOptions); + return await GetQueryableAsync(cancellationToken, options); } - protected virtual async Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) + protected virtual async Task> GetQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) { cancellationToken = GetCancellationToken(cancellationToken); var dbContext = await GetDbContextAsync(cancellationToken); var collection = dbContext.Collection(); - return ApplyDataFilters, TOtherEntity>( + return ApplyDataFilters, TOtherEntity>( dbContext.SessionHandle != null ? collection.AsQueryable(dbContext.SessionHandle, aggregateOptions) : collection.AsQueryable(aggregateOptions) @@ -810,7 +815,7 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Id!.Equals(id)) .FirstOrDefaultAsync(cancellationToken); } @@ -827,7 +832,7 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - var entities = await (await GetMongoQueryableAsync(cancellationToken)) + var entities = await (await GetQueryableAsync(cancellationToken)) .Where(x => ids.Contains(x.Id)) .ToListAsync(cancellationToken); diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs index 676450a5b8..353185c8e3 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs @@ -1,8 +1,8 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; -using MongoDB.Driver.Linq; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.MongoDB; @@ -36,19 +36,26 @@ public static class MongoDbCoreRepositoryExtensions return repository.ToMongoDbRepository().GetCollectionAsync(cancellationToken); } - [Obsolete("Use GetMongoQueryableAsync method.")] - public static IMongoQueryable GetMongoQueryable(this IReadOnlyBasicRepository repository) + [Obsolete("Use GetQueryableAsync method.")] + public static IQueryable GetMongoQueryable(this IReadOnlyBasicRepository repository) where TEntity : class, IEntity { return repository.ToMongoDbRepository().GetMongoQueryable(); } - public static Task> GetMongoQueryableAsync(this IReadOnlyBasicRepository repository, CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) + [Obsolete("Use GetQueryableAsync method.")] + public static Task> GetMongoQueryableAsync(this IReadOnlyBasicRepository repository, CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) where TEntity : class, IEntity { return repository.ToMongoDbRepository().GetMongoQueryableAsync(cancellationToken, aggregateOptions); } + public static Task> GetQueryableAsync(this IReadOnlyBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMongoDbRepository().GetQueryableAsync(); + } + public static Task> GetAggregateAsync(this IReadOnlyBasicRepository repository, CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) where TEntity : class, IEntity { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs index c1d8b8f514..6ad2b0b359 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs @@ -5,7 +5,7 @@ using MongoDB.Bson.Serialization.Serializers; namespace Volo.Abp.MongoDB; -public class AbpMongoDbDateTimeSerializer : DateTimeSerializer +public class AbpMongoDbDateTimeSerializer : StructSerializerBase { protected DateTimeKind DateTimeKind { get; set; } protected bool DisableDateTimeNormalization { get; set; } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs index f61e9ddb45..91d2808010 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs @@ -1,5 +1,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; using Volo.Abp.Domain; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Modularity; @@ -19,6 +22,8 @@ public class AbpMongoDbModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { + BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.Standard)); + context.Services.TryAddTransient( typeof(IMongoDbContextProvider<>), typeof(UnitOfWorkMongoDbContextProvider<>) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index 6a73af27f5..9d1b706d8b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -68,7 +68,6 @@ public class MongoDbContextEventInbox : IMongoDbContextEventInb .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) - .As>() .ToListAsync(cancellationToken: cancellationToken); return outgoingEventRecords diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs index 57b59038b5..6dc8817f02 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs @@ -56,7 +56,6 @@ public class MongoDbContextEventOutbox : IMongoDbContextEventOu .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) - .As>() .ToListAsync(cancellationToken: cancellationToken); return outgoingEventRecords diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs index 287f3ced0e..b7e896a27a 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs @@ -6,9 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.Linq; -using MongoDB.Driver; using MongoDB.Driver.Linq; -using Volo.Abp.DynamicProxy; namespace Volo.Abp.MongoDB; @@ -16,344 +14,339 @@ public class MongoDbAsyncQueryableProvider : IAsyncQueryableProvider, ISingleton { public bool CanExecute(IQueryable queryable) { - return ProxyHelper.UnProxy(queryable) is IMongoQueryable; - } - - protected virtual IMongoQueryable GetMongoQueryable(IQueryable queryable) - { - return ProxyHelper.UnProxy(queryable).As>(); + return queryable.Provider is IMongoQueryProvider; } public Task ContainsAsync(IQueryable queryable, T item, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).Contains(item)); + return Task.FromResult(queryable.Contains(item)); } public Task AnyAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AnyAsync(cancellationToken); + return queryable.AnyAsync(cancellationToken); } public Task AnyAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AnyAsync(predicate, cancellationToken); + return queryable.AnyAsync(predicate, cancellationToken); } public Task AllAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).All(predicate)); + return Task.FromResult(queryable.All(predicate)); } public Task CountAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).CountAsync(cancellationToken); + return queryable.CountAsync(cancellationToken); } public Task CountAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).CountAsync(predicate, cancellationToken); + return queryable.CountAsync(predicate, cancellationToken); } public Task LongCountAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).LongCountAsync(cancellationToken); + return queryable.LongCountAsync(cancellationToken); } public Task LongCountAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).LongCountAsync(predicate, cancellationToken); + return queryable.LongCountAsync(predicate, cancellationToken); } public Task FirstAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstAsync(cancellationToken); + return queryable.FirstAsync(cancellationToken); } public Task FirstAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstAsync(predicate, cancellationToken); + return queryable.FirstAsync(predicate, cancellationToken); } public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstOrDefaultAsync(cancellationToken)!; + return queryable.FirstOrDefaultAsync(cancellationToken)!; } public Task FirstOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstOrDefaultAsync(predicate, cancellationToken)!; + return queryable.FirstOrDefaultAsync(predicate, cancellationToken)!; } public Task LastAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).Last()); + return Task.FromResult(queryable.Last()); } public Task LastAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).Last(predicate)); + return Task.FromResult(queryable.Last(predicate)); } public Task LastOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).LastOrDefault()); + return Task.FromResult(queryable.LastOrDefault()); } public Task LastOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).LastOrDefault(predicate)); + return Task.FromResult(queryable.LastOrDefault(predicate)); } public Task SingleAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleAsync(cancellationToken); + return queryable.SingleAsync(cancellationToken); } public Task SingleAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleAsync(predicate, cancellationToken); + return queryable.SingleAsync(predicate, cancellationToken); } public Task SingleOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleOrDefaultAsync(cancellationToken)!; + return queryable.SingleOrDefaultAsync(cancellationToken)!; } public Task SingleOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleOrDefaultAsync(predicate, cancellationToken)!; + return queryable.SingleOrDefaultAsync(predicate, cancellationToken)!; } public Task MinAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MinAsync(cancellationToken); + return queryable.MinAsync(cancellationToken); } public Task MinAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MinAsync(selector, cancellationToken); + return queryable.MinAsync(selector, cancellationToken); } public Task MaxAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MaxAsync(cancellationToken); + return queryable.MaxAsync(cancellationToken); } public Task MaxAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MaxAsync(selector, cancellationToken); + return queryable.MaxAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task> ToListAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).ToListAsync(cancellationToken); + return queryable.ToListAsync(cancellationToken); } public async Task ToArrayAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return (await GetMongoQueryable(queryable).ToListAsync(cancellationToken)).ToArray(); + return (await queryable.ToListAsync(cancellationToken)).ToArray(); } } diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs index 954e6222ee..aa11d7ffde 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -512,7 +513,9 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToOne) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == null && + x.EntityChanges[1].PropertyChanges[0].NewValue == entityId.ToString())); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 @@ -539,10 +542,13 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToOne) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == entityId.ToString() && + x.EntityChanges[1].PropertyChanges[0].NewValue == null)); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 + var oneToManyId = ""; using (var scope = _auditingManager.BeginScope()) { using (var uow = _unitOfWorkManager.Begin()) @@ -561,6 +567,8 @@ public class Auditing_Tests : AbpAuditingTestBase await repository.UpdateAsync(entity); await uow.CompleteAsync(); await scope.SaveAsync(); + + oneToManyId = entity.OneToMany.First().Id.ToString(); } } @@ -572,36 +580,80 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == null && + x.EntityChanges[1].PropertyChanges[0].NewValue == $"[\"{oneToManyId}\"]")); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 + var newOneToManyId = ""; using (var scope = _auditingManager.BeginScope()) { using (var uow = _unitOfWorkManager.Begin()) { var entity = await repository.GetAsync(entityId); - entity.OneToMany = null; + entity.OneToMany.Add(new AppEntityWithNavigationChildOneToMany + { + AppEntityWithNavigationId = entity.Id, + ChildName = "ChildName2" + }); await repository.UpdateAsync(entity); await uow.CompleteAsync(); await scope.SaveAsync(); + + newOneToManyId = JsonSerializer.Serialize(entity.OneToMany.Select(x => x.Id).ToList()); } } #pragma warning disable 4014 AuditingStore.Received().SaveAsync(Arg.Is(x => x.EntityChanges.Count == 2 && - x.EntityChanges[0].ChangeType == EntityChangeType.Deleted && + x.EntityChanges[0].ChangeType == EntityChangeType.Created && x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName && x.EntityChanges[1].ChangeType == EntityChangeType.Updated && x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == $"[\"{oneToManyId}\"]" && + x.EntityChanges[1].PropertyChanges[0].NewValue == newOneToManyId)); + AuditingStore.ClearReceivedCalls(); +#pragma warning restore 4014 + + using (var scope = _auditingManager.BeginScope()) + { + using (var uow = _unitOfWorkManager.Begin()) + { + var entity = await repository.GetAsync(entityId); + + newOneToManyId = JsonSerializer.Serialize(entity.OneToMany.Select(x => x.Id).ToList()); + + entity.OneToMany = null; + + await repository.UpdateAsync(entity); + await uow.CompleteAsync(); + await scope.SaveAsync(); + } + } + +#pragma warning disable 4014 + AuditingStore.Received().SaveAsync(Arg.Is(x => x.EntityChanges.Count == 3 && + x.EntityChanges[0].ChangeType == EntityChangeType.Deleted && + x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName && + x.EntityChanges[1].ChangeType == EntityChangeType.Deleted && + x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName && + x.EntityChanges[2].ChangeType == EntityChangeType.Updated && + x.EntityChanges[2].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && + x.EntityChanges[2].PropertyChanges.Count == 1 && + x.EntityChanges[2].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) && + x.EntityChanges[2].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[2].PropertyChanges[0].OriginalValue == newOneToManyId && + x.EntityChanges[2].PropertyChanges[0].NewValue == null)); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 + var manyToManyId = ""; using (var scope = _auditingManager.BeginScope()) { using (var uow = _unitOfWorkManager.Begin()) @@ -619,6 +671,8 @@ public class Auditing_Tests : AbpAuditingTestBase await repository.UpdateAsync(entity); await uow.CompleteAsync(); await scope.SaveAsync(); + + manyToManyId = entity.ManyToMany.First().Id.ToString(); } } @@ -630,7 +684,9 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.ManyToMany) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == null && + x.EntityChanges[1].PropertyChanges[0].NewValue == $"[\"{manyToManyId}\"]")); #pragma warning restore 4014 @@ -655,6 +711,8 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[0].PropertyChanges.Count == 1 && x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.ManyToMany) && x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[0].PropertyChanges[0].OriginalValue == $"[\"{manyToManyId}\"]" && + x.EntityChanges[0].PropertyChanges[0].NewValue == null && x.EntityChanges[1].ChangeType == EntityChangeType.Updated && x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigationChildManyToMany).FullName && diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs index bbb8838cf6..880e2810cd 100644 --- a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs +++ b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs @@ -1,5 +1,7 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EventBus.Local; using Volo.Abp.Uow; @@ -9,6 +11,12 @@ namespace Volo.Abp.EventBus.Distributed; public class LocalDistributedEventBus_Test : LocalDistributedEventBusTestBase { + protected override void AfterAddApplication(IServiceCollection services) + { + services.Replace(ServiceDescriptor.Singleton()); + base.AfterAddApplication(services); + } + [Fact] public async Task Should_Call_Handler_AndDispose() { @@ -67,6 +75,30 @@ public class LocalDistributedEventBus_Test : LocalDistributedEventBusTestBase [Fact] public async Task DistributedEventSentAndReceived_Test() { + var localEventBus = GetRequiredService(); + if (localEventBus is UnitTestLocalEventBus eventBus) + { + eventBus.OnEventHandleInvoking = async (eventType, eventData) => + { + await localEventBus.PublishAsync(new DistributedEventReceived() + { + Source = DistributedEventSource.Direct, + EventName = EventNameAttribute.GetNameOrDefault(eventType), + EventData = eventData + }, onUnitOfWorkComplete: false); + }; + + eventBus.OnPublishing = async (eventType, eventData) => + { + await localEventBus.PublishAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Direct, + EventName = EventNameAttribute.GetNameOrDefault(eventType), + EventData = eventData + }, onUnitOfWorkComplete: false); + }; + } + GetRequiredService().Subscribe(); GetRequiredService().Subscribe(); diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/UnitTestLocalEventBus.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/UnitTestLocalEventBus.cs new file mode 100644 index 0000000000..1511d6a071 --- /dev/null +++ b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/UnitTestLocalEventBus.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.EventBus.Local; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace Volo.Abp.EventBus.Distributed; + +/// +/// This class is used in unit tests and supports to publish DistributedEventSent and DistributedEventReceived events. +/// +public class UnitTestLocalEventBus : LocalEventBus +{ + public UnitTestLocalEventBus( + [NotNull] IOptions options, + [NotNull] IServiceScopeFactory serviceScopeFactory, + [NotNull] ICurrentTenant currentTenant, + [NotNull] IUnitOfWorkManager unitOfWorkManager, + [NotNull] IEventHandlerInvoker eventHandlerInvoker) + : base(options, serviceScopeFactory, currentTenant, unitOfWorkManager, eventHandlerInvoker) + { + } + + public Func OnEventHandleInvoking { get; set; } + + protected async override Task InvokeEventHandlerAsync(IEventHandler eventHandler, object eventData, Type eventType) + { + if (OnEventHandleInvoking != null && eventType != typeof(DistributedEventSent) && eventType != typeof(DistributedEventReceived)) + { + await OnEventHandleInvoking(eventType, eventData); + } + + await base.InvokeEventHandlerAsync(eventHandler, eventData, eventType); + } + + public Func OnPublishing { get; set; } + + public async override Task PublishAsync( + Type eventType, + object eventData, + bool onUnitOfWorkComplete = true) + { + if (onUnitOfWorkComplete && UnitOfWorkManager.Current != null) + { + AddToUnitOfWork( + UnitOfWorkManager.Current, + new UnitOfWorkEventRecord(eventType, eventData, EventOrderGenerator.GetNext()) + ); + return; + } + + if (OnPublishing != null && eventType != typeof(DistributedEventSent) && eventType != typeof(DistributedEventReceived)) + { + await OnPublishing(eventType, eventData); + } + + await PublishToEventBusAsync(eventType, eventData); + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index ae688f1640..e2328fdca3 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs index 9b70fe2681..ff6fe1face 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.MongoDB; @@ -11,7 +11,8 @@ public class MongoDbFixture : IDisposable { MongoDbRunner = MongoRunner.Run(new MongoRunnerOptions { - UseSingleNodeReplicaSet = true + UseSingleNodeReplicaSet = true, + ReplicaSetSetupTimeout = TimeSpan.FromSeconds(30) }); } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index 0d5122228d..e2ad9088cb 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -18,9 +18,9 @@ public class Repository_Basic_Tests : Repository_Basic_Tests>().ShouldNotBeNull(); - ((IMongoQueryable)(await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas")).ShouldNotBeNull(); - (await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas").As>().ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).ShouldNotBeNull(); + ((IQueryable)(await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas")).ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas").ShouldNotBeNull(); } [Fact] @@ -69,9 +69,9 @@ public class Repository_Basic_Tests : Repository_Basic_Tests c.Name == "ISTANBUL").ShouldBeNull(); - (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull(); - (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull(); + (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull(); + (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull(); + (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull(); (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull(); (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull(); diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs index f8355b5466..1f0c0aa24d 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using MongoDB.Driver; using MongoDB.Driver.Linq; diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.analyze.json b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.analyze.json index 3ee0c8975a..e0e93375af 100644 --- a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.analyze.json +++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.analyze.json @@ -68,107 +68,6 @@ "contentType": "abpModule", "name": "AbpAccountHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/account/register", - "method": "POST", - "groupName": "Account", - "responseType": "Volo.Abp.Identity.IdentityUserDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "RegisterDto" - } - ] - }, - { - "path": "api/account/send-password-reset-code", - "method": "POST", - "groupName": "Account", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "SendPasswordResetCodeDto" - } - ] - }, - { - "path": "api/account/verify-password-reset-token", - "method": "POST", - "groupName": "Account", - "responseType": "System.Boolean", - "responseTypeAsJson": "true", - "parameterDescriptions": [ - { - "name": "input", - "type": "VerifyPasswordResetTokenInput" - } - ] - }, - { - "path": "api/account/reset-password", - "method": "POST", - "groupName": "Account", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "ResetPasswordDto" - } - ] - }, - { - "path": "api/account/dynamic-claims/refresh", - "method": "POST", - "groupName": "DynamicClaims", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/account/my-profile", - "method": "GET", - "groupName": "Profile", - "responseType": "Volo.Abp.Account.ProfileDto", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/account/my-profile", - "method": "PUT", - "groupName": "Profile", - "responseType": "Volo.Abp.Account.ProfileDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "UpdateProfileDto" - } - ] - }, - { - "path": "api/account/my-profile/change-password", - "method": "POST", - "groupName": "Profile", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "ChangePasswordInput" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.analyze.json b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.analyze.json index af62c4f131..230412ab0e 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.analyze.json +++ b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.analyze.json @@ -79,47 +79,6 @@ "name": "AbpAccountWebModule", "summary": null }, - { - "apis": [ - { - "path": "api/account/login", - "method": "POST", - "groupName": "Account", - "responseType": "Volo.Abp.Account.Web.Areas.Account.Controllers.Models.AbpLoginResult", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "login", - "type": "UserLoginInfo" - } - ] - }, - { - "path": "api/account/logout", - "method": "GET", - "groupName": "Account", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/account/check-password", - "method": "POST", - "groupName": "Account", - "responseType": "Volo.Abp.Account.Web.Areas.Account.Controllers.Models.AbpLoginResult", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "login", - "type": "UserLoginInfo" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null - }, { "namespace": "Volo.Abp.Account.Web.Pages.Account", "contentType": "webPage", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json index d4b3ef586c..3351816d31 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json @@ -48,7 +48,7 @@ "ChangeType": "Change type", "ChangeTime": "Time", "NewValue": "New value", - "OriginalValue": "Original value", + "OriginalValue": "Old value", "PropertyName": "Property name", "PropertyTypeFullName": "Property Type Full Name", "Yes": "Yes", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter.cs new file mode 100644 index 0000000000..f50aec3d92 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Text.RegularExpressions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AuditLogging; + +public class AuditLogEntityTypeFullNameConverter : ITransientDependency +{ + public virtual string Convert(string typeFullName) + { + var genericType = Regex.Match(typeFullName, @"(.+?)`1\[\["); + if (!genericType.Success) + { + return ReplaceGenericSymbol(typeFullName); + } + + var type = Regex.Match(typeFullName, @"`1\[\[(.+?), "); + if (!type.Success) + { + return typeFullName; + } + + if (type.Groups[1].Value.Contains("System.Nullable`1[[")) + { + return genericType.Groups[1].Value + "<" + type.Groups[1].Value.Replace("System.Nullable`1[[", "") + "?>"; + } + + return genericType.Groups[1].Value.Contains("System.Nullable") + ? type.Groups[1].Value + "?" + : genericType.Groups[1].Value + "<" + ReplaceGenericSymbol(type.Groups[1].Value) + ">"; + } + + protected virtual string ReplaceGenericSymbol(string typeFullName) + { + return typeFullName.Contains("`1+") + ? typeFullName.Substring(0, typeFullName.IndexOf("[[", StringComparison.Ordinal)).Replace("`1+", ".") + : typeFullName; + } +} diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs index 94f0622714..30b0495658 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs @@ -19,12 +19,19 @@ public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; } protected IJsonSerializer JsonSerializer { get; } protected AbpExceptionHandlingOptions ExceptionHandlingOptions { get; } + protected AuditLogEntityTypeFullNameConverter AuditLogEntityTypeFullNameConverter { get; } - public AuditLogInfoToAuditLogConverter(IGuidGenerator guidGenerator, IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, IJsonSerializer jsonSerializer, IOptions exceptionHandlingOptions) + public AuditLogInfoToAuditLogConverter( + IGuidGenerator guidGenerator, + IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, + IJsonSerializer jsonSerializer, + IOptions exceptionHandlingOptions, + AuditLogEntityTypeFullNameConverter auditLogEntityTypeFullNameConverter) { GuidGenerator = guidGenerator; ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter; JsonSerializer = jsonSerializer; + AuditLogEntityTypeFullNameConverter = auditLogEntityTypeFullNameConverter; ExceptionHandlingOptions = exceptionHandlingOptions.Value; } @@ -41,6 +48,15 @@ public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, } } + foreach (var entityChange in auditLogInfo.EntityChanges ?? Enumerable.Empty()) + { + entityChange.EntityTypeFullName = AuditLogEntityTypeFullNameConverter.Convert(entityChange.EntityTypeFullName); + foreach (var propertyChange in entityChange.PropertyChanges ?? Enumerable.Empty()) + { + propertyChange.PropertyTypeFullName = AuditLogEntityTypeFullNameConverter.Convert(propertyChange.PropertyTypeFullName); + } + } + var entityChanges = auditLogInfo .EntityChanges? .Select(entityChangeInfo => new EntityChange(GuidGenerator, auditLogId, entityChangeInfo, tenantId: auditLogInfo.TenantId)) diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.analyze.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.analyze.json index 5d090598d4..ddf610f3c8 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,14 @@ { "namespace": "Volo.Abp.AuditLogging.EntityFrameworkCore", "connectionStringName": "AbpAuditLogging", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.AuditLogging.AuditLog", + "contentType": "databaseTable", + "name": "AuditLogs", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs index b406e83d5c..92416174ae 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs @@ -64,8 +64,7 @@ public class MongoAuditLogRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -104,8 +103,7 @@ public class MongoAuditLogRepository : MongoDbRepository>() - .LongCountAsync(GetCancellationToken(cancellationToken)); + var count = await query.LongCountAsync(GetCancellationToken(cancellationToken)); return count; } @@ -128,7 +126,7 @@ public class MongoAuditLogRepository : MongoDbRepository auditLog.ExecutionTime >= startTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "") @@ -151,7 +149,7 @@ public class MongoAuditLogRepository : MongoDbRepository a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate) .OrderBy(t => t.ExecutionTime) .GroupBy(t => new { @@ -169,7 +167,7 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges.Any(y => y.Id == entityChangeId)) .OrderBy(x => x.Id) .FirstAsync(GetCancellationToken(cancellationToken))).EntityChanges.FirstOrDefault(x => x.Id == entityChangeId); @@ -199,8 +197,7 @@ public class MongoAuditLogRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -215,7 +212,7 @@ public class MongoAuditLogRepository : MongoDbRepository>().LongCountAsync(GetCancellationToken(cancellationToken)); + var count = await query.LongCountAsync(GetCancellationToken(cancellationToken)); return count; } @@ -224,7 +221,7 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges.Any(y => y.Id == entityChangeId)) .FirstAsync(GetCancellationToken(cancellationToken)); @@ -240,9 +237,8 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges.Any(y => y.EntityId == entityId && y.EntityTypeFullName == entityTypeFullName)) - .As>() .OrderByDescending(x => x.ExecutionTime) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -263,7 +259,7 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges) .WhereIf(auditLogId.HasValue, e => e.Id == auditLogId) .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogEntityTypeFullNameConverter_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogEntityTypeFullNameConverter_Tests.cs new file mode 100644 index 0000000000..db57347815 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogEntityTypeFullNameConverter_Tests.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.AuditLogging.EntityFrameworkCore; + +public class AuditLogEntityTypeFullNameConverter_Tests : AuditLogEntityTypeFullNameConverter_Tests +{ + +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj index 41718fda4e..a33c1c74f8 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogEntityTypeFullNameConverter_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogEntityTypeFullNameConverter_Tests.cs new file mode 100644 index 0000000000..5c803a2a44 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogEntityTypeFullNameConverter_Tests.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Volo.Abp.AuditLogging.MongoDB; + +[Collection(MongoTestCollection.Name)] +public class AuditLogEntityTypeFullNameConverter_Tests : AuditLogEntityTypeFullNameConverter_Tests +{ + +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs index a68f246c78..569bf3ad2d 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.AuditLogging.MongoDB; diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter_Tests.cs new file mode 100644 index 0000000000..2aac19cd42 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter_Tests.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.AuditLogging; + +public abstract class AuditLogEntityTypeFullNameConverter_Tests : AuditLoggingTestBase + where TStartupModule : IAbpModule +{ + private readonly AuditLogEntityTypeFullNameConverter _typeFullNameConverter; + + protected AuditLogEntityTypeFullNameConverter_Tests() + { + _typeFullNameConverter = GetRequiredService(); + } + + [Fact] + public void AuditLogEntityTypeFullNameConverter_Test() + { + _typeFullNameConverter.Convert("MyType").ShouldBe("MyType"); + + _typeFullNameConverter.Convert(typeof(string).FullName!).ShouldBe("System.String"); + _typeFullNameConverter.Convert(typeof(Guid).FullName!).ShouldBe("System.Guid"); + _typeFullNameConverter.Convert(typeof(Guid?).FullName!).ShouldBe("System.Guid?"); + _typeFullNameConverter.Convert(typeof(int).FullName!).ShouldBe("System.Int32"); + _typeFullNameConverter.Convert(typeof(long?).FullName!).ShouldBe("System.Int64?"); + _typeFullNameConverter.Convert(typeof(MyClass).FullName!).ShouldBe("Volo.Abp.AuditLogging.AuditLogEntityTypeFullNameConverter_Tests.MyClass"); + + _typeFullNameConverter.Convert(typeof(ICollection).FullName!).ShouldBe($"System.Collections.Generic.ICollection"); + _typeFullNameConverter.Convert(typeof(Collection).FullName!).ShouldBe($"System.Collections.ObjectModel.Collection"); + _typeFullNameConverter.Convert(typeof(List).FullName!).ShouldBe($"System.Collections.Generic.List"); + _typeFullNameConverter.Convert(typeof(List).FullName!).ShouldBe($"System.Collections.Generic.List"); + + _typeFullNameConverter.Convert(typeof(ICollection).FullName!).ShouldBe($"System.Collections.Generic.ICollection"); + _typeFullNameConverter.Convert(typeof(Collection).FullName!).ShouldBe($"System.Collections.ObjectModel.Collection"); + _typeFullNameConverter.Convert(typeof(List).FullName!).ShouldBe($"System.Collections.Generic.List"); + } + + public class MyClass + { + + } +} diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.analyze.json b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.analyze.json index fd7de5ddf3..0107165048 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,14 @@ { "namespace": "Volo.Abp.BackgroundJobs.EntityFrameworkCore", "connectionStringName": "AbpBackgroundJobs", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.BackgroundJobs.BackgroundJobRecord", + "contentType": "databaseTable", + "name": "BackgroundJobs", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs index 5993fdf9ba..a3f46643fe 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -29,10 +30,10 @@ public class MongoBackgroundJobRepository : MongoDbRepository> GetWaitingListQuery(int maxResultCount, CancellationToken cancellationToken = default) + protected virtual async Task> GetWaitingListQuery(int maxResultCount, CancellationToken cancellationToken = default) { var now = Clock.Now; - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj index c6a4b35a66..a3f84bb18a 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs index 97bd35c6fa..b41e255cb8 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.BackgroundJobs.MongoDB; diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor index 01cd632615..7814000136 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor @@ -1,8 +1,10 @@ @using Volo.Abp.Localization @using System.Globalization @using System.Collections.Immutable +@using Volo.Abp.AspNetCore.Components.Web @inject ILanguageProvider LanguageProvider @inject IJSRuntime JsRuntime +@inject ICookieService CookieService @if (_otherLanguages != null && _otherLanguages.Any()) { @@ -57,20 +59,23 @@ { await JsRuntime.InvokeVoidAsync( "localStorage.setItem", - "Abp.SelectedLanguage", + "Abp.SelectedLanguage", language.UiCultureName ); await JsRuntime.InvokeVoidAsync( "localStorage.setItem", - "Abp.IsRtl", + "Abp.IsRtl", CultureInfo.GetCultureInfo(language.UiCultureName).TextInfo.IsRightToLeft ); - await JsRuntime.InvokeVoidAsync( - "abp.utils.setCookieValue", + await CookieService.SetAsync( ".AspNetCore.Culture", - $"c={language.CultureName}|uic={language.UiCultureName}" + $"c={language.CultureName}|uic={language.UiCultureName}", + new CookieOptions + { + Path = "/" + } ); await JsRuntime.InvokeVoidAsync("location.reload"); diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.analyze.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.analyze.json index 4cad523863..45eaef2a00 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,20 @@ { "namespace": "Volo.Abp.BlobStoring.Database.EntityFrameworkCore", "connectionStringName": "AbpBlobStoring", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", + "contentType": "databaseTable", + "name": "BlobContainers", + "summary": null + }, + { + "entityFullName": "Volo.Abp.BlobStoring.Database.DatabaseBlob", + "contentType": "databaseTable", + "name": "Blobs", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs index 4610043405..6b2663013d 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs @@ -17,7 +17,7 @@ public class MongoDbDatabaseBlobRepository : MongoDbRepository x.ContainerId == containerId && x.Name == name, cancellationToken @@ -28,7 +28,7 @@ public class MongoDbDatabaseBlobRepository : MongoDbRepository x.ContainerId == containerId && x.Name == name, cancellationToken diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs index 8952236f43..7c086e0bb4 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.BlobStoring.Database.MongoDB; diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj index 1bd05f4357..61c0d81d02 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.abppkg.analyze.json b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.abppkg.analyze.json index d5d9bb3eb1..4e811c43b5 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.abppkg.analyze.json +++ b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.abppkg.analyze.json @@ -1,6 +1,6 @@ { "name": "Volo.BloggingTestApp", - "hash": "faf8c09c571a52e961d15c9dd9c7d7ac", + "hash": "", "contents": [ { "namespace": "Volo.BloggingTestApp", diff --git a/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo.Blogging.Admin.HttpApi.abppkg.analyze.json b/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo.Blogging.Admin.HttpApi.abppkg.analyze.json index 1a6a317bd2..317439a0fb 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo.Blogging.Admin.HttpApi.abppkg.analyze.json +++ b/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo.Blogging.Admin.HttpApi.abppkg.analyze.json @@ -63,90 +63,6 @@ "contentType": "abpModule", "name": "BloggingAdminHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/blogging/blogs/admin", - "method": "GET", - "groupName": "BlogManagement", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Blogging.Blogs.Dtos.BlogDto]", - "responseTypeAsJson": "{\r\n \"items\": [\r\n {\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ]\r\n}", - "parameterDescriptions": [] - }, - { - "path": "api/blogging/blogs/admin/{id}", - "method": "GET", - "groupName": "BlogManagement", - "responseType": "Volo.Blogging.Blogs.Dtos.BlogDto", - "responseTypeAsJson": "{\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/blogs/admin", - "method": "POST", - "groupName": "BlogManagement", - "responseType": "Volo.Blogging.Blogs.Dtos.BlogDto", - "responseTypeAsJson": "{\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "input", - "type": "CreateBlogDto" - } - ] - }, - { - "path": "api/blogging/blogs/admin/{id}", - "method": "PUT", - "groupName": "BlogManagement", - "responseType": "Volo.Blogging.Blogs.Dtos.BlogDto", - "responseTypeAsJson": "{\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "UpdateBlogDto" - } - ] - }, - { - "path": "api/blogging/blogs/admin/{id}", - "method": "DELETE", - "groupName": "BlogManagement", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/blogs/admin/clear-cache/{id}", - "method": "GET", - "groupName": "BlogManagement", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.abppkg.analyze.json b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.abppkg.analyze.json index 64b65921d1..4fb8a11fb7 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.abppkg.analyze.json +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.abppkg.analyze.json @@ -1717,6 +1717,83 @@ "contentType": "repositoryInterface", "name": "IBlogRepository", "summary": null + }, + { + "eventHandlerType": "Distributed", + "namespace": "Volo.Blogging.Users", + "subscribedEvents": [ + { + "underlyingType": { + "name": "UserEto", + "namespace": "Volo.Abp.Users", + "declaringAssemblyName": "Volo.Abp.Users.Abstractions", + "fullName": "Volo.Abp.Users.UserEto" + }, + "name": "EntityUpdatedEto`1", + "namespace": "Volo.Abp.Domain.Entities.Events.Distributed", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain.Shared", + "fullName": "Volo.Abp.Domain.Entities.Events.Distributed.EntityUpdatedEto`1" + } + ], + "implementingInterfaces": [ + { + "name": "IDistributedEventHandler", + "namespace": "Volo.Abp.EventBus.Distributed", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.Distributed.IDistributedEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "BlogUserSynchronizer", + "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Blogging.Posts", + "subscribedEvents": [ + { + "underlyingType": null, + "name": "PostChangedEvent", + "namespace": "Volo.Blogging.Posts", + "declaringAssemblyName": "Volo.Blogging.Domain", + "fullName": "Volo.Blogging.Posts.PostChangedEvent" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "PostCacheInvalidator", + "summary": null } ] } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.abppkg.analyze.json b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.abppkg.analyze.json index c891a76071..76c0f492fa 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,44 @@ { "namespace": "Volo.Blogging.EntityFrameworkCore", "connectionStringName": "Blogging", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Blogging.Users.BlogUser", + "contentType": "databaseTable", + "name": "Users", + "summary": null + }, + { + "entityFullName": "Volo.Blogging.Blogs.Blog", + "contentType": "databaseTable", + "name": "Blogs", + "summary": null + }, + { + "entityFullName": "Volo.Blogging.Posts.Post", + "contentType": "databaseTable", + "name": "Posts", + "summary": null + }, + { + "entityFullName": "Volo.Blogging.Tagging.Tag", + "contentType": "databaseTable", + "name": "Tags", + "summary": null + }, + { + "entityFullName": "Volo.Blogging.Posts.PostTag", + "contentType": "databaseTable", + "name": "PostTags", + "summary": null + }, + { + "entityFullName": "Volo.Blogging.Comments.Comment", + "contentType": "databaseTable", + "name": "Comments", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.abppkg.analyze.json b/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.abppkg.analyze.json index 7b15b827b0..e22ee4946c 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.abppkg.analyze.json +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.abppkg.analyze.json @@ -63,300 +63,6 @@ "contentType": "abpModule", "name": "BloggingHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/blogging/files/{name}", - "method": "GET", - "groupName": "BlogFiles", - "responseType": "Volo.Blogging.Files.RawFileDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "name", - "type": "String" - } - ] - }, - { - "path": "api/blogging/files/www/{name}", - "method": "GET", - "groupName": "BlogFiles", - "responseType": "Volo.Abp.Content.IRemoteStreamContent", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "name", - "type": "String" - } - ] - }, - { - "path": "api/blogging/files/images/upload", - "method": "POST", - "groupName": "BlogFiles", - "responseType": "Volo.Blogging.Files.FileUploadOutputDto", - "responseTypeAsJson": "{\r\n \"name\": \"string\",\r\n \"webUrl\": \"string\"\r\n}", - "parameterDescriptions": [ - { - "name": "File", - "type": "IRemoteStreamContent" - }, - { - "name": "Name", - "type": "String" - } - ] - }, - { - "path": "api/blogging/blogs", - "method": "GET", - "groupName": "Blogs", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Blogging.Blogs.Dtos.BlogDto]", - "responseTypeAsJson": "{\r\n \"items\": [\r\n {\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ]\r\n}", - "parameterDescriptions": [] - }, - { - "path": "api/blogging/blogs/by-shortname/{shortName}", - "method": "GET", - "groupName": "Blogs", - "responseType": "Volo.Blogging.Blogs.Dtos.BlogDto", - "responseTypeAsJson": "{\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "shortName", - "type": "String" - } - ] - }, - { - "path": "api/blogging/blogs/{id}", - "method": "GET", - "groupName": "Blogs", - "responseType": "Volo.Blogging.Blogs.Dtos.BlogDto", - "responseTypeAsJson": "{\r\n \"name\": \"string\",\r\n \"shortName\": \"string\",\r\n \"description\": \"string\",\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/comments/hierarchical/{postId}", - "method": "GET", - "groupName": "Comments", - "responseType": "System.Collections.Generic.List`1[Volo.Blogging.Comments.Dtos.CommentWithRepliesDto]", - "responseTypeAsJson": "[\r\n {\r\n \"comment\": {\r\n \"repliedCommentId\": null,\r\n \"text\": \"string\",\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"replies\": [\r\n {\r\n \"repliedCommentId\": null,\r\n \"text\": \"string\",\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ]\r\n }\r\n]", - "parameterDescriptions": [ - { - "name": "postId", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/comments", - "method": "POST", - "groupName": "Comments", - "responseType": "Volo.Blogging.Comments.Dtos.CommentWithDetailsDto", - "responseTypeAsJson": "{\r\n \"repliedCommentId\": null,\r\n \"text\": \"string\",\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "input", - "type": "CreateCommentDto" - } - ] - }, - { - "path": "api/blogging/comments/{id}", - "method": "PUT", - "groupName": "Comments", - "responseType": "Volo.Blogging.Comments.Dtos.CommentWithDetailsDto", - "responseTypeAsJson": "{\r\n \"repliedCommentId\": null,\r\n \"text\": \"string\",\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "UpdateCommentDto" - } - ] - }, - { - "path": "api/blogging/comments/{id}", - "method": "DELETE", - "groupName": "Comments", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/posts/{blogId}/all", - "method": "GET", - "groupName": "Posts", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Blogging.Posts.PostWithDetailsDto]", - "responseTypeAsJson": "{\r\n \"items\": [\r\n {\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "blogId", - "type": "Guid" - }, - { - "name": "tagName", - "type": "String" - } - ] - }, - { - "path": "api/blogging/posts/{blogId}/all/by-time", - "method": "GET", - "groupName": "Posts", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Blogging.Posts.PostWithDetailsDto]", - "responseTypeAsJson": "{\r\n \"items\": [\r\n {\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "blogId", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/posts/read", - "method": "GET", - "groupName": "Posts", - "responseType": "Volo.Blogging.Posts.PostWithDetailsDto", - "responseTypeAsJson": "{\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "Url", - "type": "String" - }, - { - "name": "BlogId", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/posts/{id}", - "method": "GET", - "groupName": "Posts", - "responseType": "Volo.Blogging.Posts.PostWithDetailsDto", - "responseTypeAsJson": "{\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/posts", - "method": "POST", - "groupName": "Posts", - "responseType": "Volo.Blogging.Posts.PostWithDetailsDto", - "responseTypeAsJson": "{\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "input", - "type": "CreatePostDto" - } - ] - }, - { - "path": "api/blogging/posts/{id}", - "method": "PUT", - "groupName": "Posts", - "responseType": "Volo.Blogging.Posts.PostWithDetailsDto", - "responseTypeAsJson": "{\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n}", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "UpdatePostDto" - } - ] - }, - { - "path": "api/blogging/posts/user/{userId}", - "method": "GET", - "groupName": "Posts", - "responseType": "System.Collections.Generic.List`1[Volo.Blogging.Posts.PostWithDetailsDto]", - "responseTypeAsJson": "[\r\n {\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n]", - "parameterDescriptions": [ - { - "name": "userId", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/posts/{blogId}/latest/{count}", - "method": "GET", - "groupName": "Posts", - "responseType": "System.Collections.Generic.List`1[Volo.Blogging.Posts.PostWithDetailsDto]", - "responseTypeAsJson": "[\r\n {\r\n \"blogId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"title\": \"string\",\r\n \"coverImage\": \"string\",\r\n \"url\": \"string\",\r\n \"content\": \"string\",\r\n \"description\": \"string\",\r\n \"readCount\": 0,\r\n \"commentCount\": 0,\r\n \"writer\": {\r\n \"tenantId\": null,\r\n \"name\": \"string\",\r\n \"surname\": \"string\",\r\n \"userName\": \"string\",\r\n \"email\": \"string\",\r\n \"emailConfirmed\": false,\r\n \"phoneNumber\": \"string\",\r\n \"phoneNumberConfirmed\": false,\r\n \"webSite\": \"string\",\r\n \"twitter\": \"string\",\r\n \"github\": \"string\",\r\n \"linkedin\": \"string\",\r\n \"company\": \"string\",\r\n \"jobTitle\": \"string\",\r\n \"biography\": \"string\",\r\n \"extraProperties\": {\r\n \"string\": \"object\"\r\n },\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n },\r\n \"tags\": [\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ],\r\n \"concurrencyStamp\": \"string\",\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n]", - "parameterDescriptions": [ - { - "name": "blogId", - "type": "Guid" - }, - { - "name": "count", - "type": "Int32" - } - ] - }, - { - "path": "api/blogging/posts/{id}", - "method": "DELETE", - "groupName": "Posts", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/blogging/tags/popular/{blogId}", - "method": "GET", - "groupName": "Tags", - "responseType": "System.Collections.Generic.List`1[Volo.Blogging.Tagging.Dtos.TagDto]", - "responseTypeAsJson": "[\r\n {\r\n \"name\": \"string\",\r\n \"description\": \"string\",\r\n \"usageCount\": 0,\r\n \"isDeleted\": false,\r\n \"deleterId\": null,\r\n \"deletionTime\": null,\r\n \"lastModificationTime\": null,\r\n \"lastModifierId\": null,\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"creatorId\": null,\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n]", - "parameterDescriptions": [ - { - "name": "blogId", - "type": "Guid" - }, - { - "name": "ResultCount", - "type": "Int32" - }, - { - "name": "MinimumPostCount", - "type": "Nullable" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs index 42c8bb467a..c15ef4d0cb 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs @@ -16,7 +16,7 @@ namespace Volo.Blogging.Blogs public virtual async Task FindByShortNameAsync(string shortName, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == shortName, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == shortName, GetCancellationToken(cancellationToken)); } } } diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs index 89e5b6b575..77c443e485 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -18,7 +19,7 @@ namespace Volo.Blogging.Comments public virtual async Task> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(a => a.PostId == postId) .OrderBy(a => a.CreationTime) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -26,19 +27,19 @@ namespace Volo.Blogging.Comments public virtual async Task GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .CountAsync(a => a.PostId == postId, GetCancellationToken(cancellationToken)); } public virtual async Task> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(a => a.RepliedCommentId == id).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default) { - var recordsToDelete = (await GetMongoQueryableAsync(cancellationToken)).Where(pt => pt.PostId == id); + var recordsToDelete = (await GetQueryableAsync(cancellationToken)).Where(pt => pt.PostId == id); foreach (var record in recordsToDelete) { diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs index 3cdcccc5fd..b3083cbd5f 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Nito.AsyncEx; @@ -20,13 +21,13 @@ namespace Volo.Blogging.Posts public virtual async Task> GetPostsByBlogId(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(p => blogId == p.BlogId && p.Url == url); + var query = (await GetQueryableAsync(cancellationToken)).Where(p => blogId == p.BlogId && p.Url == url); if (excludingPostId != null) { @@ -38,7 +39,7 @@ namespace Volo.Blogging.Posts public virtual async Task GetPostByUrl(Guid blogId, string url, CancellationToken cancellationToken = default) { - var post = await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url, GetCancellationToken(cancellationToken)); + var post = await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url, GetCancellationToken(cancellationToken)); if (post == null) { @@ -50,7 +51,7 @@ namespace Volo.Blogging.Posts public virtual async Task> GetOrderedList(Guid blogId, bool @descending = false, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId); + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId); if (!descending) { @@ -62,7 +63,7 @@ namespace Volo.Blogging.Posts public virtual async Task> GetListByUserIdAsync(Guid userId, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.CreatorId == userId) + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.CreatorId == userId) .OrderByDescending(x => x.CreationTime); return await query.ToListAsync(GetCancellationToken(cancellationToken)); @@ -70,7 +71,7 @@ namespace Volo.Blogging.Posts public virtual async Task> GetLatestBlogPostsAsync(Guid blogId, int count, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId) + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId) .OrderByDescending(x => x.CreationTime) .Take(count); diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs index bfa0c9fb4d..2e60faaccc 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs @@ -20,27 +20,27 @@ namespace Volo.Blogging.Tagging public virtual async Task> GetListAsync(Guid blogId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task DecreaseUsageCountOfTagsAsync(List ids, CancellationToken cancellationToken = default) { - var tags = await (await GetMongoQueryableAsync(cancellationToken)) + var tags = await (await GetQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs index 3595620f54..b68e77c9fd 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using Volo.Abp.MongoDB; using Volo.Abp.Users.MongoDB; using Volo.Blogging.MongoDB; @@ -17,7 +18,7 @@ namespace Volo.Blogging.Users public virtual async Task> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken = default) { - var query = await GetMongoQueryableAsync(cancellationToken); + var query = await GetQueryableAsync(cancellationToken); if (!string.IsNullOrWhiteSpace(filter)) { diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj index 88cd171a55..7dcac50e69 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs index ad1fce80e5..e1a4d00ce3 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; public class MongoDbFixture : IDisposable { diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.abppkg.analyze.json b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.abppkg.analyze.json index 7a5076de44..4a31b29a5e 100644 --- a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.abppkg.analyze.json +++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.abppkg.analyze.json @@ -1,6 +1,6 @@ { "name": "Volo.CmsKit.HttpApi.Host", - "hash": "1b93c2e5623eede67e84115d4c3c3265", + "hash": "", "contents": [ { "namespace": "Volo.CmsKit", diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.abppkg.analyze.json b/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.abppkg.analyze.json index 2256dbb4e0..bb6aedfa41 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.abppkg.analyze.json +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Host/Volo.CmsKit.Web.Host.abppkg.analyze.json @@ -1,6 +1,6 @@ { "name": "Volo.CmsKit.Web.Host", - "hash": "4e765df6a6f987aba4c051f2106178ac", + "hash": "", "contents": [ { "namespace": "Volo.CmsKit", diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo.CmsKit.Admin.Application.Contracts.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo.CmsKit.Admin.Application.Contracts.abppkg.analyze.json index 1be9d68e1d..e63bfd863f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo.CmsKit.Admin.Application.Contracts.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo.CmsKit.Admin.Application.Contracts.abppkg.analyze.json @@ -58,202 +58,6 @@ "contentType": "abpModule", "name": "CmsKitAdminApplicationContractsModule", "summary": null - }, - { - "displayName": "Comment management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Comments", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Comments.Delete", - "summary": null - }, - { - "displayName": "Permission:Comments.Update", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Comments.Update", - "summary": null - }, - { - "displayName": "Permission:Comments.SettingManagement", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Comments.SettingManagement", - "summary": null - }, - { - "displayName": "Tag management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Tags", - "summary": null - }, - { - "displayName": "Create", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Tags.Create", - "summary": null - }, - { - "displayName": "Update", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Tags.Update", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Tags.Delete", - "summary": null - }, - { - "displayName": "Page management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Pages", - "summary": null - }, - { - "displayName": "Create", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Pages.Create", - "summary": null - }, - { - "displayName": "Update", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Pages.Update", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Pages.Delete", - "summary": null - }, - { - "displayName": "Set as home page", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Pages.SetAsHomePage", - "summary": null - }, - { - "displayName": "Blog management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Blogs", - "summary": null - }, - { - "displayName": "Create", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Blogs.Create", - "summary": null - }, - { - "displayName": "Update", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Blogs.Update", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Blogs.Delete", - "summary": null - }, - { - "displayName": "Features", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Blogs.Features", - "summary": null - }, - { - "displayName": "Blog post management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.BlogPosts", - "summary": null - }, - { - "displayName": "Create", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.BlogPosts.Create", - "summary": null - }, - { - "displayName": "Update", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.BlogPosts.Update", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.BlogPosts.Delete", - "summary": null - }, - { - "displayName": "Publish", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.BlogPosts.Publish", - "summary": null - }, - { - "displayName": "Menu management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Menus", - "summary": null - }, - { - "displayName": "Create", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Menus.Create", - "summary": null - }, - { - "displayName": "Update", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Menus.Update", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.Menus.Delete", - "summary": null - }, - { - "displayName": "Global resources", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKit.GlobalResources", - "summary": null } ] } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo.CmsKit.Common.Application.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo.CmsKit.Common.Application.abppkg.analyze.json index 97e0500737..970db426d7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo.CmsKit.Common.Application.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo.CmsKit.Common.Application.abppkg.analyze.json @@ -74,6 +74,142 @@ "name": "CmsKitCommonApplicationModule", "summary": null }, + { + "eventHandlerType": "Local", + "namespace": "Volo.CmsKit.Menus", + "subscribedEvents": [ + { + "underlyingType": { + "name": "MenuItem", + "namespace": "Volo.CmsKit.Menus", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.Menus.MenuItem" + }, + "name": "EntityUpdatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityUpdatedEventData`1" + }, + { + "underlyingType": { + "name": "MenuItem", + "namespace": "Volo.CmsKit.Menus", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.Menus.MenuItem" + }, + "name": "EntityDeletedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityDeletedEventData`1" + }, + { + "underlyingType": { + "name": "MenuItem", + "namespace": "Volo.CmsKit.Menus", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.Menus.MenuItem" + }, + "name": "EntityCreatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityCreatedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "MenuChangedHandler", + "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.CmsKit.Blogs", + "subscribedEvents": [ + { + "underlyingType": { + "name": "BlogFeature", + "namespace": "Volo.CmsKit.Blogs", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.Blogs.BlogFeature" + }, + "name": "EntityCreatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityCreatedEventData`1" + }, + { + "underlyingType": { + "name": "BlogFeature", + "namespace": "Volo.CmsKit.Blogs", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.Blogs.BlogFeature" + }, + "name": "EntityUpdatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityUpdatedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "BlogFeatureChangedHandler", + "summary": null + }, { "namespace": "Volo.CmsKit.Tags", "baseClass": { diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.abppkg.analyze.json index a748e67a44..1a7b4bd11b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.abppkg.analyze.json @@ -68,17 +68,6 @@ "contentType": "abpModule", "name": "CmsKitDomainSharedModule", "summary": null - }, - { - "defaultValue": "false", - "displayName": "CmsKit.Comments.RequireApprovement", - "description": "", - "isVisibleToClient": true, - "isInherited": true, - "isEncrypted": false, - "contentType": "setting", - "name": "CmsKit.Comments.RequireApprovement", - "summary": null } ] } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json index c67dae4a57..e0938f4285 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json @@ -241,6 +241,19 @@ "CssClass": "فئة CSS", "TagsHelpText": "يجب أن تكون العلامات مفصولة بفواصل (على سبيل المثال: tag1، tag2، tag3)", "ThisPartOfContentCouldntBeLoaded": "لا يمكن تحميل هذا الجزء من المحتوى.", + "JustNow": "الآن", + "MinuteAgo": "دقيقة واحدة مضت", + "MinutesAgo": "{0} دقائق مضت", + "HourAgo": "ساعة واحدة مضت", + "HoursAgo": "{0} ساعات مضت", + "YesterdayAt": "أمس في {0}", + "DayAt": "{0} في {1}", + "MonthDayAt": "{0} {1} في {2}", + "FullDate": "{0} {1} {2}", + "Minute": "د", + "Hour": "س", + "Day": "ي", + "Week": "أ", "DuplicateCommentAttemptMessage": "تم اكتشاف محاولة نشر تعليق مكررة. لقد تم بالفعل تقديم تعليقك.", "ChooseAnActionForBlog": "اختر إجراءً للمدونة", "AssignBlogPostsToOtherBlog": "تعيين مشاركات المدونة إلى مدونة أخرى", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json index 4fcbc946c9..da43ebcc17 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json @@ -259,6 +259,19 @@ "CommentAlertMessage": "There are {0} comments waiting for approval", "Settings:Menu:CmsKit": "CMS", "CommentsAwaitingApproval": "Comments Awaiting Approval", + "JustNow": "Just now", + "MinuteAgo": "1 minute ago", + "MinutesAgo": "{0} minutes ago", + "HourAgo": "1 hour ago", + "HoursAgo": "{0} hours ago", + "YesterdayAt": "Yesterday at {0}", + "DayAt": "{0} at {1}", + "MonthDayAt": "{0} {1} at {2}", + "FullDate": "{0} {1} {2}", + "Minute": "m", + "Hour": "h", + "Day": "d", + "Week": "w", "CommentSubmittedForApproval": "Your comment has been submitted for approval.", "ChooseAnActionForBlog": "Choose an action for the blog", "AssignBlogPostsToOtherBlog": "Assign blog posts to another blog", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.abppkg.analyze.json index ab00cf8db6..3b127368a9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.abppkg.analyze.json @@ -5627,6 +5627,88 @@ "contentType": "repositoryInterface", "name": "IBlogRepository", "summary": null + }, + { + "eventHandlerType": "Distributed", + "namespace": "Volo.CmsKit.Users", + "subscribedEvents": [ + { + "underlyingType": { + "name": "UserEto", + "namespace": "Volo.Abp.Users", + "declaringAssemblyName": "Volo.Abp.Users.Abstractions", + "fullName": "Volo.Abp.Users.UserEto" + }, + "name": "EntityUpdatedEto`1", + "namespace": "Volo.Abp.Domain.Entities.Events.Distributed", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain.Shared", + "fullName": "Volo.Abp.Domain.Entities.Events.Distributed.EntityUpdatedEto`1" + } + ], + "implementingInterfaces": [ + { + "name": "IDistributedEventHandler", + "namespace": "Volo.Abp.EventBus.Distributed", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.Distributed.IDistributedEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "CmsUserSynchronizer", + "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.CmsKit.Menus", + "subscribedEvents": [ + { + "underlyingType": { + "name": "Page", + "namespace": "Volo.CmsKit.Pages", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.Pages.Page" + }, + "name": "EntityUpdatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityUpdatedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "PageChangedHandler", + "summary": null } ] } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo.CmsKit.EntityFrameworkCore.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo.CmsKit.EntityFrameworkCore.abppkg.analyze.json index 88283b8433..c558f2842d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo.CmsKit.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo.CmsKit.EntityFrameworkCore.abppkg.analyze.json @@ -72,7 +72,92 @@ { "namespace": "Volo.CmsKit.EntityFrameworkCore", "connectionStringName": "CmsKit", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.CmsKit.Comments.Comment", + "contentType": "databaseTable", + "name": "Comments", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Users.CmsUser", + "contentType": "databaseTable", + "name": "User", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Reactions.UserReaction", + "contentType": "databaseTable", + "name": "Reactions", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Ratings.Rating", + "contentType": "databaseTable", + "name": "Ratings", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Tags.Tag", + "contentType": "databaseTable", + "name": "Tags", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Tags.EntityTag", + "contentType": "databaseTable", + "name": "EntityTags", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Pages.Page", + "contentType": "databaseTable", + "name": "Pages", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Blogs.Blog", + "contentType": "databaseTable", + "name": "Blogs", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Blogs.BlogPost", + "contentType": "databaseTable", + "name": "BlogPosts", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Blogs.BlogFeature", + "contentType": "databaseTable", + "name": "BlogFeatures", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.MediaDescriptors.MediaDescriptor", + "contentType": "databaseTable", + "name": "MediaDescriptors", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.Menus.MenuItem", + "contentType": "databaseTable", + "name": "MenuItems", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.GlobalResources.GlobalResource", + "contentType": "databaseTable", + "name": "GlobalResources", + "summary": null + }, + { + "entityFullName": "Volo.CmsKit.MarkedItems.UserMarkedItem", + "contentType": "databaseTable", + "name": "UserMarkedItems", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs index 334debe8c8..606c3e28ff 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs @@ -25,14 +25,14 @@ public class MongoBlogFeatureRepository : MongoDbRepository> GetListAsync(Guid blogId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.BlogId == blogId) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListAsync(Guid blogId, List featureNames, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.BlogId == blogId && featureNames.Contains(x.FeatureName)) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs index 0212e5975c..b47abe1115 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs @@ -44,7 +44,7 @@ public class MongoBlogPostRepository : MongoDbRepository(token)).FirstOrDefaultAsync(x => x.Id == blogPost.AuthorId, token); + blogPost.Author = await (await GetQueryableAsync(token)).FirstOrDefaultAsync(x => x.Id == blogPost.AuthorId, token); return blogPost; } @@ -64,13 +64,13 @@ public class MongoBlogPostRepository : MongoDbRepository>(tagFilteredEntityIds.Any(), x => tagFilteredEntityIds.Contains(x.Id)) - .WhereIf>(favoriteUserFilteredEntityIds.Any(), x => favoriteUserFilteredEntityIds.Contains(x.Id)) - .WhereIf>(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter)) - .WhereIf>(blogId.HasValue, x => x.BlogId == blogId) - .WhereIf>(authorId.HasValue, x => x.AuthorId == authorId) - .WhereIf>(statusFilter.HasValue, x => x.Status == statusFilter) + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(tagFilteredEntityIds.Any(), x => tagFilteredEntityIds.Contains(x.Id)) + .WhereIf(favoriteUserFilteredEntityIds.Any(), x => favoriteUserFilteredEntityIds.Contains(x.Id)) + .WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter)) + .WhereIf(blogId.HasValue, x => x.BlogId == blogId) + .WhereIf(authorId.HasValue, x => x.AuthorId == authorId) + .WhereIf(statusFilter.HasValue, x => x.Status == statusFilter) .CountAsync(cancellationToken); } @@ -174,7 +174,7 @@ public class MongoBlogPostRepository : MongoDbRepository x.BlogId == blogId && x.Slug.ToLower() == slug, cancellationToken); } @@ -225,14 +225,14 @@ public class MongoBlogPostRepository : MongoDbRepository x.Status == BlogPostStatus.WaitingForReview, cancellationToken); } public async Task UpdateBlogAsync(Guid sourceBlogId, Guid? targetBlogId, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var blogPosts = await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == sourceBlogId).ToListAsync(cancellationToken); + var blogPosts = await (await GetQueryableAsync(cancellationToken)).Where(x => x.BlogId == sourceBlogId).ToListAsync(cancellationToken); if (targetBlogId.HasValue) { foreach (var blogPost in blogPosts) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs index 98567899e5..c25bc688b7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs @@ -23,13 +23,13 @@ public class MongoBlogRepository : MongoDbRepository ExistsAsync(Guid id, CancellationToken cancellationToken = default) { var token = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Id == id, token); + return await (await GetQueryableAsync(token)).AnyAsync(x => x.Id == id, token); } public virtual async Task SlugExistsAsync(string slug, CancellationToken cancellationToken = default) { var token = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Slug == slug, token); + return await (await GetQueryableAsync(token)).AnyAsync(x => x.Slug == slug, token); } public virtual async Task> GetListAsync( @@ -44,8 +44,7 @@ public class MongoBlogRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(token); } @@ -63,7 +62,7 @@ public class MongoBlogRepository : MongoDbRepository x.Id).ToList(); - var blogPostCount = await (await GetMongoQueryableAsync(token)) + var blogPostCount = await (await GetQueryableAsync(token)) .Where(blogPost => blogIds.Contains(blogPost.Id)) .GroupBy(blogPost => blogPost.BlogId) .Select(x => new @@ -82,7 +81,7 @@ public class MongoBlogRepository : MongoDbRepository>().LongCountAsync(token); + return await query.LongCountAsync(token); } public virtual Task GetBySlugAsync([NotNull] string slug, CancellationToken cancellationToken = default) @@ -93,7 +92,7 @@ public class MongoBlogRepository : MongoDbRepository> GetListQueryAsync(string filter = null, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), b => b.Name.Contains(filter)); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs index fab729fcd2..5b4566ecb8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs @@ -61,19 +61,18 @@ public class MongoCommentRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(token); var commentIds = comments.Select(x => x.Id).ToList(); - var authorsQuery = from comment in (await GetMongoQueryableAsync(token)) + var authorsQuery = from comment in (await GetQueryableAsync(token)) join user in (await GetDbContextAsync(token)).CmsUsers on comment.CreatorId equals user.Id where commentIds.Contains(comment.Id) orderby comment.CreationTime select user; - var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(token); + var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(token); return comments .Select( @@ -104,8 +103,7 @@ public class MongoCommentRepository : MongoDbRepository>() - .LongCountAsync(GetCancellationToken(cancellationToken)); + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListWithAuthorsAsync( @@ -117,15 +115,15 @@ public class MongoCommentRepository : MongoDbRepository, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); + var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); - var commentsQuery = (await GetMongoQueryableAsync(cancellationToken)) + var commentsQuery = (await GetQueryableAsync(cancellationToken)) .Where(c => c.EntityId == entityId && c.EntityType == entityType); commentsQuery = commentApproveState switch { @@ -152,7 +150,7 @@ public class MongoCommentRepository : MongoDbRepository x.RepliedCommentId == comment.Id) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -172,7 +170,7 @@ public class MongoCommentRepository : MongoDbRepository ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); } @@ -187,11 +185,11 @@ public class MongoCommentRepository : MongoDbRepository(cancellationToken)).FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken); + var author = await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken); var authorId = author?.Id ?? Guid.Empty; diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs index 91fbbf996e..ea81fe03ff 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs @@ -24,7 +24,7 @@ public class MongoUserMarkedItemRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType && @@ -39,7 +39,7 @@ public class MongoUserMarkedItemRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType) @@ -49,7 +49,7 @@ public class MongoUserMarkedItemRepository : MongoDbRepository> GetEntityIdsFilteredByUserAsync([NotNull] Guid userId, [NotNull] string entityType, [CanBeNull] Guid? tenantId = null, CancellationToken cancellationToken = default) { var dbContext = await GetDbContextAsync(); - var userMarkedItemQueryable = await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)); + var userMarkedItemQueryable = await GetQueryableAsync(GetCancellationToken(cancellationToken)); var resultQueryable = userMarkedItemQueryable .Where(x => x.CreatorId == userId diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs index 1b49ac48bb..7c2f9a3891 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs @@ -26,8 +26,8 @@ public class MongoPageRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellation)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Title.ToLower().Contains(filter.ToLower()) || u.Slug.Contains(filter) @@ -43,13 +43,12 @@ public class MongoPageRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellation)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Title.ToLower().Contains(filter) || u.Slug.Contains(filter)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(Page.Title) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(cancellation); } @@ -68,7 +67,7 @@ public class MongoPageRepository : MongoDbRepository ExistsAsync([NotNull] string slug, CancellationToken cancellationToken = default) { Check.NotNullOrEmpty(slug, nameof(slug)); - return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x => x.Slug == slug, + return await (await GetQueryableAsync(cancellationToken)).AnyAsync(x => x.Slug == slug, GetCancellationToken(cancellationToken)); } @@ -79,7 +78,7 @@ public class MongoPageRepository : MongoDbRepository FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) .FirstOrDefaultAsync(cancellationToken); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs index 3a18f31719..d93cad27be 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs @@ -25,7 +25,7 @@ public class MongoRatingRepository : MongoDbRepository r.EntityType == entityType && r.EntityId == entityId && r.CreatorId == userId, GetCancellationToken(cancellationToken)); @@ -39,7 +39,7 @@ public class MongoRatingRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType && @@ -47,7 +47,7 @@ public class MongoUserReactionRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType && @@ -63,7 +63,7 @@ public class MongoUserReactionRepository : MongoDbRepository x.EntityType == entityType && x.EntityId == entityId) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs index 2e8dc96d01..1ce2319a49 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs @@ -67,7 +67,7 @@ public class MongoEntityTagRepository : MongoDbRepository x.EntityType == entityType && x.Name == name, @@ -69,12 +69,12 @@ public class MongoTagRepository : MongoDbRepository(cancellationToken)) + var entityTagIds = await (await GetQueryableAsync(cancellationToken)) .Where(q => q.EntityId == entityId) .Select(q => q.TagId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); - var query = (await GetMongoQueryableAsync(cancellationToken)) + var query = (await GetQueryableAsync(cancellationToken)) .Where(x => x.EntityType == entityType && entityTagIds.Contains(x.Id)); @@ -86,14 +86,14 @@ public class MongoTagRepository : MongoDbRepository> GetPopularTagsAsync(string entityType, int maxCount, CancellationToken cancellationToken = default) { - var tags = await (await GetMongoQueryableAsync(cancellationToken)) + var tags = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.EntityType == entityType) .Select(x => new { x.Id, x.Name }) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); var tagIds = tags.Select(x => x.Id); - var entityTagCounts = await (await GetMongoQueryableAsync(cancellationToken)) + var entityTagCounts = await (await GetQueryableAsync(cancellationToken)) .Where(q => tagIds.Contains(q.TagId)) .GroupBy(q => q.TagId) .Select(q => new { TagId = q.Key, Count = q.Count() }) @@ -116,8 +116,7 @@ public class MongoTagRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -126,9 +125,9 @@ public class MongoTagRepository : MongoDbRepository> GetQueryableByFilterAsync(string filter, CancellationToken cancellationToken = default) + private async Task> GetQueryableByFilterAsync(string filter, CancellationToken cancellationToken = default) { - var mongoQueryable = await GetMongoQueryableAsync(cancellationToken: cancellationToken); + var mongoQueryable = await GetQueryableAsync(cancellationToken: cancellationToken); if (!filter.IsNullOrWhiteSpace()) { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo.CmsKit.Public.Application.Contracts.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo.CmsKit.Public.Application.Contracts.abppkg.analyze.json index 68bc9f6b6d..61c2d03247 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo.CmsKit.Public.Application.Contracts.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo.CmsKit.Public.Application.Contracts.abppkg.analyze.json @@ -63,20 +63,6 @@ "contentType": "abpModule", "name": "CmsKitPublicApplicationContractsModule", "summary": null - }, - { - "displayName": "Comment management", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKitPublic.Comments", - "summary": null - }, - { - "displayName": "Delete all", - "isEnabled": true, - "contentType": "permission", - "name": "CmsKitPublic.Comments.DeleteAll", - "summary": null } ] } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.abppkg.analyze.json b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.abppkg.analyze.json index 599b6913f4..8e10e6ce08 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.abppkg.analyze.json +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.abppkg.analyze.json @@ -69,6 +69,47 @@ "name": "CmsKitPublicApplicationModule", "summary": null }, + { + "eventHandlerType": "Local", + "namespace": "Volo.CmsKit.Public.GlobalResources.Handlers", + "subscribedEvents": [ + { + "underlyingType": { + "name": "GlobalResource", + "namespace": "Volo.CmsKit.GlobalResources", + "declaringAssemblyName": "Volo.CmsKit.Domain", + "fullName": "Volo.CmsKit.GlobalResources.GlobalResource" + }, + "name": "EntityUpdatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityUpdatedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "GlobalResourceEventHandler", + "summary": null + }, { "namespace": "Volo.CmsKit.Public.Reactions", "baseClass": { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml index 7033978f48..d8c09fd773 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml @@ -22,7 +22,7 @@ @((string.IsNullOrWhiteSpace(author.Name) ? author.UserName : author.Name + " " + author.Surname).Trim()) - @creationTime.ToString() + ; } @{ diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index e9ddda97f3..1307c0f26c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -13,6 +13,79 @@ }; } + function isDoubleClicked(element) { + if (element.data("isclicked")) return true; + + element.data("isclicked", true); + setTimeout(function () { + element.removeData("isclicked"); + }, 2000); + } + + function registerCommentTime($container) { + $container.find('[comment-time]').each(function () { + const $timeElement = $(this); + + const creationTime = moment.utc($timeElement.attr('comment-time')); + var timeAgo = formatTime(creationTime); + var readableTime = formatReadableTimestamp(creationTime); + + $timeElement.text(timeAgo); + $timeElement.on('click', function () { + if (isDoubleClicked($timeElement)) return; + + $timeElement.text(readableTime); + setTimeout(function () { + $timeElement.trigger('focusout'); + }, 2000); + + }); + + $timeElement.on('focusout', function () { + $timeElement.text(timeAgo); + }); + }); + } + + function formatTime(creationTime) { + let now = moment(); + let duration = moment.duration(now.diff(creationTime)); + if (duration.asMinutes() < 1) { + return l('JustNow'); + } else if (duration.asMinutes() < 60) { + return `${Math.floor(duration.asMinutes())} ${l('Minute')}`; + } else if (duration.asHours() < 24) { + return `${Math.floor(duration.asHours())} ${l('Hour')}`; + } else if (duration.asDays() < 7) { + return `${Math.floor(duration.asDays())} ${l('Day')}`; + } else { + return `${Math.floor(duration.asWeeks())} ${l('Week')}`; + } + } + + function formatReadableTimestamp(creationTime) { + const now = moment(); + const diffInMinutes = now.diff(creationTime, 'minutes'); + const diffInHours = now.diff(creationTime, 'hours'); + const diffInDays = now.diff(creationTime, 'days'); + + if (diffInMinutes < 1) { + return l('JustNow'); + } else if (diffInMinutes < 60) { + return l('MinutesAgo', diffInMinutes); + } else if (diffInHours < 24) { + return diffInHours === 1 ? l('HourAgo') : l('HoursAgo', diffInHours); + } else if (diffInDays === 1) { + return l('YesterdayAt', creationTime.local().format('h:mm a')); + } else if (diffInDays < 7) { + return l('DayAt', creationTime.local().format('dddd'), creationTime.local().format('h:mm a')); + } else if (now.isSame(creationTime, 'year')) { + return l('MonthDayAt', creationTime.local().format('D'), creationTime.local().format('MMMM'), creationTime.local().format('h:mm a') ); + } else { + return l('FullDate', creationTime.local().format('D'), creationTime.local().format('MMMM'), creationTime.local().format('YYYY')); + } + } + function registerEditLinks($container) { $container.find('.comment-edit-link').each(function () { let $link = $(this); @@ -216,6 +289,8 @@ registerUpdateOfNewComment($widget); registerSubmissionOfNewComment($widget); + registerCommentTime($widget); + focusOnHash($widget); } diff --git a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs index 22f63a3780..53c9457a30 100644 --- a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs +++ b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.CmsKit.MongoDB; diff --git a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj index 17c6dfe717..9c8dc44660 100644 --- a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.abppkg.analyze.json b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.abppkg.analyze.json index 2cec527fd8..14bbf07464 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.abppkg.analyze.json +++ b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.abppkg.analyze.json @@ -1,6 +1,6 @@ { "name": "VoloDocs.Web", - "hash": "b510ce34d8f9772fc2cbd0235c731ce4", + "hash": "", "contents": [ { "namespace": "VoloDocs.Web", @@ -94,6 +94,11 @@ "declaringAssemblyName": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", "namespace": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", "name": "AbpAspNetCoreMvcUiBasicThemeModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Caching.StackExchangeRedis", + "namespace": "Volo.Abp.Caching.StackExchangeRedis", + "name": "AbpCachingStackExchangeRedisModule" } ], "implementingInterfaces": [ diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.abppkg.analyze.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.abppkg.analyze.json index e46f6f929a..a35f53f051 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.abppkg.analyze.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.abppkg.analyze.json @@ -68,41 +68,6 @@ "contentType": "abpModule", "name": "DocsAdminApplicationContractsModule", "summary": null - }, - { - "displayName": "Projects", - "isEnabled": true, - "contentType": "permission", - "name": "Docs.Admin.Projects", - "summary": null - }, - { - "displayName": "Edit", - "isEnabled": true, - "contentType": "permission", - "name": "Docs.Admin.Projects.Update", - "summary": null - }, - { - "displayName": "Delete", - "isEnabled": true, - "contentType": "permission", - "name": "Docs.Admin.Projects.Delete", - "summary": null - }, - { - "displayName": "Create", - "isEnabled": true, - "contentType": "permission", - "name": "Docs.Admin.Projects.Create", - "summary": null - }, - { - "displayName": "Documents", - "isEnabled": true, - "contentType": "permission", - "name": "Docs.Admin.Documents", - "summary": null } ] } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.abppkg.analyze.json b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.abppkg.analyze.json index 0123d894fc..63cd4e0e50 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.abppkg.analyze.json +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.abppkg.analyze.json @@ -63,269 +63,6 @@ "contentType": "abpModule", "name": "DocsAdminHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/docs/admin/documents/ClearCache", - "method": "POST", - "groupName": "DocumentsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "ClearCacheInput" - } - ] - }, - { - "path": "api/docs/admin/documents/PullAll", - "method": "POST", - "groupName": "DocumentsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "PullAllDocumentInput" - } - ] - }, - { - "path": "api/docs/admin/documents/Pull", - "method": "POST", - "groupName": "DocumentsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "PullDocumentInput" - } - ] - }, - { - "path": "api/docs/admin/documents/GetAll", - "method": "GET", - "groupName": "DocumentsAdmin", - "responseType": "Volo.Abp.Application.Dtos.PagedResultDto`1[Volo.Docs.Admin.Documents.DocumentDto]", - "responseTypeAsJson": "{\r\n \"totalCount\": 0,\r\n \"items\": [\r\n {\r\n \"projectId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"projectName\": \"string\",\r\n \"name\": \"string\",\r\n \"version\": \"string\",\r\n \"languageCode\": \"string\",\r\n \"fileName\": \"string\",\r\n \"format\": \"string\",\r\n \"creationTime\": \"0001-01-01T00:00:00\",\r\n \"lastUpdatedTime\": \"0001-01-01T00:00:00\",\r\n \"lastSignificantUpdateTime\": null,\r\n \"lastCachedTime\": \"0001-01-01T00:00:00\",\r\n \"id\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Nullable" - }, - { - "name": "Name", - "type": "String" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - }, - { - "name": "FileName", - "type": "String" - }, - { - "name": "Format", - "type": "String" - }, - { - "name": "CreationTimeMin", - "type": "Nullable" - }, - { - "name": "CreationTimeMax", - "type": "Nullable" - }, - { - "name": "LastUpdatedTimeMin", - "type": "Nullable" - }, - { - "name": "LastUpdatedTimeMax", - "type": "Nullable" - }, - { - "name": "LastSignificantUpdateTimeMin", - "type": "Nullable" - }, - { - "name": "LastSignificantUpdateTimeMax", - "type": "Nullable" - }, - { - "name": "LastCachedTimeMin", - "type": "Nullable" - }, - { - "name": "LastCachedTimeMax", - "type": "Nullable" - }, - { - "name": "Sorting", - "type": "String" - }, - { - "name": "SkipCount", - "type": "Int32" - }, - { - "name": "MaxResultCount", - "type": "Int32" - } - ] - }, - { - "path": "api/docs/admin/documents/RemoveDocumentFromCache", - "method": "PUT", - "groupName": "DocumentsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "documentId", - "type": "Guid" - } - ] - }, - { - "path": "api/docs/admin/documents/ReindexDocument", - "method": "PUT", - "groupName": "DocumentsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "documentId", - "type": "Guid" - } - ] - }, - { - "path": "api/docs/admin/documents/GetFilterItems", - "method": "GET", - "groupName": "DocumentsAdmin", - "responseType": "System.Collections.Generic.List`1[Volo.Docs.Admin.Documents.DocumentInfoDto]", - "responseTypeAsJson": "[\r\n {\r\n \"version\": \"string\",\r\n \"format\": \"string\",\r\n \"languageCode\": \"string\",\r\n \"projectId\": \"00000000-0000-0000-0000-000000000000\"\r\n }\r\n]", - "parameterDescriptions": [] - }, - { - "path": "api/docs/admin/projects", - "method": "GET", - "groupName": "ProjectsAdmin", - "responseType": "Volo.Abp.Application.Dtos.PagedResultDto`1[Volo.Docs.Admin.Projects.ProjectDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "Sorting", - "type": "String" - }, - { - "name": "SkipCount", - "type": "Int32" - }, - { - "name": "MaxResultCount", - "type": "Int32" - } - ] - }, - { - "path": "api/docs/admin/projects/{id}", - "method": "GET", - "groupName": "ProjectsAdmin", - "responseType": "Volo.Docs.Admin.Projects.ProjectDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/docs/admin/projects", - "method": "POST", - "groupName": "ProjectsAdmin", - "responseType": "Volo.Docs.Admin.Projects.ProjectDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "CreateProjectDto" - } - ] - }, - { - "path": "api/docs/admin/projects/{id}", - "method": "PUT", - "groupName": "ProjectsAdmin", - "responseType": "Volo.Docs.Admin.Projects.ProjectDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "UpdateProjectDto" - } - ] - }, - { - "path": "api/docs/admin/projects", - "method": "DELETE", - "groupName": "ProjectsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/docs/admin/projects/ReindexAll", - "method": "POST", - "groupName": "ProjectsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/docs/admin/projects/GetListProjectWithoutDetailsAsync", - "method": "GET", - "groupName": "ProjectsAdmin", - "responseType": "System.Collections.Generic.List`1[Volo.Docs.Admin.Projects.ProjectWithoutDetailsDto]", - "responseTypeAsJson": "[\r\n {\r\n \"id\": \"00000000-0000-0000-0000-000000000000\",\r\n \"name\": \"string\"\r\n }\r\n]", - "parameterDescriptions": [] - }, - { - "path": "api/docs/admin/projects/Reindex", - "method": "POST", - "groupName": "ProjectsAdmin", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "ReindexInput" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.abppkg.analyze.json b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.abppkg.analyze.json index 3e6a93851c..43d97ded1c 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.abppkg.analyze.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.abppkg.analyze.json @@ -1799,6 +1799,83 @@ "contentType": "repositoryInterface", "name": "IDocumentRepository", "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Docs.Documents.FullSearch.Elastic", + "subscribedEvents": [ + { + "underlyingType": { + "name": "Document", + "namespace": "Volo.Docs.Documents", + "declaringAssemblyName": "Volo.Docs.Domain", + "fullName": "Volo.Docs.Documents.Document" + }, + "name": "EntityCreatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityCreatedEventData`1" + }, + { + "underlyingType": { + "name": "Document", + "namespace": "Volo.Docs.Documents", + "declaringAssemblyName": "Volo.Docs.Domain", + "fullName": "Volo.Docs.Documents.Document" + }, + "name": "EntityUpdatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityUpdatedEventData`1" + }, + { + "underlyingType": { + "name": "Document", + "namespace": "Volo.Docs.Documents", + "declaringAssemblyName": "Volo.Docs.Domain", + "fullName": "Volo.Docs.Documents.Document" + }, + "name": "EntityDeletedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityDeletedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "DocumentChangedEventHandler", + "summary": null } ] } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.abppkg.analyze.json b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.abppkg.analyze.json index df487b23e9..e4485ab78c 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,26 @@ { "namespace": "Volo.Docs.EntityFrameworkCore", "connectionStringName": "Docs", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Docs.Projects.Project", + "contentType": "databaseTable", + "name": "Projects", + "summary": null + }, + { + "entityFullName": "Volo.Docs.Documents.Document", + "contentType": "databaseTable", + "name": "Documents", + "summary": null + }, + { + "entityFullName": "Volo.Docs.Documents.DocumentContributor", + "contentType": "databaseTable", + "name": "DocumentContributors", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/docs/src/Volo.Docs.HttpApi/Volo.Docs.HttpApi.abppkg.analyze.json b/modules/docs/src/Volo.Docs.HttpApi/Volo.Docs.HttpApi.abppkg.analyze.json index cc16357478..24a58380bf 100644 --- a/modules/docs/src/Volo.Docs.HttpApi/Volo.Docs.HttpApi.abppkg.analyze.json +++ b/modules/docs/src/Volo.Docs.HttpApi/Volo.Docs.HttpApi.abppkg.analyze.json @@ -63,228 +63,6 @@ "contentType": "abpModule", "name": "DocsHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/docs/projects", - "method": "GET", - "groupName": "DocsProject", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Docs.Projects.ProjectDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/docs/projects/{shortName}", - "method": "GET", - "groupName": "DocsProject", - "responseType": "Volo.Docs.Projects.ProjectDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "shortName", - "type": "String" - } - ] - }, - { - "path": "api/docs/projects/{shortName}/defaultLanguage", - "method": "GET", - "groupName": "DocsProject", - "responseType": "System.String", - "responseTypeAsJson": "\"string\"", - "parameterDescriptions": [ - { - "name": "shortName", - "type": "String" - }, - { - "name": "version", - "type": "String" - } - ] - }, - { - "path": "api/docs/projects/{shortName}/versions", - "method": "GET", - "groupName": "DocsProject", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Docs.Projects.VersionInfoDto]", - "responseTypeAsJson": "{\r\n \"items\": [\r\n {\r\n \"displayName\": \"string\",\r\n \"name\": \"string\"\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "shortName", - "type": "String" - } - ] - }, - { - "path": "api/docs/projects/{shortName}/{version}/languageList", - "method": "GET", - "groupName": "DocsProject", - "responseType": "Volo.Docs.Documents.LanguageConfig", - "responseTypeAsJson": "{\r\n \"languages\": [\r\n {\r\n \"displayName\": \"string\",\r\n \"code\": \"string\",\r\n \"isDefault\": false\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "shortName", - "type": "String" - }, - { - "name": "version", - "type": "String" - } - ] - }, - { - "path": "api/docs/documents", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "Volo.Docs.Documents.DocumentWithDetailsDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Guid" - }, - { - "name": "Name", - "type": "String" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - } - ] - }, - { - "path": "api/docs/documents/default", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "Volo.Docs.Documents.DocumentWithDetailsDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Guid" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - } - ] - }, - { - "path": "api/docs/documents/navigation", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "Volo.Docs.Documents.NavigationNode", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Guid" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - } - ] - }, - { - "path": "api/docs/documents/resource", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "Volo.Docs.Documents.DocumentResourceDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Guid" - }, - { - "name": "Name", - "type": "String" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - } - ] - }, - { - "path": "api/docs/documents/search", - "method": "POST", - "groupName": "DocsDocument", - "responseType": "Volo.Abp.Application.Dtos.PagedResultDto`1[Volo.Docs.Documents.DocumentSearchOutput]", - "responseTypeAsJson": "{\r\n \"totalCount\": 0,\r\n \"items\": [\r\n {\r\n \"name\": \"string\",\r\n \"fileName\": \"string\",\r\n \"version\": \"string\",\r\n \"languageCode\": \"string\",\r\n \"highlight\": [\r\n \"string\"\r\n ]\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "input", - "type": "DocumentSearchInput" - } - ] - }, - { - "path": "api/docs/documents/full-search-enabled", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "System.Boolean", - "responseTypeAsJson": "true", - "parameterDescriptions": [] - }, - { - "path": "api/docs/documents/links", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "System.Collections.Generic.List`1[System.String]", - "responseTypeAsJson": "[\r\n \"string\"\r\n]", - "parameterDescriptions": [ - { - "name": "prefix", - "type": "String" - } - ] - }, - { - "path": "api/docs/documents/parameters", - "method": "GET", - "groupName": "DocsDocument", - "responseType": "Volo.Docs.Documents.DocumentParametersDto", - "responseTypeAsJson": "{\r\n \"parameters\": [\r\n {\r\n \"name\": \"string\",\r\n \"displayName\": \"string\",\r\n \"values\": {\r\n \"string\": \"string\"\r\n }\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Guid" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs index 7f55ef63b0..081e920cff 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs @@ -22,7 +22,7 @@ namespace Volo.Docs.Documents public virtual async Task> GetListWithoutDetailsByProjectId(Guid projectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.ProjectId == projectId) .Select(x => new DocumentWithoutDetails { @@ -37,7 +37,7 @@ namespace Volo.Docs.Documents public virtual async Task> GetUniqueListDocumentInfoAsync(CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Select(x=> new DocumentInfo { ProjectId = x.ProjectId, Version = x.Version, @@ -51,13 +51,13 @@ namespace Volo.Docs.Documents public virtual async Task> GetListByProjectId(Guid projectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetUniqueDocumentsByProjectIdPagedAsync(Guid projectId, int skipCount, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.ProjectId == projectId) .OrderBy(x => x.LastCachedTime) .GroupBy(x => new { x.Name, x.LanguageCode, x.Version }) @@ -69,7 +69,7 @@ namespace Volo.Docs.Documents public virtual async Task GetUniqueDocumentCountByProjectIdAsync(Guid projectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId) + return await (await GetQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId) .GroupBy(x => new { x.Name, x.LanguageCode, x.Version }) .LongCountAsync(GetCancellationToken(cancellationToken)); } @@ -89,17 +89,18 @@ namespace Volo.Docs.Documents bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && - x.Name == name && - x.LanguageCode == languageCode && - x.Version == version, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => + x.ProjectId == projectId && + x.Name == name && + x.LanguageCode == languageCode && + x.Version == version, GetCancellationToken(cancellationToken)); } - + public virtual async Task FindAsync(Guid projectId, List possibleNames, string languageCode, string version, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && possibleNames.Contains(x.Name) && x.LanguageCode == languageCode && x.Version == version, GetCancellationToken(cancellationToken)); @@ -114,11 +115,10 @@ namespace Volo.Docs.Documents public virtual async Task> GetListAsync(Guid? projectId, string version, string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(version != null, x => x.Version == version) .WhereIf(name != null, x => x.Name == name) .WhereIf(projectId.HasValue, x => x.ProjectId == projectId) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -142,26 +142,25 @@ namespace Volo.Docs.Documents int skipCount = 0, CancellationToken cancellationToken = default) { - return await (await ApplyFilterForGetAll( - await GetMongoQueryableAsync(cancellationToken), - projectId: projectId, - name: name, - version: version, - languageCode: languageCode, - fileName: fileName, - format: format, - creationTimeMin: creationTimeMin, - creationTimeMax: creationTimeMax, - lastUpdatedTimeMin: lastUpdatedTimeMin, - lastUpdatedTimeMax: lastUpdatedTimeMax, - lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, - lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, - lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax)) - .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As>() - .PageBy>(skipCount, maxResultCount) - .ToListAsync(GetCancellationToken(cancellationToken)); + await GetQueryableAsync(cancellationToken), + projectId: projectId, + name: name, + version: version, + languageCode: languageCode, + fileName: fileName, + format: format, + creationTimeMin: creationTimeMin, + creationTimeMax: creationTimeMax, + lastUpdatedTimeMin: lastUpdatedTimeMin, + lastUpdatedTimeMax: lastUpdatedTimeMax, + lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, + lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, + lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax, cancellationToken: cancellationToken)) + .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting) + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetAllCountAsync( @@ -184,36 +183,35 @@ namespace Volo.Docs.Documents int skipCount = 0, CancellationToken cancellationToken = default) { - - return await (await ApplyFilterForGetAll( - await GetMongoQueryableAsync(cancellationToken), - projectId: projectId, - name: name, - version: version, - languageCode: languageCode, - fileName: fileName, - format: format, - creationTimeMin: creationTimeMin, - creationTimeMax: creationTimeMax, - lastUpdatedTimeMin: lastUpdatedTimeMin, - lastUpdatedTimeMax: lastUpdatedTimeMax, - lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, - lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, - lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax)) - .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As>() - .PageBy>(skipCount, maxResultCount) - .LongCountAsync(GetCancellationToken(cancellationToken)); + await GetQueryableAsync(cancellationToken), + projectId: projectId, + name: name, + version: version, + languageCode: languageCode, + fileName: fileName, + format: format, + creationTimeMin: creationTimeMin, + creationTimeMax: creationTimeMax, + lastUpdatedTimeMin: lastUpdatedTimeMin, + lastUpdatedTimeMax: lastUpdatedTimeMax, + lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, + lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, + lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax, + cancellationToken: cancellationToken)) + .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting) + .PageBy(skipCount, maxResultCount) + .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == id).SingleAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.Id == id).SingleAsync(GetCancellationToken(cancellationToken)); } - - protected virtual async Task> ApplyFilterForGetAll( - IMongoQueryable query, + + protected virtual async Task> ApplyFilterForGetAll( + IQueryable query, Guid? projectId, string name, string version, @@ -254,7 +252,7 @@ namespace Volo.Docs.Documents { query = query.Where(d => d.FileName != null && d.FileName.Contains(fileName)); } - + if (format != null) { query = query.Where(d => d.Format != null && d.Format == format); diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs index 3960b07eb3..af54bd6bc5 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs @@ -22,8 +22,7 @@ namespace Volo.Docs.Projects public virtual async Task> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default) { - var projects = await (await GetMongoQueryableAsync(cancellationToken)).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting).As>() - .PageBy>(skipCount, maxResultCount) + var projects = await (await GetQueryableAsync(cancellationToken)).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting).PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); return projects; @@ -31,7 +30,7 @@ namespace Volo.Docs.Projects public virtual async Task> GetListWithoutDetailsAsync(CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Select(x=> new ProjectWithoutDetails { Id = x.Id, Name = x.Name, @@ -44,7 +43,7 @@ namespace Volo.Docs.Projects { var normalizeShortName = NormalizeShortName(shortName); - var project = await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); + var project = await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); if (project == null) { @@ -58,7 +57,7 @@ namespace Volo.Docs.Projects { var normalizeShortName = NormalizeShortName(shortName); - return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x => x.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).AnyAsync(x => x.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); } private string NormalizeShortName(string shortName) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index 33f0f3b539..6636787f33 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -24,7 +24,7 @@ var doc = doc || {}; return; } - var textCss = node.path === "javascript:;" ? "": "tree-toggle"; + var textCss = node.path === "javascript:;" ? "tree-toggle" : ""; var uiCss = isRootLazyNode ? "" : "style='display: none;'"; var $ul = $(``); var $li = $(`
  • `); @@ -58,8 +58,6 @@ var doc = doc || {}; doc.lazyExpandableNavigation.isAllLoaded = false; doc.lazyExpandableNavigation.loadAll(childLazyLiElements); } - - initLazyExpandNavigation(); } doc.lazyExpandableNavigation.isAllLoaded = true; @@ -80,6 +78,8 @@ var doc = doc || {}; node.items.forEach(item => { doc.lazyExpandableNavigation.renderNodeAsHtml($li, item, true); }) + + initLazyExpandNavigation(); } } @@ -376,14 +376,14 @@ var doc = doc || {}; var initLazyExpandNavigation = function(){ $("li .lazy-expand").off('click'); - $("li .lazy-expand a").on('click', function(e){ + $("li .lazy-expand").children("a").off('click'); + $("li .lazy-expand").children("a").on('click', function(e){ if($(this).attr("href") !== "javascript:;"){ e.stopPropagation(); } }); $("li .lazy-expand").on('click', function(){ doc.lazyExpandableNavigation.load(this); - initLazyExpandNavigation(); }); } diff --git a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.abppkg.analyze.json b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.abppkg.analyze.json index e05caa0b3c..754357e581 100644 --- a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.abppkg.analyze.json +++ b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.abppkg.analyze.json @@ -84,38 +84,6 @@ "name": "DocsWebModule", "summary": null }, - { - "apis": [ - { - "path": "document-resources", - "method": "GET", - "groupName": "DocumentResource", - "responseType": "Volo.Abp.Http.RemoteServiceErrorResponse", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "ProjectId", - "type": "Guid" - }, - { - "name": "Name", - "type": "String" - }, - { - "name": "Version", - "type": "String" - }, - { - "name": "LanguageCode", - "type": "String" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null - }, { "namespace": "Volo.Docs.Pages.Documents.Project", "contentType": "webPage", diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj index 5c3f98c351..90df72d01d 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs index ad1fce80e5..e1a4d00ce3 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; public class MongoDbFixture : IDisposable { diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo.Abp.FeatureManagement.Domain.abppkg.analyze.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo.Abp.FeatureManagement.Domain.abppkg.analyze.json index 3c2abaac23..3247a44ab8 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo.Abp.FeatureManagement.Domain.abppkg.analyze.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo.Abp.FeatureManagement.Domain.abppkg.analyze.json @@ -667,6 +667,47 @@ "contentType": "repositoryInterface", "name": "IFeatureValueRepository", "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.FeatureManagement", + "subscribedEvents": [ + { + "underlyingType": { + "name": "FeatureValue", + "namespace": "Volo.Abp.FeatureManagement", + "declaringAssemblyName": "Volo.Abp.FeatureManagement.Domain", + "fullName": "Volo.Abp.FeatureManagement.FeatureValue" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "FeatureValueCacheItemInvalidator", + "summary": null } ] } \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo.Abp.FeatureManagement.EntityFrameworkCore.abppkg.analyze.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo.Abp.FeatureManagement.EntityFrameworkCore.abppkg.analyze.json index 39496c615c..c53ce86e71 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo.Abp.FeatureManagement.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo.Abp.FeatureManagement.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,26 @@ { "namespace": "Volo.Abp.FeatureManagement.EntityFrameworkCore", "connectionStringName": "AbpFeatureManagement", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", + "contentType": "databaseTable", + "name": "FeatureGroups", + "summary": null + }, + { + "entityFullName": "Volo.Abp.FeatureManagement.FeatureDefinitionRecord", + "contentType": "databaseTable", + "name": "Features", + "summary": null + }, + { + "entityFullName": "Volo.Abp.FeatureManagement.FeatureValue", + "contentType": "databaseTable", + "name": "FeatureValues", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo.Abp.FeatureManagement.HttpApi.abppkg.analyze.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo.Abp.FeatureManagement.HttpApi.abppkg.analyze.json index 5f25516d3b..2d34f6665b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo.Abp.FeatureManagement.HttpApi.abppkg.analyze.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo.Abp.FeatureManagement.HttpApi.abppkg.analyze.json @@ -63,68 +63,6 @@ "contentType": "abpModule", "name": "AbpFeatureManagementHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/feature-management/features", - "method": "GET", - "groupName": "Features", - "responseType": "Volo.Abp.FeatureManagement.GetFeatureListResultDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "providerName", - "type": "String" - }, - { - "name": "providerKey", - "type": "String" - } - ] - }, - { - "path": "api/feature-management/features", - "method": "PUT", - "groupName": "Features", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "providerName", - "type": "String" - }, - { - "name": "providerKey", - "type": "String" - }, - { - "name": "input", - "type": "UpdateFeaturesDto" - } - ] - }, - { - "path": "api/feature-management/features", - "method": "DELETE", - "groupName": "Features", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "providerName", - "type": "String" - }, - { - "name": "providerKey", - "type": "String" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs index cb7f48aeb4..e89a68a710 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -20,7 +21,7 @@ public class MongoFeatureDefinitionRecordRepository : public virtual async Task FindByNameAsync(string name, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( s => s.Name == name, diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs index 3b52fe2634..0eb4f07e2f 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs @@ -27,7 +27,7 @@ public class MongoFeatureValueRepository : string providerKey, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, GetCancellationToken(cancellationToken)); } @@ -38,7 +38,7 @@ public class MongoFeatureValueRepository : string providerKey, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(GetCancellationToken(cancellationToken)); } @@ -47,7 +47,7 @@ public class MongoFeatureValueRepository : string providerKey, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj index bfc01a429f..2f7f5ee7d0 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs index 8088afee7b..23a5403281 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.FeatureManagement.MongoDB; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json index 3f952c8ba3..510b422ada 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json @@ -6055,6 +6055,65 @@ "name": "IOrganizationUnitRepository", "summary": null }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.Identity", + "subscribedEvents": [ + { + "underlyingType": { + "name": "IdentityUser", + "namespace": "Volo.Abp.Identity", + "declaringAssemblyName": "Volo.Abp.Identity.Domain", + "fullName": "Volo.Abp.Identity.IdentityUser" + }, + "name": "EntityUpdatedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityUpdatedEventData`1" + }, + { + "underlyingType": { + "name": "IdentityUser", + "namespace": "Volo.Abp.Identity", + "declaringAssemblyName": "Volo.Abp.Identity.Domain", + "fullName": "Volo.Abp.Identity.IdentityUser" + }, + "name": "EntityDeletedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityDeletedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "UserEntityUpdatedOrDeletedEventHandler", + "summary": null + }, { "defaultValue": "6", "displayName": "Required length", diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.abppkg.analyze.json b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.abppkg.analyze.json index 06cd2fea51..f0b91802b4 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,56 @@ { "namespace": "Volo.Abp.Identity.EntityFrameworkCore", "connectionStringName": "AbpIdentity", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.Identity.IdentityUser", + "contentType": "databaseTable", + "name": "Users", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.IdentityRole", + "contentType": "databaseTable", + "name": "Roles", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.IdentityClaimType", + "contentType": "databaseTable", + "name": "ClaimTypes", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.OrganizationUnit", + "contentType": "databaseTable", + "name": "OrganizationUnits", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.IdentitySecurityLog", + "contentType": "databaseTable", + "name": "SecurityLogs", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.IdentityLinkUser", + "contentType": "databaseTable", + "name": "LinkUsers", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.IdentityUserDelegation", + "contentType": "databaseTable", + "name": "UserDelegations", + "summary": null + }, + { + "entityFullName": "Volo.Abp.Identity.IdentitySession", + "contentType": "databaseTable", + "name": "Sessions", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo.Abp.Identity.HttpApi.abppkg.analyze.json b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo.Abp.Identity.HttpApi.abppkg.analyze.json index 60e2d18f17..846f79d7e4 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo.Abp.Identity.HttpApi.abppkg.analyze.json +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo.Abp.Identity.HttpApi.abppkg.analyze.json @@ -63,323 +63,6 @@ "contentType": "abpModule", "name": "AbpIdentityHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/identity/roles/all", - "method": "GET", - "groupName": "IdentityRole", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Abp.Identity.IdentityRoleDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/identity/roles", - "method": "GET", - "groupName": "IdentityRole", - "responseType": "Volo.Abp.Application.Dtos.PagedResultDto`1[Volo.Abp.Identity.IdentityRoleDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "Filter", - "type": "String" - }, - { - "name": "Sorting", - "type": "String" - }, - { - "name": "SkipCount", - "type": "Int32" - }, - { - "name": "MaxResultCount", - "type": "Int32" - }, - { - "name": "ExtraProperties", - "type": "ExtraPropertyDictionary" - } - ] - }, - { - "path": "api/identity/roles/{id}", - "method": "GET", - "groupName": "IdentityRole", - "responseType": "Volo.Abp.Identity.IdentityRoleDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/identity/roles", - "method": "POST", - "groupName": "IdentityRole", - "responseType": "Volo.Abp.Identity.IdentityRoleDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "IdentityRoleCreateDto" - } - ] - }, - { - "path": "api/identity/roles/{id}", - "method": "PUT", - "groupName": "IdentityRole", - "responseType": "Volo.Abp.Identity.IdentityRoleDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "IdentityRoleUpdateDto" - } - ] - }, - { - "path": "api/identity/roles/{id}", - "method": "DELETE", - "groupName": "IdentityRole", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/identity/users/{id}", - "method": "GET", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Identity.IdentityUserDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/identity/users", - "method": "GET", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Application.Dtos.PagedResultDto`1[Volo.Abp.Identity.IdentityUserDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "Filter", - "type": "String" - }, - { - "name": "Sorting", - "type": "String" - }, - { - "name": "SkipCount", - "type": "Int32" - }, - { - "name": "MaxResultCount", - "type": "Int32" - }, - { - "name": "ExtraProperties", - "type": "ExtraPropertyDictionary" - } - ] - }, - { - "path": "api/identity/users", - "method": "POST", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Identity.IdentityUserDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "IdentityUserCreateDto" - } - ] - }, - { - "path": "api/identity/users/{id}", - "method": "PUT", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Identity.IdentityUserDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "IdentityUserUpdateDto" - } - ] - }, - { - "path": "api/identity/users/{id}", - "method": "DELETE", - "groupName": "IdentityUser", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/identity/users/{id}/roles", - "method": "GET", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Abp.Identity.IdentityRoleDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/identity/users/assignable-roles", - "method": "GET", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Abp.Identity.IdentityRoleDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [] - }, - { - "path": "api/identity/users/{id}/roles", - "method": "PUT", - "groupName": "IdentityUser", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "IdentityUserUpdateRolesDto" - } - ] - }, - { - "path": "api/identity/users/by-username/{userName}", - "method": "GET", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Identity.IdentityUserDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "userName", - "type": "String" - } - ] - }, - { - "path": "api/identity/users/by-email/{email}", - "method": "GET", - "groupName": "IdentityUser", - "responseType": "Volo.Abp.Identity.IdentityUserDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "email", - "type": "String" - } - ] - }, - { - "path": "api/identity/users/lookup/{id}", - "method": "GET", - "groupName": "IdentityUserLookup", - "responseType": "Volo.Abp.Users.UserData", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/identity/users/lookup/by-username/{userName}", - "method": "GET", - "groupName": "IdentityUserLookup", - "responseType": "Volo.Abp.Users.UserData", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "userName", - "type": "String" - } - ] - }, - { - "path": "api/identity/users/lookup/search", - "method": "GET", - "groupName": "IdentityUserLookup", - "responseType": "Volo.Abp.Application.Dtos.ListResultDto`1[Volo.Abp.Users.UserData]", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "Filter", - "type": "String" - }, - { - "name": "Sorting", - "type": "String" - }, - { - "name": "SkipCount", - "type": "Int32" - }, - { - "name": "MaxResultCount", - "type": "Int32" - }, - { - "name": "ExtraProperties", - "type": "ExtraPropertyDictionary" - } - ] - }, - { - "path": "api/identity/users/lookup/count", - "method": "GET", - "groupName": "IdentityUserLookup", - "responseType": "System.Int64", - "responseTypeAsJson": "42", - "parameterDescriptions": [ - { - "name": "Filter", - "type": "String" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs index ac0b86dee9..6a24fd8ed9 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs @@ -24,13 +24,13 @@ public class MongoIdentityClaimTypeRepository : MongoDbRepository ct.Name == name) .AnyAsync(GetCancellationToken(cancellationToken)); } else { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ct => ct.Id != ignoredId && ct.Name == name) .AnyAsync(GetCancellationToken(cancellationToken)); } @@ -43,15 +43,14 @@ public class MongoIdentityClaimTypeRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) ) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityClaimType.CreationTime) + " desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -59,19 +58,18 @@ public class MongoIdentityClaimTypeRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) ) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListByNamesAsync(IEnumerable names, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => names.Contains(x.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs index 20116fdd0b..46cfc60eb3 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs @@ -18,7 +18,7 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository FindAsync(IdentityLinkUserInfo sourceLinkUserInfo, IdentityLinkUserInfo targetLinkUserInfo, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.SourceUserId == sourceLinkUserInfo.UserId && x.SourceTenantId == sourceLinkUserInfo.TenantId && x.TargetUserId == targetLinkUserInfo.UserId && x.TargetTenantId == targetLinkUserInfo.TenantId || @@ -30,7 +30,7 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository> GetListAsync(IdentityLinkUserInfo linkUserInfo, List excludes = null, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId); @@ -49,7 +49,7 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository + var linkUsers = await (await GetQueryableAsync(cancellationToken)).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs index 3a57f69902..f977572a04 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs @@ -23,7 +23,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync(r => r.NormalizedName == normalizedRoleName, GetCancellationToken(cancellationToken)); } @@ -38,7 +38,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Id).ToList(); - var userCount = await (await GetMongoQueryableAsync(cancellationToken)) + var userCount = await (await GetQueryableAsync(cancellationToken)) .Where(user => user.Roles.Any(role => roleIds.Contains(role.RoleId))) .SelectMany(user => user.Roles) .GroupBy(userRole => userRole.RoleId) @@ -73,7 +73,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository ids, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -82,7 +82,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository r.IsDefault) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -91,17 +91,16 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task RemoveClaimFromAllRolesAsync(string claimType, bool autoSave = false, CancellationToken cancellationToken = default) { - var roles = await (await GetMongoQueryableAsync(cancellationToken)) + var roles = await (await GetQueryableAsync(cancellationToken)) .Where(r => r.Claims.Any(c => c.ClaimType == claimType)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -121,13 +120,12 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityRole.CreationTime) + " desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs index f173272009..388c059f1f 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs @@ -51,8 +51,7 @@ public class MongoIdentitySecurityLogRepository : ); return await query.OrderBy(sorting.IsNullOrWhiteSpace() ? $"{nameof(IdentitySecurityLog.CreationTime)} desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -83,15 +82,14 @@ public class MongoIdentitySecurityLogRepository : cancellationToken ); - return await query.As>() - .LongCountAsync(GetCancellationToken(cancellationToken)); + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetByUserIdAsync(Guid id, Guid userId, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, + return await (await GetQueryableAsync(cancellationToken)).OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, GetCancellationToken(cancellationToken)); } @@ -108,7 +106,7 @@ public class MongoIdentitySecurityLogRepository : string clientIpAddress = null, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .WhereIf(startTime.HasValue, securityLog => securityLog.CreationTime >= startTime.Value) .WhereIf(endTime.HasValue, securityLog => securityLog.CreationTime < endTime.Value.AddDays(1).Date) .WhereIf(!applicationName.IsNullOrWhiteSpace(), securityLog => securityLog.ApplicationName == applicationName) diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs index a1a8f94c49..eb3f99e688 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs @@ -23,8 +23,7 @@ public class MongoIdentitySessionRepository : MongoDbRepository FindAsync(string sessionId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) - .As>() + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .FirstOrDefaultAsync(x => x.SessionId == sessionId, GetCancellationToken(cancellationToken)); } @@ -41,15 +40,13 @@ public class MongoIdentitySessionRepository : MongoDbRepository ExistAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) - .As>() + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .AnyAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task ExistAsync(string sessionId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) - .As>() + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .AnyAsync(x => x.SessionId == sessionId, GetCancellationToken(cancellationToken)); } @@ -62,13 +59,12 @@ public class MongoIdentitySessionRepository : MongoDbRepository x.UserId == userId) .WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device) .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) .OrderBy(sorting.IsNullOrWhiteSpace() ? $"{nameof(IdentitySession.LastAccessed)} desc" : sorting) .PageBy(skipCount, maxResultCount) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -78,11 +74,10 @@ public class MongoIdentitySessionRepository : MongoDbRepository x.UserId == userId) .WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device) .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs index 56cc48121e..1855069b4a 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs @@ -24,25 +24,23 @@ public class MongoIdentityUserDelegationRepository : MongoDbRepository> GetListAsync(Guid? sourceUserId, Guid? targetUserId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(sourceUserId.HasValue, x => x.SourceUserId == sourceUserId) .WhereIf(targetUserId.HasValue, x => x.TargetUserId == targetUserId) - .As>() .ToListAsync(cancellationToken: cancellationToken); } public virtual async Task> GetActiveDelegationsAsync(Guid targetUserId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.TargetUserId == targetUserId) .Where(x => x.StartTime <= Clock.Now && x.EndTime >= Clock.Now) - .As>() .ToListAsync(cancellationToken: cancellationToken); } public virtual async Task FindActiveDelegationByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(x => x.Id == id && x.StartTime <= Clock.Now && diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 58486893ec..c93a41e21d 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -25,7 +25,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync( u => u.NormalizedUserName == normalizedUserName, @@ -43,13 +43,13 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId) .ToArray(); - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken: cancellationToken); var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); var allRoleIds = orgUnitRoleIds.Union(roleIds); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(cancellationToken); } public virtual async Task> GetRoleNamesInOrganizationUnitAsync( @@ -63,13 +63,13 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId) .ToArray(); - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken: cancellationToken); var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); - var queryable = await GetMongoQueryableAsync(cancellationToken); + var queryable = await GetQueryableAsync(cancellationToken); return await queryable .Where(r => roleIds.Contains(r.Id)) @@ -83,7 +83,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.Logins.Any(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -94,7 +94,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Id).FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, GetCancellationToken(cancellationToken)); } @@ -103,14 +103,14 @@ public class MongoIdentityUserRepository : MongoDbRepository u.Claims.Any(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task RemoveClaimFromAllUsersAsync(string claimType, bool autoSave, CancellationToken cancellationToken = default) { - var users = await (await GetMongoQueryableAsync(cancellationToken)) + var users = await (await GetQueryableAsync(cancellationToken)) .Where(u => u.Claims.Any(c => c.ClaimType == claimType)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -129,7 +129,7 @@ public class MongoIdentityUserRepository : MongoDbRepository(cancellationToken); + var queryable = await GetQueryableAsync(cancellationToken); var role = await queryable .Where(x => x.NormalizedName == normalizedRoleName) @@ -141,7 +141,7 @@ public class MongoIdentityUserRepository : MongoDbRepository(); } - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => u.Roles.Any(r => r.RoleId == role.Id)) .ToListAsync(cancellationToken); } @@ -150,7 +150,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.Roles.Any(r => r.RoleId == roleId)) .Select(x => x.Id) .ToListAsync(cancellationToken); @@ -201,8 +201,7 @@ public class MongoIdentityUserRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -217,13 +216,13 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId) .ToArray(); - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken: cancellationToken); var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); var allRoleIds = orgUnitRoleIds.Union(roleIds); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).ToListAsync(cancellationToken); } public virtual async Task> GetOrganizationUnitsAsync( @@ -235,7 +234,7 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken); } @@ -286,7 +285,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnitId)) .ToListAsync(GetCancellationToken(cancellationToken)); return result; @@ -296,7 +295,7 @@ public class MongoIdentityUserRepository : MongoDbRepository organizationUnitIds, CancellationToken cancellationToken = default) { - var result = await (await GetMongoQueryableAsync(cancellationToken)) + var result = await (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)); return result; @@ -308,12 +307,12 @@ public class MongoIdentityUserRepository : MongoDbRepository(cancellationToken)) + var organizationUnitIds = await (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.Code.StartsWith(code)) .Select(ou => ou.Id) .ToListAsync(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(cancellationToken); } @@ -324,7 +323,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.TenantId == tenantId && u.UserName == userName, GetCancellationToken(cancellationToken) @@ -333,14 +332,14 @@ public class MongoIdentityUserRepository : MongoDbRepository> GetListByIdsAsync(IEnumerable ids, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => ids.Contains(x.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task UpdateRoleAsync(Guid sourceRoleId, Guid? targetRoleId, CancellationToken cancellationToken = default) { - var users = await (await GetMongoQueryableAsync(cancellationToken)) + var users = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Roles.Any(r => r.RoleId == sourceRoleId)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -358,7 +357,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.OrganizationUnits.Any(r => r.OrganizationUnitId == sourceOrganizationId)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -390,7 +389,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Value); var roleIds = userAndRoleIds.SelectMany(x => x.Value); - var organizationUnitAndRoleIds = await (await GetMongoQueryableAsync(cancellationToken)).Where(ou => organizationUnitIds.Contains(ou.Id)) + var organizationUnitAndRoleIds = await (await GetQueryableAsync(cancellationToken)).Where(ou => organizationUnitIds.Contains(ou.Id)) .Select(userOrganizationUnit => new { userOrganizationUnit.Id, @@ -399,7 +398,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Roles.Select(r => r.RoleId)).ToList(); var allRoleIds = roleIds.Union(allOrganizationUnitRoleIds); - var roles = await (await GetMongoQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => new{ r.Id, r.Name }).ToListAsync(cancellationToken); + var roles = await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => new{ r.Id, r.Name }).ToListAsync(cancellationToken); var userRoles = userAndRoleIds.ToDictionary(x => x.Key, x => roles.Where(r => x.Value.Contains(r.Id)).Select(r => r.Name).ToArray()); var result = userRoles.Select(x => new IdentityUserIdWithRoleNames { Id = x.Key, RoleNames = x.Value }).ToList(); @@ -422,7 +421,7 @@ public class MongoIdentityUserRepository : MongoDbRepository> GetFilteredQueryableAsync( + protected virtual async Task> GetFilteredQueryableAsync( string filter = null, Guid? roleId = null, Guid? organizationUnitId = null, @@ -442,11 +441,11 @@ public class MongoIdentityUserRepository : MongoDbRepository(cancellationToken)) + var organizationUnitIds = (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.Roles.Any(r => r.RoleId == roleId.Value)) .Select(userOrganizationUnit => userOrganizationUnit.Id) .ToArray(); @@ -455,7 +454,7 @@ public class MongoIdentityUserRepository : MongoDbRepository>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.NormalizedUserName.Contains(upperFilter) || @@ -464,20 +463,20 @@ public class MongoIdentityUserRepository : MongoDbRepository>(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) - .WhereIf>(!string.IsNullOrWhiteSpace(userName), x => x.UserName == userName) - .WhereIf>(!string.IsNullOrWhiteSpace(phoneNumber), x => x.PhoneNumber == phoneNumber) - .WhereIf>(!string.IsNullOrWhiteSpace(emailAddress), x => x.Email == emailAddress) - .WhereIf>(!string.IsNullOrWhiteSpace(name), x => x.Name == name) - .WhereIf>(!string.IsNullOrWhiteSpace(surname), x => x.Surname == surname) - .WhereIf>(isLockedOut.HasValue && isLockedOut.Value, x => x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow) - .WhereIf>(isLockedOut.HasValue && !isLockedOut.Value, x => !(x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow)) - .WhereIf>(notActive.HasValue, x => x.IsActive == !notActive.Value) - .WhereIf>(emailConfirmed.HasValue, x => x.EmailConfirmed == emailConfirmed.Value) - .WhereIf>(isExternal.HasValue, x => x.IsExternal == isExternal.Value) - .WhereIf>(maxCreationTime != null, p => p.CreationTime <= maxCreationTime) - .WhereIf>(minCreationTime != null, p => p.CreationTime >= minCreationTime) - .WhereIf>(maxModifitionTime != null, p => p.LastModificationTime <= maxModifitionTime) - .WhereIf>(minModifitionTime != null, p => p.LastModificationTime >= minModifitionTime); + .WhereIf(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) + .WhereIf(!string.IsNullOrWhiteSpace(userName), x => x.UserName == userName) + .WhereIf(!string.IsNullOrWhiteSpace(phoneNumber), x => x.PhoneNumber == phoneNumber) + .WhereIf(!string.IsNullOrWhiteSpace(emailAddress), x => x.Email == emailAddress) + .WhereIf(!string.IsNullOrWhiteSpace(name), x => x.Name == name) + .WhereIf(!string.IsNullOrWhiteSpace(surname), x => x.Surname == surname) + .WhereIf(isLockedOut.HasValue && isLockedOut.Value, x => x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow) + .WhereIf(isLockedOut.HasValue && !isLockedOut.Value, x => !(x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow)) + .WhereIf(notActive.HasValue, x => x.IsActive == !notActive.Value) + .WhereIf(emailConfirmed.HasValue, x => x.EmailConfirmed == emailConfirmed.Value) + .WhereIf(isExternal.HasValue, x => x.IsExternal == isExternal.Value) + .WhereIf(maxCreationTime != null, p => p.CreationTime <= maxCreationTime) + .WhereIf(minCreationTime != null, p => p.CreationTime >= minCreationTime) + .WhereIf(maxModifitionTime != null, p => p.LastModificationTime <= maxModifitionTime) + .WhereIf(minModifitionTime != null, p => p.LastModificationTime >= minModifitionTime); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index 78838c9c6c..14514e0ab4 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -27,7 +27,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.ParentId == parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -38,7 +38,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -48,7 +48,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -58,7 +58,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Roles.Any(r => r.RoleId == roleId)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -68,7 +68,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => displayNames.Contains(x.DisplayName)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -80,10 +80,9 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(OrganizationUnit.CreationTime) + " desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -92,7 +91,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( ou => ou.DisplayName == displayName, @@ -110,11 +109,10 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => roleIds.Contains(r.Id)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityRole.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -126,17 +124,16 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); var roleIds = organizationUnits.SelectMany(ou => ou.Roles.Select(r => r.RoleId)).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => roleIds.Contains(r.Id)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityRole.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -146,7 +143,7 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(r => roleIds.Contains(r.Id)).CountAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(r => roleIds.Contains(r.Id)).CountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetUnaddedRolesAsync( @@ -160,12 +157,11 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityRole.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -176,10 +172,9 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) - .As>() .CountAsync(GetCancellationToken(cancellationToken)); } @@ -196,15 +191,14 @@ public class MongoOrganizationUnitRepository var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, cancellationToken); return await query .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(cancellationToken); } public virtual async Task> GetMemberIdsAsync(Guid id, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == id)).Select(x => x.Id) .ToListAsync(cancellationToken); } @@ -229,9 +223,9 @@ public class MongoOrganizationUnitRepository CancellationToken cancellationToken = default) { return await - (await GetMongoQueryableAsync(cancellationToken)) + (await GetQueryableAsync(cancellationToken)) .Where(u => !u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || @@ -239,24 +233,22 @@ public class MongoOrganizationUnitRepository (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetUnaddedUsersCountAsync(OrganizationUnit organizationUnit, string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => !u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || u.Email.Contains(filter) || (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) - .As>() .CountAsync(GetCancellationToken(cancellationToken)); } @@ -269,11 +261,10 @@ public class MongoOrganizationUnitRepository public virtual async Task RemoveAllMembersAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var userQueryable = await GetMongoQueryableAsync(cancellationToken); + var userQueryable = await GetQueryableAsync(cancellationToken); var dbContext = await GetDbContextAsync(cancellationToken); var users = await userQueryable .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .As>() .ToListAsync(cancellationToken); foreach (var user in users) @@ -283,14 +274,14 @@ public class MongoOrganizationUnitRepository } } - protected virtual async Task> CreateGetMembersFilteredQueryAsync( + protected virtual async Task> CreateGetMembersFilteredQueryAsync( OrganizationUnit organizationUnit, string filter = null, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj index cc463e1cc8..311ee9fa69 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj @@ -20,10 +20,10 @@ - - - - + + + + diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs index 732500214c..90b0f60b14 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.Identity.MongoDB; diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json index ee8a8e35db..096202cd42 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json @@ -3933,6 +3933,178 @@ "contentType": "repositoryInterface", "name": "IApiResourceRepository", "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.IdentityServer", + "subscribedEvents": [ + { + "underlyingType": { + "name": "Client", + "namespace": "Volo.Abp.IdentityServer.Clients", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.Clients.Client" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + }, + { + "underlyingType": { + "name": "ClientCorsOrigin", + "namespace": "Volo.Abp.IdentityServer.Clients", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.Clients.ClientCorsOrigin" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "AllowedCorsOriginsCacheItemInvalidator", + "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.IdentityServer", + "subscribedEvents": [ + { + "underlyingType": { + "name": "Client", + "namespace": "Volo.Abp.IdentityServer.Clients", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.Clients.Client" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + }, + { + "underlyingType": { + "name": "ClientCorsOrigin", + "namespace": "Volo.Abp.IdentityServer.Clients", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.Clients.ClientCorsOrigin" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + }, + { + "underlyingType": { + "name": "IdentityResource", + "namespace": "Volo.Abp.IdentityServer.IdentityResources", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.IdentityResources.IdentityResource" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + }, + { + "underlyingType": { + "name": "ApiResource", + "namespace": "Volo.Abp.IdentityServer.ApiResources", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.ApiResources.ApiResource" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + }, + { + "underlyingType": { + "name": "ApiScope", + "namespace": "Volo.Abp.IdentityServer.ApiScopes", + "declaringAssemblyName": "Volo.Abp.IdentityServer.Domain", + "fullName": "Volo.Abp.IdentityServer.ApiScopes.ApiScope" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "IdentityServerCacheItemInvalidator", + "summary": null } ] } \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs index a77cb01d8a..5259c31329 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs @@ -1,7 +1,9 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.BackgroundWorkers; +using Volo.Abp.DistributedLocking; using Volo.Abp.Threading; namespace Volo.Abp.IdentityServer.Tokens; @@ -9,24 +11,40 @@ namespace Volo.Abp.IdentityServer.Tokens; public class TokenCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase { protected TokenCleanupOptions Options { get; } + protected IAbpDistributedLock DistributedLock { get; } public TokenCleanupBackgroundWorker( AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, - IOptions options) + IOptions options, + IAbpDistributedLock distributedLock) : base( timer, serviceScopeFactory) { + DistributedLock = distributedLock; Options = options.Value; timer.Period = Options.CleanupPeriod; } protected async override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) { - await workerContext - .ServiceProvider - .GetRequiredService() - .CleanAsync(); + await using (var handle = await DistributedLock.TryAcquireAsync(nameof(TokenCleanupBackgroundWorker))) + { + Logger.LogInformation($"Lock is acquired for {nameof(TokenCleanupBackgroundWorker)}"); + + if (handle != null) + { + await workerContext + .ServiceProvider + .GetRequiredService() + .CleanAsync(); + + Logger.LogInformation($"Lock is released for {nameof(TokenCleanupBackgroundWorker)}"); + return; + } + + Logger.LogInformation($"Handle is null because of the locking for : {nameof(TokenCleanupBackgroundWorker)}"); + } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.abppkg.analyze.json b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.abppkg.analyze.json index 6e763e3e8b..1327d6382d 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,146 @@ { "namespace": "Volo.Abp.IdentityServer.EntityFrameworkCore", "connectionStringName": "AbpIdentityServer", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.IdentityServer.ApiResources.ApiResource", + "contentType": "databaseTable", + "name": "ApiResources", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiResources.ApiResourceSecret", + "contentType": "databaseTable", + "name": "ApiResourceSecrets", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", + "contentType": "databaseTable", + "name": "ApiResourceClaims", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiResources.ApiResourceScope", + "contentType": "databaseTable", + "name": "ApiResourceScopes", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiResources.ApiResourceProperty", + "contentType": "databaseTable", + "name": "ApiResourceProperties", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiScopes.ApiScope", + "contentType": "databaseTable", + "name": "ApiScopes", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiScopes.ApiScopeClaim", + "contentType": "databaseTable", + "name": "ApiScopeClaims", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.ApiScopes.ApiScopeProperty", + "contentType": "databaseTable", + "name": "ApiScopeProperties", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.IdentityResources.IdentityResource", + "contentType": "databaseTable", + "name": "IdentityResources", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.IdentityResources.IdentityResourceClaim", + "contentType": "databaseTable", + "name": "IdentityClaims", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.IdentityResources.IdentityResourceProperty", + "contentType": "databaseTable", + "name": "IdentityResourceProperties", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.Client", + "contentType": "databaseTable", + "name": "Clients", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientGrantType", + "contentType": "databaseTable", + "name": "ClientGrantTypes", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientRedirectUri", + "contentType": "databaseTable", + "name": "ClientRedirectUris", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", + "contentType": "databaseTable", + "name": "ClientPostLogoutRedirectUris", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientScope", + "contentType": "databaseTable", + "name": "ClientScopes", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientSecret", + "contentType": "databaseTable", + "name": "ClientSecrets", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientClaim", + "contentType": "databaseTable", + "name": "ClientClaims", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", + "contentType": "databaseTable", + "name": "ClientIdPRestrictions", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", + "contentType": "databaseTable", + "name": "ClientCorsOrigins", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Clients.ClientProperty", + "contentType": "databaseTable", + "name": "ClientProperties", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Grants.PersistedGrant", + "contentType": "databaseTable", + "name": "PersistedGrants", + "summary": null + }, + { + "entityFullName": "Volo.Abp.IdentityServer.Devices.DeviceFlowCodes", + "contentType": "databaseTable", + "name": "DeviceFlowCodes", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs index 24dc519a40..42379b44f9 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs @@ -20,7 +20,7 @@ public class MongoApiResourceRepository : MongoDbRepository FindByNameAsync(string apiResourceName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(ar => ar.Id) .FirstOrDefaultAsync(ar => ar.Name == apiResourceName, GetCancellationToken(cancellationToken)); } @@ -28,7 +28,7 @@ public class MongoApiResourceRepository : MongoDbRepository> FindByNameAsync(string[] apiResourceNames, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ar => apiResourceNames.Contains(ar.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -36,7 +36,7 @@ public class MongoApiResourceRepository : MongoDbRepository> GetListByScopesAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ar => ar.Scopes.Any(x => scopeNames.Contains(x.Scope))) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -44,21 +44,20 @@ public class MongoApiResourceRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(ApiResource.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -67,7 +66,7 @@ public class MongoApiResourceRepository : MongoDbRepository CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(ar => ar.Id != expectedId && ar.Name == name, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs index 01c1ecad07..760bd0522c 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs @@ -22,7 +22,7 @@ public class MongoApiScopeRepository : MongoDbRepository FindByNameAsync(string scopeName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(x => x.Name == scopeName, GetCancellationToken(cancellationToken)); } @@ -30,7 +30,7 @@ public class MongoApiScopeRepository : MongoDbRepository> GetListByNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(scope => scopeNames.Contains(scope.Name)) .OrderBy(scope => scope.Id) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -39,21 +39,20 @@ public class MongoApiScopeRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(ApiScope.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -62,7 +61,7 @@ public class MongoApiScopeRepository : MongoDbRepository CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(x => x.Id != expectedId && x.Name == name, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs index c7f81f51e2..d266ac7c52 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs @@ -26,7 +26,7 @@ public class MongoClientRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken)); } @@ -39,18 +39,17 @@ public class MongoClientRepository : MongoDbRepository x.ClientId.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(Client.ClientName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) .LongCountAsync(GetCancellationToken(cancellationToken)); } @@ -58,7 +57,7 @@ public class MongoClientRepository : MongoDbRepository> GetAllDistinctAllowedCorsOriginsAsync( CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .SelectMany(x => x.AllowedCorsOrigins) .Select(y => y.Origin) .Distinct() @@ -67,7 +66,7 @@ public class MongoClientRepository : MongoDbRepository CheckClientIdExistAsync(string clientId, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(c => c.Id != expectedId && c.ClientId == clientId, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs index 921225a5ae..65d74b975a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -23,7 +24,7 @@ public class MongoDeviceFlowCodesRepository : string userCode, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.UserCode == userCode) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -31,7 +32,7 @@ public class MongoDeviceFlowCodesRepository : public virtual async Task FindByDeviceCodeAsync(string deviceCode, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.DeviceCode == deviceCode) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -42,7 +43,7 @@ public class MongoDeviceFlowCodesRepository : int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs index faf3d66d96..9a3ee0f815 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs @@ -20,20 +20,19 @@ public class MongoIdentityResourceRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityResource.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -45,7 +44,7 @@ public class MongoIdentityResourceRepository : MongoDbRepository x.Name == name) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -54,14 +53,14 @@ public class MongoIdentityResourceRepository : MongoDbRepository> GetListByScopeNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ar => scopeNames.Contains(ar.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(ir => ir.Id != expectedId && ir.Name == name, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs index e3f3cc8368..4ac0844bbe 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs @@ -27,7 +27,7 @@ public class MongoPersistentGrantRepository : MongoDbRepository FindByKeyAsync(string key, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Key == key) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -35,7 +35,7 @@ public class MongoPersistentGrantRepository : MongoDbRepository> GetListBySubjectIdAsync(string subjectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.SubjectId == subjectId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -43,7 +43,7 @@ public class MongoPersistentGrantRepository : MongoDbRepository> GetListByExpirationAsync(DateTime maxExpirationDate, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) @@ -87,18 +87,17 @@ public class MongoPersistentGrantRepository : MongoDbRepository> FilterAsync( + private async Task> FilterAsync( string subjectId, string sessionId, string clientId, string type, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId) - .WhereIf>(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId) - .WhereIf>(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) - .WhereIf>(!type.IsNullOrWhiteSpace(), x => x.Type == type) - .As>(); + return (await GetQueryableAsync(cancellationToken)) + .WhereIf(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId) + .WhereIf(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId) + .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) + .WhereIf(!type.IsNullOrWhiteSpace(), x => x.Type == type); } } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj index d2d7bf8a0e..07377805af 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj @@ -20,10 +20,10 @@ - - - - + + + + diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs index 2f6d52d255..6611beb635 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.IdentityServer; diff --git a/modules/openiddict/app/OpenIddict.Demo.Client.Mvc/OpenIddict.Demo.Client.Mvc.abppkg.analyze.json b/modules/openiddict/app/OpenIddict.Demo.Client.Mvc/OpenIddict.Demo.Client.Mvc.abppkg.analyze.json new file mode 100644 index 0000000000..c14575a4ec --- /dev/null +++ b/modules/openiddict/app/OpenIddict.Demo.Client.Mvc/OpenIddict.Demo.Client.Mvc.abppkg.analyze.json @@ -0,0 +1,68 @@ +{ + "name": "OpenIddict.Demo.Client.Mvc", + "hash": "", + "contents": [ + { + "namespace": "OpenIddict.Demo.Client.Mvc", + "dependsOnModules": [ + { + "declaringAssemblyName": "Volo.Abp.AspNetCore.Mvc", + "namespace": "Volo.Abp.AspNetCore.Mvc", + "name": "AbpAspNetCoreMvcModule" + }, + { + "declaringAssemblyName": "Volo.Abp.AspNetCore.Authentication.OpenIdConnect", + "namespace": "Volo.Abp.AspNetCore.Authentication.OpenIdConnect", + "name": "AbpAspNetCoreAuthenticationOpenIdConnectModule" + } + ], + "implementingInterfaces": [ + { + "name": "IAbpModule", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IAbpModule" + }, + { + "name": "IOnPreApplicationInitialization", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IOnPreApplicationInitialization" + }, + { + "name": "IOnApplicationInitialization", + "namespace": "Volo.Abp", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.IOnApplicationInitialization" + }, + { + "name": "IOnPostApplicationInitialization", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IOnPostApplicationInitialization" + }, + { + "name": "IOnApplicationShutdown", + "namespace": "Volo.Abp", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.IOnApplicationShutdown" + }, + { + "name": "IPreConfigureServices", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IPreConfigureServices" + }, + { + "name": "IPostConfigureServices", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IPostConfigureServices" + } + ], + "contentType": "abpModule", + "name": "OpenIddictMvcModule", + "summary": null + } + ] +} \ No newline at end of file diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo.Abp.OpenIddict.EntityFrameworkCore.abppkg.analyze.json b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo.Abp.OpenIddict.EntityFrameworkCore.abppkg.analyze.json index 6978ff01a7..c00f6f067b 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo.Abp.OpenIddict.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo.Abp.OpenIddict.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,32 @@ { "namespace": "Volo.Abp.OpenIddict.EntityFrameworkCore", "connectionStringName": "AbpOpenIddict", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.OpenIddict.Applications.OpenIddictApplication", + "contentType": "databaseTable", + "name": "Applications", + "summary": null + }, + { + "entityFullName": "Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", + "contentType": "databaseTable", + "name": "Authorizations", + "summary": null + }, + { + "entityFullName": "Volo.Abp.OpenIddict.Scopes.OpenIddictScope", + "contentType": "databaseTable", + "name": "Scopes", + "summary": null + }, + { + "entityFullName": "Volo.Abp.OpenIddict.Tokens.OpenIddictToken", + "contentType": "databaseTable", + "name": "Tokens", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs index ad9064e8cf..867bbe71c5 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs @@ -21,50 +21,47 @@ public class MongoOpenIddictApplicationRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, CancellationToken cancellationToken = default) { - return await ((await GetMongoQueryableAsync(cancellationToken))) + return await ((await GetQueryableAsync(cancellationToken))) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictApplication.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await ((await GetMongoQueryableAsync(cancellationToken))) + return await ((await GetQueryableAsync(cancellationToken))) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(x => x.ClientId == clientId, cancellationToken); } public virtual async Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await query(await GetQueryableAsync(cancellationToken), state).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs index f4bd5f4817..87ed933f00 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs @@ -29,53 +29,52 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository> FindAsync(string subject, Guid? client, string status, string type, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!subject.IsNullOrWhiteSpace(), x => x.Subject == subject) .WhereIf(client.HasValue, x => x.ApplicationId == client) .WhereIf(!status.IsNullOrWhiteSpace(), x => x.Status == status) .WhereIf(!type.IsNullOrWhiteSpace(), x => x.Type == type) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(authorization => authorization.Id!) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>().ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task PruneAsync(DateTime date, CancellationToken cancellationToken = default) { - var tokenIds = await (await GetMongoQueryableAsync(cancellationToken)) + var tokenIds = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.AuthorizationId != null) .Select(x => x.AuthorizationId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); - var authorizations = await (await GetMongoQueryableAsync(cancellationToken)) + var authorizations = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.CreationDate < date) .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !tokenIds.Contains(x.Id))) .Select(x => x.Id) .ToListAsync(cancellationToken: cancellationToken); - var tokens = await (await GetMongoQueryableAsync(cancellationToken)) + var tokens = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.AuthorizationId != null && authorizations.Contains(x.AuthorizationId.Value)) .ToListAsync(cancellationToken: cancellationToken); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs index 3e16df4e9b..7323b3f272 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs @@ -21,61 +21,56 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.DisplayName.Contains(filter) || x.Description.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictScope.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.DisplayName.Contains(filter) || x.Description.Contains(filter)) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task FindByNameAsync(string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); } public virtual async Task> FindByNamesAsync(string[] names, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => names.Contains(x.Name)) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByResourceAsync(string resource, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.Resources.Contains(resource)) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs index 175b137515..2b2a9bec12 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs @@ -21,7 +21,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.ApplicationId == applicationId) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -31,7 +31,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.AuthorizationId == authorizationId) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -40,7 +40,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.AuthorizationId != null && authorizationIds.Contains(x.AuthorizationId.Value)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -49,67 +49,62 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository> FindAsync(string subject, Guid? client, string status, string type, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!subject.IsNullOrWhiteSpace(), x => x.Subject == subject) .WhereIf(client.HasValue, x => x.ApplicationId == client) .WhereIf(!status.IsNullOrWhiteSpace(), x => x.Status == status) .WhereIf(!type.IsNullOrWhiteSpace(), x => x.Type == type) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.ApplicationId == applicationId) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByAuthorizationIdAsync(Guid authorizationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.AuthorizationId == authorizationId) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task FindByReferenceIdAsync(string referenceId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); } public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.Subject == subject) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task PruneAsync(DateTime date, CancellationToken cancellationToken = default) { - var authorizationIds = await (await GetMongoQueryableAsync(cancellationToken)) + var authorizationIds = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Status != OpenIddictConstants.Statuses.Valid) .Select(x => x.Id) .ToListAsync(GetCancellationToken(cancellationToken)); - var tokens = await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + var tokens = await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.CreationDate < date) .Where(x => (x.Status != OpenIddictConstants.Statuses.Inactive && x.Status != OpenIddictConstants.Statuses.Valid) || diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj index 56512b464c..d5f8903293 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs index ddceaf8104..1716d478a5 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.OpenIddict.MongoDB; diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo.Abp.PermissionManagement.Domain.abppkg.analyze.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo.Abp.PermissionManagement.Domain.abppkg.analyze.json index a6f3e6528d..f65a774ef5 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo.Abp.PermissionManagement.Domain.abppkg.analyze.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo.Abp.PermissionManagement.Domain.abppkg.analyze.json @@ -605,6 +605,47 @@ "contentType": "repositoryInterface", "name": "IPermissionGroupDefinitionRecordRepository", "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.PermissionManagement", + "subscribedEvents": [ + { + "underlyingType": { + "name": "PermissionGrant", + "namespace": "Volo.Abp.PermissionManagement", + "declaringAssemblyName": "Volo.Abp.PermissionManagement.Domain", + "fullName": "Volo.Abp.PermissionManagement.PermissionGrant" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "PermissionGrantCacheItemInvalidator", + "summary": null } ] } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo.Abp.PermissionManagement.EntityFrameworkCore.abppkg.analyze.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo.Abp.PermissionManagement.EntityFrameworkCore.abppkg.analyze.json index 099ce4d6cc..769b7bf6c4 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo.Abp.PermissionManagement.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.EntityFrameworkCore/Volo.Abp.PermissionManagement.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,26 @@ { "namespace": "Volo.Abp.PermissionManagement.EntityFrameworkCore", "connectionStringName": "AbpPermissionManagement", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", + "contentType": "databaseTable", + "name": "PermissionGroups", + "summary": null + }, + { + "entityFullName": "Volo.Abp.PermissionManagement.PermissionDefinitionRecord", + "contentType": "databaseTable", + "name": "Permissions", + "summary": null + }, + { + "entityFullName": "Volo.Abp.PermissionManagement.PermissionGrant", + "contentType": "databaseTable", + "name": "PermissionGrants", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo.Abp.PermissionManagement.HttpApi.abppkg.analyze.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo.Abp.PermissionManagement.HttpApi.abppkg.analyze.json index 951b30cdbd..4268835513 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo.Abp.PermissionManagement.HttpApi.abppkg.analyze.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.HttpApi/Volo.Abp.PermissionManagement.HttpApi.abppkg.analyze.json @@ -63,51 +63,6 @@ "contentType": "abpModule", "name": "AbpPermissionManagementHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/permission-management/permissions", - "method": "GET", - "groupName": "Permissions", - "responseType": "Volo.Abp.PermissionManagement.GetPermissionListResultDto", - "responseTypeAsJson": "{\r\n \"entityDisplayName\": \"string\",\r\n \"groups\": [\r\n {\r\n \"name\": \"string\",\r\n \"displayName\": \"string\",\r\n \"displayNameKey\": \"string\",\r\n \"displayNameResource\": \"string\",\r\n \"permissions\": [\r\n {\r\n \"name\": \"string\",\r\n \"displayName\": \"string\",\r\n \"parentName\": \"string\",\r\n \"isGranted\": false,\r\n \"allowedProviders\": [\r\n \"string\"\r\n ],\r\n \"grantedProviders\": [\r\n {\r\n \"providerName\": \"string\",\r\n \"providerKey\": \"string\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n ]\r\n}", - "parameterDescriptions": [ - { - "name": "providerName", - "type": "String" - }, - { - "name": "providerKey", - "type": "String" - } - ] - }, - { - "path": "api/permission-management/permissions", - "method": "PUT", - "groupName": "Permissions", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "providerName", - "type": "String" - }, - { - "name": "providerKey", - "type": "String" - }, - { - "name": "input", - "type": "UpdatePermissionsDto" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs index 529f56511c..2f98db4f60 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -22,7 +23,7 @@ public class MongoPermissionDefinitionRecordRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( s => s.Name == name, diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs index aa7694b7d5..d83d916890 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs @@ -27,7 +27,7 @@ public class MongoPermissionGrantRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && @@ -43,7 +43,7 @@ public class MongoPermissionGrantRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey @@ -54,7 +54,7 @@ public class MongoPermissionGrantRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => names.Contains(s.Name) && s.ProviderName == providerName && diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj index 757b0f164c..0f9e0169e8 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj @@ -19,10 +19,10 @@ - - - - + + + + diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs index fc039d7ee2..05fae7288c 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.PermissionManagement.MongoDB; diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo.Abp.SettingManagement.Application.abppkg.analyze.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo.Abp.SettingManagement.Application.abppkg.analyze.json index 47160bc535..8123cb38d9 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo.Abp.SettingManagement.Application.abppkg.analyze.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo.Abp.SettingManagement.Application.abppkg.analyze.json @@ -84,6 +84,47 @@ "name": "AbpSettingManagementApplicationModule", "summary": null }, + { + "eventHandlerType": "Distributed", + "namespace": "Volo.Abp.SettingManagement", + "subscribedEvents": [ + { + "underlyingType": { + "name": "UserEto", + "namespace": "Volo.Abp.Users", + "declaringAssemblyName": "Volo.Abp.Users.Abstractions", + "fullName": "Volo.Abp.Users.UserEto" + }, + "name": "EntityDeletedEto`1", + "namespace": "Volo.Abp.Domain.Entities.Events.Distributed", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain.Shared", + "fullName": "Volo.Abp.Domain.Entities.Events.Distributed.EntityDeletedEto`1" + } + ], + "implementingInterfaces": [ + { + "name": "IDistributedEventHandler", + "namespace": "Volo.Abp.EventBus.Distributed", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.Distributed.IDistributedEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "UserDeletedEventHandler", + "summary": null + }, { "namespace": "Volo.Abp.SettingManagement", "baseClass": { diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.abppkg.analyze.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.abppkg.analyze.json index c3b545a078..33a15e01ee 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.abppkg.analyze.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.abppkg.analyze.json @@ -494,6 +494,47 @@ "contentType": "repositoryInterface", "name": "ISettingRepository", "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.SettingManagement", + "subscribedEvents": [ + { + "underlyingType": { + "name": "Setting", + "namespace": "Volo.Abp.SettingManagement", + "declaringAssemblyName": "Volo.Abp.SettingManagement.Domain", + "fullName": "Volo.Abp.SettingManagement.Setting" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "SettingCacheItemInvalidator", + "summary": null } ] } \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.abppkg.analyze.json b/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.abppkg.analyze.json index 82d123d7cf..fa1bfc4143 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,20 @@ { "namespace": "Volo.Abp.SettingManagement.EntityFrameworkCore", "connectionStringName": "AbpSettingManagement", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.SettingManagement.Setting", + "contentType": "databaseTable", + "name": "Settings", + "summary": null + }, + { + "entityFullName": "Volo.Abp.SettingManagement.SettingDefinitionRecord", + "contentType": "databaseTable", + "name": "SettingDefinitionRecords", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi/Volo.Abp.SettingManagement.HttpApi.abppkg.analyze.json b/modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi/Volo.Abp.SettingManagement.HttpApi.abppkg.analyze.json index c448c0450e..3e70901871 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi/Volo.Abp.SettingManagement.HttpApi.abppkg.analyze.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi/Volo.Abp.SettingManagement.HttpApi.abppkg.analyze.json @@ -63,76 +63,6 @@ "contentType": "abpModule", "name": "AbpSettingManagementHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/setting-management/emailing", - "method": "GET", - "groupName": "EmailSettings", - "responseType": "Volo.Abp.SettingManagement.EmailSettingsDto", - "responseTypeAsJson": "{\r\n \"smtpHost\": \"string\",\r\n \"smtpPort\": 0,\r\n \"smtpUserName\": \"string\",\r\n \"smtpPassword\": \"string\",\r\n \"smtpDomain\": \"string\",\r\n \"smtpEnableSsl\": false,\r\n \"smtpUseDefaultCredentials\": false,\r\n \"defaultFromAddress\": \"string\",\r\n \"defaultFromDisplayName\": \"string\"\r\n}", - "parameterDescriptions": [] - }, - { - "path": "api/setting-management/emailing", - "method": "POST", - "groupName": "EmailSettings", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "UpdateEmailSettingsDto" - } - ] - }, - { - "path": "api/setting-management/emailing/send-test-email", - "method": "POST", - "groupName": "EmailSettings", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "SendTestEmailInput" - } - ] - }, - { - "path": "api/setting-management/timezone", - "method": "GET", - "groupName": "TimeZoneSettings", - "responseType": "System.String", - "responseTypeAsJson": "\"string\"", - "parameterDescriptions": [] - }, - { - "path": "api/setting-management/timezone/timezones", - "method": "GET", - "groupName": "TimeZoneSettings", - "responseType": "System.Collections.Generic.List`1[Volo.Abp.NameValue]", - "responseTypeAsJson": "[\r\n {\r\n \"name\": \"string\",\r\n \"value\": \"string\"\r\n }\r\n]", - "parameterDescriptions": [] - }, - { - "path": "api/setting-management/timezone", - "method": "POST", - "groupName": "TimeZoneSettings", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "timezone", - "type": "String" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs index d2500cccd2..3ea0206759 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -16,7 +17,7 @@ public class MongoSettingDefinitionRecordRepository : MongoDbRepository FindByNameAsync(string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name, GetCancellationToken(cancellationToken)); } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs index 74c680e7e2..ea264b254e 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs @@ -24,7 +24,7 @@ public class MongoSettingRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync( s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, @@ -36,7 +36,7 @@ public class MongoSettingRepository : MongoDbRepository s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -47,7 +47,7 @@ public class MongoSettingRepository : MongoDbRepository names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj index 65ea9436ee..9c2c2f36a9 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs index 625b66b328..bc5feb98b1 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.SettingManagement.MongoDB; diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo.Abp.TenantManagement.Domain.abppkg.analyze.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo.Abp.TenantManagement.Domain.abppkg.analyze.json index aeb603a65d..d35d66ab49 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo.Abp.TenantManagement.Domain.abppkg.analyze.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo.Abp.TenantManagement.Domain.abppkg.analyze.json @@ -614,6 +614,60 @@ "contentType": "repositoryInterface", "name": "ITenantRepository", "summary": null + }, + { + "eventHandlerType": "Local", + "namespace": "Volo.Abp.TenantManagement", + "subscribedEvents": [ + { + "underlyingType": { + "name": "Tenant", + "namespace": "Volo.Abp.TenantManagement", + "declaringAssemblyName": "Volo.Abp.TenantManagement.Domain", + "fullName": "Volo.Abp.TenantManagement.Tenant" + }, + "name": "EntityChangedEventData`1", + "namespace": "Volo.Abp.Domain.Entities.Events", + "declaringAssemblyName": "Volo.Abp.Ddd.Domain", + "fullName": "Volo.Abp.Domain.Entities.Events.EntityChangedEventData`1" + }, + { + "underlyingType": null, + "name": "TenantChangedEvent", + "namespace": "Volo.Abp.MultiTenancy", + "declaringAssemblyName": "Volo.Abp.MultiTenancy.Abstractions", + "fullName": "Volo.Abp.MultiTenancy.TenantChangedEvent" + } + ], + "implementingInterfaces": [ + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "IEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.IEventHandler" + }, + { + "name": "ILocalEventHandler", + "namespace": "Volo.Abp.EventBus", + "declaringAssemblyName": "Volo.Abp.EventBus.Abstractions", + "fullName": "Volo.Abp.EventBus.ILocalEventHandler" + }, + { + "name": "ITransientDependency", + "namespace": "Volo.Abp.DependencyInjection", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.DependencyInjection.ITransientDependency" + } + ], + "contentType": "eventHandler", + "name": "TenantConfigurationCacheItemInvalidator", + "summary": null } ] } \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo.Abp.TenantManagement.EntityFrameworkCore.abppkg.analyze.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo.Abp.TenantManagement.EntityFrameworkCore.abppkg.analyze.json index 9fa4137df7..5b66280917 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo.Abp.TenantManagement.EntityFrameworkCore.abppkg.analyze.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo.Abp.TenantManagement.EntityFrameworkCore.abppkg.analyze.json @@ -67,7 +67,20 @@ { "namespace": "Volo.Abp.TenantManagement.EntityFrameworkCore", "connectionStringName": "AbpTenantManagement", - "databaseTables": [], + "databaseTables": [ + { + "entityFullName": "Volo.Abp.TenantManagement.Tenant", + "contentType": "databaseTable", + "name": "Tenants", + "summary": null + }, + { + "entityFullName": "Volo.Abp.TenantManagement.TenantConnectionString", + "contentType": "databaseTable", + "name": "TenantConnectionStrings", + "summary": null + } + ], "replacedDbContexts": [], "modelBuilderExtensionMethods": [ { diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo.Abp.TenantManagement.HttpApi.abppkg.analyze.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo.Abp.TenantManagement.HttpApi.abppkg.analyze.json index 43cb2a091f..2dd6769ce4 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo.Abp.TenantManagement.HttpApi.abppkg.analyze.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo.Abp.TenantManagement.HttpApi.abppkg.analyze.json @@ -68,137 +68,6 @@ "contentType": "abpModule", "name": "AbpTenantManagementHttpApiModule", "summary": null - }, - { - "apis": [ - { - "path": "api/multi-tenancy/tenants/{id}", - "method": "GET", - "groupName": "Tenant", - "responseType": "Volo.Abp.TenantManagement.TenantDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/multi-tenancy/tenants", - "method": "GET", - "groupName": "Tenant", - "responseType": "Volo.Abp.Application.Dtos.PagedResultDto`1[Volo.Abp.TenantManagement.TenantDto]", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "Filter", - "type": "String" - }, - { - "name": "Sorting", - "type": "String" - }, - { - "name": "SkipCount", - "type": "Int32" - }, - { - "name": "MaxResultCount", - "type": "Int32" - } - ] - }, - { - "path": "api/multi-tenancy/tenants", - "method": "POST", - "groupName": "Tenant", - "responseType": "Volo.Abp.TenantManagement.TenantDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "input", - "type": "TenantCreateDto" - } - ] - }, - { - "path": "api/multi-tenancy/tenants/{id}", - "method": "PUT", - "groupName": "Tenant", - "responseType": "Volo.Abp.TenantManagement.TenantDto", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "input", - "type": "TenantUpdateDto" - } - ] - }, - { - "path": "api/multi-tenancy/tenants/{id}", - "method": "DELETE", - "groupName": "Tenant", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/multi-tenancy/tenants/{id}/default-connection-string", - "method": "GET", - "groupName": "Tenant", - "responseType": "System.String", - "responseTypeAsJson": "\"string\"", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - }, - { - "path": "api/multi-tenancy/tenants/{id}/default-connection-string", - "method": "PUT", - "groupName": "Tenant", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - }, - { - "name": "defaultConnectionString", - "type": "String" - } - ] - }, - { - "path": "api/multi-tenancy/tenants/{id}/default-connection-string", - "method": "DELETE", - "groupName": "Tenant", - "responseType": "System.Void", - "responseTypeAsJson": "", - "parameterDescriptions": [ - { - "name": "id", - "type": "Guid" - } - ] - } - ], - "contentType": "httpApi", - "name": "Defined Http Apis", - "summary": null } ] } \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs index 049dc5e57c..758ece4d71 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs @@ -24,21 +24,21 @@ public class MongoTenantRepository : MongoDbRepository t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken)); } [Obsolete("Use FindByNameAsync method.")] public virtual Tenant FindByName(string normalizedName, bool includeDetails = true) { - return GetMongoQueryable() + return GetQueryable() .FirstOrDefault(t => t.NormalizedName == normalizedName); } [Obsolete("Use FindAsync method.")] public virtual Tenant FindById(Guid id, bool includeDetails = true) { - return GetMongoQueryable() + return GetQueryable() .FirstOrDefault(t => t.Id == id); } @@ -50,22 +50,21 @@ public class MongoTenantRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) ) .OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj index c22da31998..2913a0ed53 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs index 7b12dc33e7..4610234bf6 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; using MongoDB.Driver; using Volo.Abp.MongoDB; diff --git a/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs b/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs index d0e1e76873..2e657227b1 100644 --- a/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs +++ b/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs @@ -24,7 +24,7 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi public virtual async Task FindByUserNameAsync(string userName, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(u => u.UserName == userName, cancellationToken); } @@ -32,7 +32,7 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => ids.Contains(u.Id)) .ToListAsync(cancellationToken); } @@ -45,8 +45,8 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || @@ -55,16 +55,15 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi (u.Surname != null && u.Surname.Contains(filter)) ) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IUserData.UserName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(cancellationToken); } public async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || diff --git a/npm/ng-packs/migrations.json b/npm/ng-packs/migrations.json index 6fb305ede9..e89bc86d78 100644 --- a/npm/ng-packs/migrations.json +++ b/npm/ng-packs/migrations.json @@ -1,159 +1,19 @@ { "migrations": [ { - "version": "20.0.0-beta.7", - "description": "Migration for v20.0.0-beta.7", - "implementation": "./src/migrations/update-20-0-0/move-use-daemon-process", - "package": "nx", - "name": "move-use-daemon-process" - }, - { - "version": "20.0.1", - "description": "Set `useLegacyCache` to true for migrating workspaces", - "implementation": "./src/migrations/update-20-0-1/use-legacy-cache", - "x-repair-skip": true, - "package": "nx", - "name": "use-legacy-cache" - }, - { - "version": "20.2.0-beta.5", - "description": "Update TypeScript ESLint packages to v8.13.0 if they are already on v8", - "implementation": "./src/migrations/update-20-2-0/update-typescript-eslint-v8-13-0", + "version": "20.3.0-beta.1", + "description": "Update ESLint flat config to include .cjs, .mjs, .cts, and .mts files in overrides (if needed)", + "implementation": "./src/migrations/update-20-3-0/add-file-extensions-to-overrides", "package": "@nx/eslint", - "name": "update-typescript-eslint-v8.13.0" - }, - { - "cli": "nx", - "version": "19.6.0-beta.4", - "description": "Update ciWebServerCommand to use static serve for the application.", - "implementation": "./src/migrations/update-19-6-0/update-ci-webserver-for-static-serve", - "package": "@nx/cypress", - "name": "update-19-6-0-update-ci-webserver-for-vite" - }, - { - "cli": "nx", - "version": "20.0.0-beta.5", - "description": "replace getJestProjects with getJestProjectsAsync", - "implementation": "./src/migrations/update-20-0-0/replace-getJestProjects-with-getJestProjectsAsync", - "package": "@nx/jest", - "name": "replace-getJestProjects-with-getJestProjectsAsync" - }, - { - "cli": "nx", - "version": "19.6.0-beta.4", - "description": "Ensure Module Federation DTS is turned off by default.", - "factory": "./src/migrations/update-19-6-0/turn-off-dts-by-default", - "package": "@nx/angular", - "name": "update-19-6-0" - }, - { - "cli": "nx", - "version": "19.6.0-beta.7", - "requires": { "@angular/core": ">=18.2.0" }, - "description": "Update the @angular/cli package version to ~18.2.0.", - "factory": "./src/migrations/update-19-6-0/update-angular-cli", - "package": "@nx/angular", - "name": "update-angular-cli-version-18-2-0" - }, - { - "cli": "nx", - "version": "19.6.1-beta.0", - "description": "Ensure Target Defaults are set correctly for Module Federation.", - "factory": "./src/migrations/update-19-6-1/ensure-depends-on-for-mf", - "package": "@nx/angular", - "name": "update-19-6-1-ensure-module-federation-target-defaults" - }, - { - "cli": "nx", - "version": "20.2.0-beta.2", - "description": "Update the ModuleFederationConfig import use @nx/module-federation.", - "factory": "./src/migrations/update-20-2-0/migrate-mf-imports-to-new-package", - "package": "@nx/angular", - "name": "update-20-2-0-update-module-federation-config-import" - }, - { - "cli": "nx", - "version": "20.2.0-beta.2", - "description": "Update the withModuleFederation import use @nx/module-federation/angular.", - "factory": "./src/migrations/update-20-2-0/migrate-with-mf-import-to-new-package", - "package": "@nx/angular", - "name": "update-20-2-0-update-with-module-federation-import" - }, - { - "cli": "nx", - "version": "20.2.0-beta.5", - "requires": { "@angular/core": ">=19.0.0" }, - "description": "Update the @angular/cli package version to ~19.0.0.", - "factory": "./src/migrations/update-20-2-0/update-angular-cli", - "package": "@nx/angular", - "name": "update-angular-cli-version-19-0-0" - }, - { - "cli": "nx", - "version": "20.2.0-beta.5", - "requires": { "@angular/core": ">=19.0.0" }, - "description": "Add the '@angular/localize/init' polyfill to the 'polyfills' option of targets using esbuild-based executors.", - "factory": "./src/migrations/update-20-2-0/add-localize-polyfill-to-targets", - "package": "@nx/angular", - "name": "add-localize-polyfill-to-targets" - }, - { - "cli": "nx", - "version": "20.2.0-beta.5", - "requires": { "@angular/core": ">=19.0.0" }, - "description": "Update '@angular/ssr' import paths to use the new '/node' entry point when 'CommonEngine' is detected.", - "factory": "./src/migrations/update-20-2-0/update-angular-ssr-imports-to-use-node-entry-point", - "package": "@nx/angular", - "name": "update-angular-ssr-imports-to-use-node-entry-point" + "name": "add-file-extensions-to-overrides" }, { "cli": "nx", - "version": "20.2.0-beta.6", - "requires": { "@angular/core": ">=19.0.0" }, - "description": "Disable the Angular ESLint prefer-standalone rule if not set.", - "factory": "./src/migrations/update-20-2-0/disable-angular-eslint-prefer-standalone", + "version": "20.3.0-beta.2", + "description": "If workspace includes Module Federation projects, ensure the new @nx/module-federation package is installed.", + "factory": "./src/migrations/update-20-3-0/ensure-nx-module-federation-package", "package": "@nx/angular", - "name": "disable-angular-eslint-prefer-standalone" - }, - { - "cli": "nx", - "version": "20.2.0-beta.8", - "requires": { "@angular/core": ">=19.0.0" }, - "description": "Remove Angular ESLint rules that were removed in v19.0.0.", - "factory": "./src/migrations/update-20-2-0/remove-angular-eslint-rules", - "package": "@nx/angular", - "name": "remove-angular-eslint-rules" - }, - { - "cli": "nx", - "version": "20.2.0-beta.8", - "requires": { "@angular/core": ">=19.0.0" }, - "description": "Remove the deprecated 'tailwindConfig' option from ng-packagr executors. Tailwind CSS configurations located at the project or workspace root will be picked up automatically.", - "factory": "./src/migrations/update-20-2-0/remove-tailwind-config-from-ng-packagr-executors", - "package": "@nx/angular", - "name": "remove-tailwind-config-from-ng-packagr-executors" - }, - { - "version": "19.0.0", - "description": "Updates non-standalone Directives, Component and Pipes to 'standalone:false' and removes 'standalone:true' from those who are standalone", - "factory": "./bundles/explicit-standalone-flag#migrate", - "package": "@angular/core", - "name": "explicit-standalone-flag" - }, - { - "version": "19.0.0", - "description": "Updates ExperimentalPendingTasks to PendingTasks", - "factory": "./bundles/pending-tasks#migrate", - "package": "@angular/core", - "name": "pending-tasks" - }, - { - "version": "19.0.0", - "description": "Replaces `APP_INITIALIZER`, `ENVIRONMENT_INITIALIZER` & `PLATFORM_INITIALIZER` respectively with `provideAppInitializer`, `provideEnvironmentInitializer` & `providePlatformInitializer`.", - "factory": "./bundles/provide-initializer#migrate", - "optional": true, - "package": "@angular/core", - "name": "provide-initializer" + "name": "ensure-nx-module-federation-package" } ] } diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index dfb3bc458e..3046c6abde 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -46,38 +46,38 @@ "devDependencies": { "@abp/ng.theme.lepton-x": "~4.1.0-rc.1", "@abp/utils": "~9.1.0-rc.1", - "@angular-devkit/build-angular": "~19.0.0", - "@angular-devkit/core": "~19.0.0", - "@angular-devkit/schematics": "~19.0.0", - "@angular-devkit/schematics-cli": "~19.0.0", + "@angular-devkit/build-angular": "~19.1.0", + "@angular-devkit/core": "~19.1.0", + "@angular-devkit/schematics": "~19.1.0", + "@angular-devkit/schematics-cli": "~19.1.0", "@angular-eslint/eslint-plugin": "~19.0.0", "@angular-eslint/eslint-plugin-template": "~19.0.0", "@angular-eslint/template-parser": "~19.0.0", - "@angular/animations": "~19.0.0", - "@angular/cli": "~19.0.0", - "@angular/common": "~19.0.0", - "@angular/compiler": "~19.0.0", - "@angular/compiler-cli": "~19.0.0", - "@angular/core": "~19.0.0", - "@angular/forms": "~19.0.0", - "@angular/language-service": "~19.0.0", - "@angular/localize": "~19.0.0", - "@angular/platform-browser": "~19.0.0", - "@angular/platform-browser-dynamic": "~19.0.0", - "@angular/router": "~19.0.0", + "@angular/animations": "~19.1.0", + "@angular/cli": "~19.1.0", + "@angular/common": "~19.1.0", + "@angular/compiler": "~19.1.0", + "@angular/compiler-cli": "~19.1.0", + "@angular/core": "~19.1.0", + "@angular/forms": "~19.1.0", + "@angular/language-service": "~19.1.0", + "@angular/localize": "~19.1.0", + "@angular/platform-browser": "~19.1.0", + "@angular/platform-browser-dynamic": "~19.1.0", + "@angular/router": "~19.1.0", "@fortawesome/fontawesome-free": "^6.0.0", - "@ng-bootstrap/ng-bootstrap": "~18.0.0-rc.0", + "@ng-bootstrap/ng-bootstrap": "~18.0.0", "@ngneat/spectator": "~19.1.0", "@ngx-validate/core": "^0.2.0", - "@nx/angular": "~20.2.0", - "@nx/cypress": "~20.2.0", - "@nx/devkit": "~20.2.0", - "@nx/eslint": "~20.2.0", - "@nx/eslint-plugin": "~20.2.0", - "@nx/jest": "~20.2.0", - "@nx/js": "~20.2.0", - "@nx/plugin": "~20.2.0", - "@nx/workspace": "~20.2.0", + "@nx/angular": "~20.3.0", + "@nx/cypress": "~20.3.0", + "@nx/devkit": "~20.3.0", + "@nx/eslint": "~20.3.0", + "@nx/eslint-plugin": "~20.3.0", + "@nx/jest": "~20.3.0", + "@nx/js": "~20.3.0", + "@nx/plugin": "~20.3.0", + "@nx/workspace": "~20.3.0", "@popperjs/core": "~2.11.0", "@schematics/angular": "~19.0.0", "@swc-node/register": "1.9.2", @@ -111,9 +111,9 @@ "just-compare": "^2.0.0", "lerna": "^4.0.0", "lint-staged": "^13.0.0", - "ng-packagr": "~19.0.0", + "ng-packagr": "~19.1.0", "ng-zorro-antd": "^19.0.0-beta.0", - "nx": "~20.2.0", + "nx": "~20.3.0", "postcss": "^8.0.0", "postcss-import": "14.1.0", "postcss-preset-env": "7.5.0", diff --git a/npm/ng-packs/packages/components/package.json b/npm/ng-packs/packages/components/package.json index 63463950a8..45770d0a33 100644 --- a/npm/ng-packs/packages/components/package.json +++ b/npm/ng-packs/packages/components/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "chart.js": "^3.5.1", - "ng-zorro-antd": "^17.0.0", + "ng-zorro-antd": "^19.0.0-beta.0", "@ctrl/tinycolor": "^4.0.0", "tslib": "^2.0.0" }, diff --git a/npm/ng-packs/packages/schematics/package.json b/npm/ng-packs/packages/schematics/package.json index 361bf77604..c0358c2abc 100644 --- a/npm/ng-packs/packages/schematics/package.json +++ b/npm/ng-packs/packages/schematics/package.json @@ -4,16 +4,16 @@ "author": "", "schematics": "./collection.json", "dependencies": { - "@angular-devkit/core": "~19.0.0", - "@angular-devkit/schematics": "~19.0.0", - "@angular/cli": "~19.0.0", + "@angular-devkit/core": "~19.1.0", + "@angular-devkit/schematics": "~19.1.0", + "@angular/cli": "~19.1.0", "got": "^11.5.2", "jsonc-parser": "^2.3.0", "should-quote": "^1.0.0", "typescript": "~5.6.0" }, "devDependencies": { - "@schematics/angular": "~19.0.0", + "@schematics/angular": "~19.1.0", "@types/jest": "29.4.4", "@types/node": "20.2.5", "jest": "29.4.3", diff --git a/npm/ng-packs/packages/schematics/src/utils/model.ts b/npm/ng-packs/packages/schematics/src/utils/model.ts index 20055a96c3..a1485858d4 100644 --- a/npm/ng-packs/packages/schematics/src/utils/model.ts +++ b/npm/ng-packs/packages/schematics/src/utils/model.ts @@ -148,7 +148,7 @@ export function createImportRefToInterfaceReducerCreator(params: ModelGeneratorP typeDef.properties?.forEach(prop => { let name = prop.jsonName || camel(prop.name); name = shouldQuote(name) ? `'${name}'` : name; - const type = simplifyType(prop.typeSimple); + const type = simplifyType(prop.type); const refs = parseType(prop.type).reduce( (acc: string[], r) => acc.concat(parseGenerics(r).toGenerics()), [], @@ -182,7 +182,7 @@ export function createRefToImportReducerCreator(params: ModelGeneratorParams) { } function isOptionalProperty(prop: PropertyDef) { - return prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && !prop.isRequired); + return prop.typeSimple.endsWith('?') || !prop.isRequired; } export function parseBaseTypeWithGenericTypes(type: string): string[] { diff --git a/npm/ng-packs/packages/theme-shared/package.json b/npm/ng-packs/packages/theme-shared/package.json index b8376770b7..f1f78d5cd5 100644 --- a/npm/ng-packs/packages/theme-shared/package.json +++ b/npm/ng-packs/packages/theme-shared/package.json @@ -9,7 +9,7 @@ "dependencies": { "@abp/ng.core": "~9.1.0-rc.1", "@fortawesome/fontawesome-free": "^5.0.0", - "@ng-bootstrap/ng-bootstrap": "~17.0.0", + "@ng-bootstrap/ng-bootstrap": "~18.0.0", "@ngx-validate/core": "^0.2.0", "@popperjs/core": "~2.11.0", "@swimlane/ngx-datatable": "^20.0.0", diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json index bbd90971f9..fc77c3a467 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json @@ -24,8 +24,7 @@ "@abp/moment": "~9.1.0-rc.1", "@abp/select2": "~9.1.0-rc.1", "@abp/sweetalert2": "~9.1.0-rc.1", - "@abp/timeago": "~9.1.0-rc.1", - "@abp/toastr": "~9.1.0-rc.1" + "@abp/timeago": "~9.1.0-rc.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/templates/app-nolayers/angular/package.json b/templates/app-nolayers/angular/package.json index d5c530a12a..5d35381f99 100644 --- a/templates/app-nolayers/angular/package.json +++ b/templates/app-nolayers/angular/package.json @@ -21,15 +21,15 @@ "@abp/ng.tenant-management": "~9.1.0-rc.1", "@abp/ng.theme.lepton-x": "~4.1.0-rc.1", "@abp/ng.theme.shared": "~9.1.0-rc.1", - "@angular/animations": "~19.0.0", - "@angular/common": "~19.0.0", - "@angular/compiler": "~19.0.0", - "@angular/core": "~19.0.0", - "@angular/forms": "~19.0.0", - "@angular/localize": "~19.0.0", - "@angular/platform-browser": "~19.0.0", - "@angular/platform-browser-dynamic": "~19.0.0", - "@angular/router": "~19.0.0", + "@angular/animations": "~19.1.0", + "@angular/common": "~19.1.0", + "@angular/compiler": "~19.1.0", + "@angular/core": "~19.1.0", + "@angular/forms": "~19.1.0", + "@angular/localize": "~19.1.0", + "@angular/platform-browser": "~19.1.0", + "@angular/platform-browser-dynamic": "~19.1.0", + "@angular/router": "~19.1.0", "bootstrap-icons": "~1.8.0", "rxjs": "~7.8.0", "tslib": "^2.0.0", @@ -37,15 +37,15 @@ }, "devDependencies": { "@abp/ng.schematics": "~9.1.0-rc.1", - "@angular-devkit/build-angular": "~19.0.0", + "@angular-devkit/build-angular": "~19.1.0", "@angular-eslint/builder": "~19.0.0", "@angular-eslint/eslint-plugin": "~19.0.0", "@angular-eslint/eslint-plugin-template": "~19.0.0", "@angular-eslint/schematics": "~19.0.0", "@angular-eslint/template-parser": "~19.0.0", - "@angular/cli": "~19.0.0", - "@angular/compiler-cli": "~19.0.0", - "@angular/language-service": "~19.0.0", + "@angular/cli": "~19.1.0", + "@angular/compiler-cli": "~19.1.0", + "@angular/language-service": "~19.1.0", "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "7.16.0", diff --git a/templates/app/angular/package.json b/templates/app/angular/package.json index d5c530a12a..5d35381f99 100644 --- a/templates/app/angular/package.json +++ b/templates/app/angular/package.json @@ -21,15 +21,15 @@ "@abp/ng.tenant-management": "~9.1.0-rc.1", "@abp/ng.theme.lepton-x": "~4.1.0-rc.1", "@abp/ng.theme.shared": "~9.1.0-rc.1", - "@angular/animations": "~19.0.0", - "@angular/common": "~19.0.0", - "@angular/compiler": "~19.0.0", - "@angular/core": "~19.0.0", - "@angular/forms": "~19.0.0", - "@angular/localize": "~19.0.0", - "@angular/platform-browser": "~19.0.0", - "@angular/platform-browser-dynamic": "~19.0.0", - "@angular/router": "~19.0.0", + "@angular/animations": "~19.1.0", + "@angular/common": "~19.1.0", + "@angular/compiler": "~19.1.0", + "@angular/core": "~19.1.0", + "@angular/forms": "~19.1.0", + "@angular/localize": "~19.1.0", + "@angular/platform-browser": "~19.1.0", + "@angular/platform-browser-dynamic": "~19.1.0", + "@angular/router": "~19.1.0", "bootstrap-icons": "~1.8.0", "rxjs": "~7.8.0", "tslib": "^2.0.0", @@ -37,15 +37,15 @@ }, "devDependencies": { "@abp/ng.schematics": "~9.1.0-rc.1", - "@angular-devkit/build-angular": "~19.0.0", + "@angular-devkit/build-angular": "~19.1.0", "@angular-eslint/builder": "~19.0.0", "@angular-eslint/eslint-plugin": "~19.0.0", "@angular-eslint/eslint-plugin-template": "~19.0.0", "@angular-eslint/schematics": "~19.0.0", "@angular-eslint/template-parser": "~19.0.0", - "@angular/cli": "~19.0.0", - "@angular/compiler-cli": "~19.0.0", - "@angular/language-service": "~19.0.0", + "@angular/cli": "~19.1.0", + "@angular/compiler-cli": "~19.1.0", + "@angular/language-service": "~19.1.0", "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "7.16.0", diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs index 55387d7ba5..e69539eff8 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace MyCompanyName.MyProjectName.MongoDB; diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs index 9f51c616ec..f705959e83 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs @@ -32,7 +32,7 @@ public class SampleRepositoryTests : MyProjectNameMongoDbTestBase await WithUnitOfWorkAsync(async () => { //Act - var adminUser = await (await _appUserRepository.GetMongoQueryableAsync()) + var adminUser = await (await _appUserRepository.GetQueryableAsync()) .FirstOrDefaultAsync(u => u.UserName == "admin"); //Assert diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index 53cc18991c..e18c27a2de 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/templates/module/angular/package.json b/templates/module/angular/package.json index 4134fead2b..223a33d92a 100644 --- a/templates/module/angular/package.json +++ b/templates/module/angular/package.json @@ -22,30 +22,30 @@ "@abp/ng.tenant-management": "~9.1.0-rc.1", "@abp/ng.theme.basic": "~9.1.0-rc.1", "@abp/ng.theme.shared": "~9.1.0-rc.1", - "@angular/animations": "~19.0.0", - "@angular/common": "~19.0.0", - "@angular/compiler": "~19.0.0", - "@angular/core": "~19.0.0", - "@angular/forms": "~19.0.0", - "@angular/localize": "~19.0.0", - "@angular/platform-browser": "~19.0.0", - "@angular/platform-browser-dynamic": "~19.0.0", - "@angular/router": "~19.0.0", + "@angular/animations": "~19.1.0", + "@angular/common": "~19.1.0", + "@angular/compiler": "~19.1.0", + "@angular/core": "~19.1.0", + "@angular/forms": "~19.1.0", + "@angular/localize": "~19.1.0", + "@angular/platform-browser": "~19.1.0", + "@angular/platform-browser-dynamic": "~19.1.0", + "@angular/router": "~19.1.0", "rxjs": "~7.8.0", "tslib": "^2.0.0", "zone.js": "~0.15.0" }, "devDependencies": { "@abp/ng.schematics": "~9.1.0-rc.1", - "@angular-devkit/build-angular": "~19.0.0", + "@angular-devkit/build-angular": "~19.1.0", "@angular-eslint/builder": "~19.0.0", "@angular-eslint/eslint-plugin": "~19.0.0", "@angular-eslint/eslint-plugin-template": "~19.0.0", "@angular-eslint/schematics": "~19.0.0", "@angular-eslint/template-parser": "~19.0.0", - "@angular/cli": "~19.0.0", - "@angular/compiler-cli": "~19.0.0", - "@angular/language-service": "~19.0.0", + "@angular/cli": "~19.1.0", + "@angular/compiler-cli": "~19.1.0", + "@angular/language-service": "~19.1.0", "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "7.16.0", @@ -57,7 +57,7 @@ "karma-coverage": "~2.1.0", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.7.0", - "ng-packagr": "~19.0.0", + "ng-packagr": "~19.1.0", "symlink": "^2.0.0", "typescript": "~5.6.0" } diff --git a/templates/module/angular/projects/my-project-name/package.json b/templates/module/angular/projects/my-project-name/package.json index 6ac5d309fb..7af2340ee2 100644 --- a/templates/module/angular/projects/my-project-name/package.json +++ b/templates/module/angular/projects/my-project-name/package.json @@ -2,8 +2,8 @@ "name": "@my-company-name/my-project-name", "version": "0.0.1", "peerDependencies": { - "@angular/common": "~19.0.0", - "@angular/core": "~19.0.0", + "@angular/common": "~19.1.0", + "@angular/core": "~19.1.0", "@abp/ng.core": "~9.1.0-rc.1", "@abp/ng.theme.shared": "~9.1.0-rc.1" }, diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs index 07cfd77583..63a2f598c5 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace MyCompanyName.MyProjectName.MongoDB; diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index fed5495bbe..5e43f82146 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -10,10 +10,10 @@ - - - - + + + +