diff --git a/Directory.Packages.props b/Directory.Packages.props index 81225fdbde..0b60bf9e60 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -29,7 +29,7 @@ - + diff --git a/README.md b/README.md index 31db04cba2..7cf41d47eb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ABP Framework ![build and test](https://img.shields.io/github/actions/workflow/status/abpframework/abp/build-and-test.yml?branch=dev&style=flat-square) ๐Ÿ”น [![codecov](https://codecov.io/gh/abpframework/abp/branch/dev/graph/badge.svg?token=jUKLCxa6HF)](https://codecov.io/gh/abpframework/abp) ๐Ÿ”น [![NuGet](https://img.shields.io/nuget/v/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) ๐Ÿ”น [![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) ๐Ÿ”น [![MyGet (nightly builds)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://abp.io/docs/latest/release-info/nightly-builds) ๐Ÿ”น -[![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) ๐Ÿ”น [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md) ๐Ÿ”น [![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp) ๐Ÿ”น [![Discord Shield](https://discord.com/api/guilds/951497912645476422/widget.png?style=shield)](https://discord.gg/abp) +[![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) ๐Ÿ”น [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md) ๐Ÿ”น [![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp) ๐Ÿ”น [![Discord Shield](https://discord.com/api/guilds/951497912645476422/widget.png?style=shield)](https://abp.io/join-discord) [ABP](https://abp.io/) offers an **opinionated architecture** to build enterprise software solutions with **best practices** on top of the **.NET** and the **ASP.NET Core** platforms. It provides the fundamental infrastructure, production-ready startup templates, pre-built application modules, UI themes, tooling, guides and documentation to implement that architecture properly and **automate the details** and repetitive works as much as possible. @@ -121,4 +121,4 @@ GitHub repository stars are an important indicator of popularity and the size of ## Discord Server -We have a Discord server where you can chat with other ABP users. Share your ideas, report technical issues, showcase your creations, share the tips that worked for you and catch up with the latest news and announcements about ABP Framework. Join ๐Ÿ‘‰ https://discord.gg/abp. +We have a Discord server where you can chat with other ABP users. Share your ideas, report technical issues, showcase your creations, share the tips that worked for you and catch up with the latest news and announcements about ABP Framework. Join ๐Ÿ‘‰ https://abp.io/join-discord. diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index ed7781b476..4890226d9a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -242,14 +242,14 @@ "ReturnOnInvestment": "Return on Investment", "PromotionalOffers": "Promotional Offers", "PromotionalOffersDefinition": "Discounts, seasonal campaigns, etc.", - "EventsDefinition": "Community Talks, Webinars, ABP .NET Conference, etc.", + "EventsDefinition": "Community Talks, Webinars, ABP DOTNET Conference, etc.", "ReleaseNotesDefinition": "ABP.IO Platform releases, new products, etc.", "Newsletter": "Newsletter", "NewsletterDefinition": "Blog posts, community news, etc.", "OrganizationOverview": "Organization Overview", "EmailPreferences": "Email Preferences", "VideoCourses": "Essential Videos", - "DoYouAgreePrivacyPolicy": "By clicking Subscribe button you agree to the Terms & Conditions and Privacy Policy.", + "DoYouAgreePrivacyPolicy": "By clicking Subscribe button you agree to the Terms & Conditions and Privacy Policy.", "AbpConferenceDescription": "ABP Conference is a virtual event for .NET developers to learn and connect with the community.", "Mobile": "Mobile", "MetaTwitterCard": "summary_large_image" diff --git a/docs/en/Blog-Posts/2022-05-09 v5_3_Preview/POST.md b/docs/en/Blog-Posts/2022-05-09 v5_3_Preview/POST.md index b23dab0cd1..dfc5a7d67e 100644 --- a/docs/en/Blog-Posts/2022-05-09 v5_3_Preview/POST.md +++ b/docs/en/Blog-Posts/2022-05-09 v5_3_Preview/POST.md @@ -255,4 +255,4 @@ We've created an official ABP Discord server so the ABP Community can interact w Thanks to the ABP Community, **700+** people joined our Discord Server so far and it grows every day. -You can join our Discord Server from [here](https://discord.gg/abp), if you haven't yet. \ No newline at end of file +You can join our Discord Server from [here](https://abp.io/join-discord), if you haven't yet. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md b/docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md index 01acdff96c..33dd9eb292 100644 --- a/docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md +++ b/docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md @@ -75,16 +75,14 @@ public class MyModuleBundleStyleBundleContributor : BundleContributor } ``` -## Use the Global Assets in the Blazor wasm app +## Use the Global Assets in the Blazor WASM -### MyProject +### MyCompanyName.MyProjectName.Blazor -Convert your `MyProject` project to integrate the `ABP module` system and depend on the `AbpAspNetCoreMvcUiBundlingModule` and `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule`: - -> If the `BlazorWebAssembly modules` in `MyProject.Client` contain `BundleContributor`, Please also add the `BlazorWebAssemblyBundlingModule` of the module to the `MyProject` project. +Convert your `MyCompanyName.MyProjectName.Blazor` project to integrate the `ABP module` system and depend on the `AbpAspNetCoreMvcUiBundlingModule` and `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule`: * The `AbpAspNetCoreMvcUiBundlingModule` uses to create the `JavaScript/CSS` files to virtual files. -* The `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule` uses to add theme `JavaScript/CSS` to the bundling system. +* The `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule` uses to add theme `JavaScript/CSS` to the bundling system. Here is how your project files look like: @@ -107,7 +105,7 @@ public class Program await app.RunAsync(); return 0; - //... + //... } } ``` @@ -118,7 +116,7 @@ public class Program [DependsOn( typeof(AbpAutofacModule), typeof(AbpAspNetCoreMvcUiBundlingModule), - typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule) //Should be added! + typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule) //Should be added! )] public class MyProjectNameBlazorModule : AbpModule { @@ -166,7 +164,7 @@ public class MyProjectNameBlazorModule : AbpModule } ``` -**`MyProjectName.csproj`:** +**`MyCompanyName.MyProjectName.Blazor.csproj`:** ```xml @@ -174,15 +172,118 @@ public class MyProjectNameBlazorModule : AbpModule + if you're using LeptonXTheme ``` -### MyProjectName.Client +### BlazorWebAssemblyBundlingModule in the ABP commercial + +Here is the list of `Bundling Modules` in the ABP commercial. If you're using the pro template, you should add them to the `MyCompanyName.MyProjectName.Blazor` project. + +| BundlingModules | Nuget Package | +|---------------------------------------------|-----------------------------------------------------| +| AbpAuditLoggingBlazorWebAssemblyBundlingModule | Volo.Abp.AuditLogging.Blazor.WebAssembly.Bundling | +| FileManagementBlazorWebAssemblyBundlingModule | Volo.FileManagement.Blazor.WebAssembly.Bundling | +| SaasHostBlazorWebAssemblyBundlingModule | Volo.Saas.Host.Blazor.WebAssembly.Bundling | +| ChatBlazorWebAssemblyBundlingModule | Volo.Chat.Blazor.WebAssembly.Bundling | +| CmsKitProAdminBlazorWebAssemblyBundlingModule | Volo.CmsKit.Pro.Admin.Blazor.WebAssembly.Bundling | + + +### MyCompanyName.MyProjectName.Blazor.Client + +1. Remove the `global.JavaScript/CSS` files from the `MyCompanyName.MyProjectName.Blazor`'s `wwwroot` folder. +2. Remove the `AbpCli:Bundle` section from the `appsettings.json` file. +3. Remove all BundleContributor classes that inherit from IBundleContributor. Then, create `MyProjectNameStyleBundleContributor` and `MyProjectNameScriptBundleContributor` classes to add your style and JavaScript files. Finally, add them to `AbpBundlingOptions`. + + +```cs +public class MyProjectNameStyleBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.Add(new BundleFile("main.css", true)); + } +} + + +public class MyProjectNameScriptBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.Add(new BundleFile("main.js", true)); + } +} +``` + +```cs +Configure(options => +{ + var globalStyles = options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global); + globalStyles.AddContributors(typeof(MyProjectNameStyleBundleContributor)); + + var globalScripts = options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global); + globalScripts.AddContributors(typeof(MyProjectNameScriptBundleContributor)); +}); +``` + +## Use the Global Assets in the Blazor WebApp + +### MyCompanyName.MyProjectName.Blazor.WebApp -1. Remove the `global.JavaScript/CSS` files from the `MyProjectName.Client`'s `wwwroot` folder. -2. Refactor all BundleContributor classes that inherit from `IBundleContributor` to inherit from `BundleContributor` instead. -3. Remove the `AbpCli:Bundle` section from the `appsettings.json` file. +Depending on the `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule` in your `MyCompanyName.MyProjectName.Blazor.WebApp` project. + +* The `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule` uses to add theme `JavaScript/CSS` to the bundling system. + + +### BlazorWebAssemblyBundlingModule in the ABP commercial + +Here is the list of `Bundling Modules` in the ABP commercial. If you're using the pro template, you should add them to the `MyCompanyName.MyProjectName.Blazor.WebApp` project. + +| BundlingModules | Nuget Package | +|---------------------------------------------|-----------------------------------------------------| +| AbpAuditLoggingBlazorWebAssemblyBundlingModule | Volo.Abp.AuditLogging.Blazor.WebAssembly.Bundling | +| FileManagementBlazorWebAssemblyBundlingModule | Volo.FileManagement.Blazor.WebAssembly.Bundling | +| SaasHostBlazorWebAssemblyBundlingModule | Volo.Saas.Host.Blazor.WebAssembly.Bundling | +| ChatBlazorWebAssemblyBundlingModule | Volo.Chat.Blazor.WebAssembly.Bundling | +| CmsKitProAdminBlazorWebAssemblyBundlingModule | Volo.CmsKit.Pro.Admin.Blazor.WebAssembly.Bundling | + + +### MyCompanyName.MyProjectName.Blazor.WebApp.Client + +1. Remove the `global.JavaScript/CSS` files from the `MyCompanyName.MyProjectName.Blazor.WebApp.Client`'s `wwwroot` folder. +2. Remove the `AbpCli:Bundle` section from the `appsettings.json` file. +3. Remove all BundleContributor classes that inherit from IBundleContributor. Then, create `MyProjectNameStyleBundleContributor` and `MyProjectNameScriptBundleContributor` classes to add your style and JavaScript files. Finally, add them to `AbpBundlingOptions`. + +```cs +public class MyProjectNameStyleBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.Add(new BundleFile("main.css", true)); + } +} + + +public class MyProjectNameScriptBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.Add(new BundleFile("main.js", true)); + } +} +``` + +```cs +Configure(options => +{ + var globalStyles = options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global); + globalStyles.AddContributors(typeof(MyProjectNameStyleBundleContributor)); + + var globalScripts = options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global); + globalScripts.AddContributors(typeof(MyProjectNameScriptBundleContributor)); +}); +``` ### Check the Global Assets diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 3ef62ff220..1c22ee1c8f 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -57,6 +57,8 @@ }, { "text": "TODO Application", + "isLazyExpandable": true, + "path": "tutorials/todo", "items": [ { "text": "Overview", @@ -75,6 +77,8 @@ }, { "text": "Book Store Application", + "isLazyExpandable": true, + "path": "tutorials/book-store", "items": [ { "text": "Overview", @@ -125,6 +129,8 @@ }, { "text": "Book Store Application (with ABP Suite)", + "isLazyExpandable": true, + "path": "tutorials/book-store-with-abp-suite/index.md", "items": [ { "text": "Overview", @@ -155,6 +161,8 @@ }, { "text": "Modular Monolith Application", + "isLazyExpandable": true, + "path": "tutorials/modular-crm/index.md", "items": [ { "text": "Overview", @@ -197,6 +205,8 @@ }, { "text": "Microservice Solution", + "isLazyExpandable": true, + "path": "tutorials/microservice/index.md", "items": [ { "text": "Overview", @@ -233,6 +243,25 @@ } ] }, + { + "text": "Mobile Application Development", + "isLazyExpandable": true, + "path": "tutorials/mobile/index.md", + "items": [ + { + "text": "Overview", + "path": "tutorials/mobile/index.md" + }, + { + "text": "MAUI", + "path": "tutorials/mobile/maui/index.md" + }, + { + "text": "React Native", + "path": "tutorials/mobile/react-native/index.md" + } + ] + }, { "text": "Community Articles", "path": "https://abp.io/community" @@ -1893,7 +1922,170 @@ }, { "text": "Microservice Solution", - "path": "solution-templates/microservice" + "isLazyExpandable": true, + "path": "solution-templates/microservice", + "items":[ + { + "text": "Overview", + "path": "solution-templates/microservice" + }, + { + "text": "Solution Structure", + "path": "solution-templates/microservice/solution-structure.md" + }, + { + "text": "Main Components", + "items": [ + { + "text": "Overview", + "path": "solution-templates/microservice/main-components" + }, + { + "text": "Microservices", + "path": "solution-templates/microservice/microservices.md" + }, + { + "text": "API Gateways", + "path": "solution-templates/microservice/api-gateways.md" + }, + { + "text": "Web Applications", + "path": "solution-templates/microservice/web-applications.md" + }, + { + "text": "Mobile Applications", + "path": "solution-templates/microservice/mobile-applications.md" + } + ] + }, + { + "text": "Built-In Features", + "items": [ + { + "text": "Overview", + "path": "solution-templates/microservice/built-in-features.md" + }, + { + "text": "Authentication", + "path": "solution-templates/microservice/authentication.md" + }, + { + "text": "Database configurations", + "path": "solution-templates/microservice/database-configurations.md" + }, + { + "text": "Logging (with Serilog and Elasticsearch)", + "path": "solution-templates/microservice/logging.md" + }, + { + "text": "Monitoring (with Prometheus and Grafana)", + "path": "solution-templates/microservice/monitoring.md" + }, + { + "text": "Swagger integration", + "path": "solution-templates/microservice/swagger.md" + }, + { + "text": "Permission management", + "path": "solution-templates/microservice/permission-management.md" + }, + { + "text": "Feature management", + "path": "solution-templates/microservice/feature-management.md" + }, + { + "text": "Localization system", + "path": "solution-templates/microservice/localization-system.md" + }, + { + "text": "Background Jobs", + "path": "solution-templates/microservice/background-jobs.md" + }, + { + "text": "Background Workers", + "path": "solution-templates/microservice/background-workers.md" + }, + { + "text": "Distributed Locking", + "path": "solution-templates/microservice/distributed-locking.md" + }, + { + "text": "Distributed Cache", + "path": "solution-templates/microservice/distributed-cache.md" + }, + { + "text": "Multi-Tenancy", + "path": "solution-templates/microservice/multi-tenancy.md" + }, + { + "text": "BLOB Storing", + "path": "solution-templates/microservice/blob-storing.md" + }, + { + "text": "CORS configuration", + "path": "solution-templates/microservice/cors-configuration.md" + } + ] + }, + { + "text": "Communication", + "items":[ + { + "text": "Overview", + "path": "solution-templates/microservice/communication.md" + }, + { + "text": "HTTP API Calls", + "path": "solution-templates/microservice/http-api-calls.md" + }, + { + "text": "gRPC Calls", + "path": "solution-templates/microservice/grpc-calls.md" + }, + { + "text": "Distributed Events", + "path": "solution-templates/microservice/distributed-events.md" + } + ] + }, + { + "text": "Helm Charts and Kubernetes", + "path": "solution-templates/microservice/helm-charts-and-kubernetes.md" + }, + { + "text": "Guides", + "items": [ + { + "text": "Overview", + "path": "solution-templates/microservice/guides.md" + }, + { + "text": "Adding new microservices", + "path": "solution-templates/microservice/adding-new-microservices.md" + }, + { + "text": "Adding new applications", + "path": "solution-templates/microservice/adding-new-applications.md" + }, + { + "text": "Adding new API gateways", + "path": "solution-templates/microservice/adding-new-api-gateways.md" + }, + { + "text": "Mono-repo vs multiple repository approaches", + "path": "solution-templates/microservice/mono-repo-vs-multiple-repository-approaches.md" + }, + { + "text": "Authoring unit and integration tests", + "path": "solution-templates/microservice/authoring-unit-and-integration-tests.md" + }, + { + "text": "How to use with ABP Suite", + "path": "solution-templates/microservice/how-to-use-with-abp-suite.md" + } + ] + } + ] }, { "text": "Application Module", @@ -1981,6 +2173,8 @@ }, { "text": "IdentityServer", + "isLazyExpandable": true, + "path": "modules/identity-server.md", "items": [ { "text": "Overview", @@ -2003,6 +2197,8 @@ }, { "text": "OpenIddict", + "isLazyExpandable": true, + "path": "modules/openiddict.md", "items": [ { "text": "Overview", diff --git a/docs/en/docs-params.json b/docs/en/docs-params.json index e108f1b554..4aa720e441 100644 --- a/docs/en/docs-params.json +++ b/docs/en/docs-params.json @@ -8,6 +8,7 @@ "Blazor": "Blazor WebAssembly", "BlazorServer": "Blazor Server", "BlazorWebApp": "Blazor WebApp", + "MAUIBlazor": "MAUI Blazor (Hybrid)", "NG": "Angular" } }, diff --git a/docs/en/framework/ui/blazor/global-scripts-styles.md b/docs/en/framework/ui/blazor/global-scripts-styles.md index d53fc3d2ba..a8819df35a 100644 --- a/docs/en/framework/ui/blazor/global-scripts-styles.md +++ b/docs/en/framework/ui/blazor/global-scripts-styles.md @@ -1,83 +1,72 @@ # Blazor UI: Managing Global Scripts & Styles -Some modules may require additional styles or scripts that need to be referenced in **index.html** file. It's not easy to find and update these types of references in Blazor apps. ABP offers a simple, powerful, and modular way to manage global style and scripts in Blazor apps. +You can add your JavaScript and CSS files from your modules or applications to the Blazor global assets system. All the JavaScript and CSS files will be added to the `global.js` and `global.css` files. You can access these files via the following URL in a Blazor WASM project: -To update script & style references without worrying about dependencies, ordering, etc in a project, you can use the [bundle command](../../../cli#bundle). +- https://localhost/global.js +- https://localhost/global.css -You can also add custom styles and scripts and let ABP manage them for you. In your Blazor project, you can create a class implementing `IBundleContributor` interface. +## Add JavaScript and CSS to the global assets system in the module -`IBundleContributor` interface contains two methods. +Your module project solution will have two related Blazor projects: -* `AddScripts(...)` -* `AddStyles(...)` +* `MyModule.Blazor`๏ผšThis project includes the JavaScript/CSS files required for your Blazor components. The `MyApp.Blazor.Client (Blazor WASM)` project will reference this project. +* `MyModule.Blazor.WebAssembly.Bundling`๏ผšThis project is used to add your JavaScript/CSS files to the Blazor global resources. The `MyModule.Blazor (ASP.NET Core)` project will reference this project. -Both methods get `BundleContext` as a parameter. You can add scripts and styles to the `BundleContext` and run [bundle command](../../../cli#bundle). Bundle command detects custom styles and scripts with module dependencies and updates `index.html` file. +You need to define JavaScript and CSS contributor classes in the `MyModule.Blazor.WebAssembly.Bundling` project to add the files to the global assets system. -## Example Usage -```csharp -namespace MyProject.Blazor +> Please use `BlazorWebAssemblyStandardBundles.Scripts.Global` and `BlazorWebAssemblyStandardBundles.Styles.Global` for the bundle name. + +```cs +public class MyModuleBundleScriptContributor : BundleContributor { - public class MyProjectBundleContributor : IBundleContributor + public override void ConfigureBundle(BundleConfigurationContext context) { - public void AddScripts(BundleContext context) - { - context.Add("site.js"); - } - - public void AddStyles(BundleContext context) - { - context.Add("main.css"); - context.Add("custom-styles.css"); - } + context.Files.AddIfNotContains("_content/MyModule.Blazor/libs/myscript.js"); } } ``` -> There is a BundleContributor class implementing `IBundleContributor` interface coming by default with the startup templates. So, most of the time, you don't need to add it manually. - -## Bundling And Minification -`abp bundle` command offers bundling and minification support for client-side resources(JavaScript and CSS files). `abp bundle` command reads the `appsettings.json` file inside the Blazor project and bundles the resources according to the configuration. You can find the bundle configurations inside `AbpCli.Bundle` element. - -Here are the options that you can control inside the `appsettings.json` file. - -`Mode`: Bundling and minification mode. Possible values are -* `BundleAndMinify`: Bundle all the files into a single file and minify the content. -* `Bundle`: Bundle all files into a single file, but not minify. -* `None`: Add files individually, do not bundle. - -`Name`: Bundle file name. Default value is `global`. - -`Parameters`: You can define additional key/value pair parameters inside this section. `abp bundle` command automatically sends these parameters to the bundle contributors, and you can check these parameters inside the bundle contributor, take some actions according to these values. - -Let's say that you want to exclude some resources from the bundle and control this action using the bundle parameters. You can add a parameter to the bundle section like below. - -```json -"AbpCli": { - "Bundle": { - "Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */ - "Name": "global", - "Parameters": { - "ExcludeThemeFromBundle":"true" - } - } - } -``` - -You can check this parameter and take action like below. - -```csharp -public class MyProjectNameBundleContributor : IBundleContributor +```cs +public class MyModuleBundleStyleContributor : BundleContributor { - public void AddScripts(BundleContext context) + public override void ConfigureBundle(BundleConfigurationContext context) { + context.Files.AddIfNotContains("_content/MyModule.Blazor/libs/mystyle.css"); } +} +``` - public void AddStyles(BundleContext context) +```cs +[DependsOn( + typeof(AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule) +)] +public class MyBlazorWebAssemblyBundlingModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - var excludeThemeFromBundle = bool.Parse(context.Parameters.GetValueOrDefault("ExcludeThemeFromBundle")); - context.Add("mytheme.css", excludeFromBundle: excludeThemeFromBundle); - context.Add("main.css"); + Configure(options => + { + // Add script bundle + options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global) + .AddContributors(typeof(MyModuleBundleScriptContributor)); + + // Add style bundle + options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global) + .AddContributors(typeof(MyModuleBundleStyleContributor)); + }); } } ``` +## Add JavaScript and CSS to the global assets system in the application + +This is similar to the module. You need to define JavaScript and CSS contributor classes in the `MyApp.Blazor.Client` project to add the files to the global assets system. + +## AbpBundlingGlobalAssetsOptions + +You can configure the JavaScript and CSS file names in the `GlobalAssets` property of the `AbpBundlingOptions` class. The default values are `global.js` and `global.css`. + +## Reference + +- [ASP.NET Core MVC Bundling & Minification](../mvc-razor-pages/bundling-minification#bundle-contributorsg) +- [ABP Global Assets - New way to bundle JavaScript/CSS files in Blazor WebAssembly app](https://github.com/abpframework/abp/blob/dev/docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md) diff --git a/docs/en/solution-templates/application-module/images/additional-options.png b/docs/en/solution-templates/application-module/images/additional-options.png new file mode 100644 index 0000000000..216c60e50f Binary files /dev/null and b/docs/en/solution-templates/application-module/images/additional-options.png differ diff --git a/docs/en/solution-templates/application-module/images/create-new-module.png b/docs/en/solution-templates/application-module/images/create-new-module.png new file mode 100644 index 0000000000..0b92070b66 Binary files /dev/null and b/docs/en/solution-templates/application-module/images/create-new-module.png differ diff --git a/docs/en/solution-templates/application-module/images/issuemanagement-module-solution.png b/docs/en/solution-templates/application-module/images/issuemanagement-module-solution.png new file mode 100644 index 0000000000..c0c77fb529 Binary files /dev/null and b/docs/en/solution-templates/application-module/images/issuemanagement-module-solution.png differ diff --git a/docs/en/solution-templates/application-module/images/new-module.png b/docs/en/solution-templates/application-module/images/new-module.png new file mode 100644 index 0000000000..af046d16c3 Binary files /dev/null and b/docs/en/solution-templates/application-module/images/new-module.png differ diff --git a/docs/en/solution-templates/application-module/images/new-solution.png b/docs/en/solution-templates/application-module/images/new-solution.png new file mode 100644 index 0000000000..29e6fe4b74 Binary files /dev/null and b/docs/en/solution-templates/application-module/images/new-solution.png differ diff --git a/docs/en/solution-templates/application-module/images/select-database-provider.png b/docs/en/solution-templates/application-module/images/select-database-provider.png new file mode 100644 index 0000000000..1ff834ee1a Binary files /dev/null and b/docs/en/solution-templates/application-module/images/select-database-provider.png differ diff --git a/docs/en/solution-templates/application-module/images/select-user-interface.png b/docs/en/solution-templates/application-module/images/select-user-interface.png new file mode 100644 index 0000000000..b0eecbc25d Binary files /dev/null and b/docs/en/solution-templates/application-module/images/select-user-interface.png differ diff --git a/docs/en/solution-templates/application-module/images/solution-properties.png b/docs/en/solution-templates/application-module/images/solution-properties.png new file mode 100644 index 0000000000..67549db2c5 Binary files /dev/null and b/docs/en/solution-templates/application-module/images/solution-properties.png differ diff --git a/docs/en/solution-templates/application-module/index.md b/docs/en/solution-templates/application-module/index.md index 857b4ed936..0c0f86ddbd 100644 --- a/docs/en/solution-templates/application-module/index.md +++ b/docs/en/solution-templates/application-module/index.md @@ -4,43 +4,51 @@ This template can be used to create a **reusable [application module](../../modu ## How to Start With? -You can use the [ABP CLI](../../cli) to create a new project using this startup template. Alternatively, you can generate a CLI command from the [Get Started](https://abp.io/get-started) page. CLI approach is used here. +You can use the [ABP CLI](../../cli) or [ABP Studio](../../studio/overview.md) to create a new project using this startup template. Alternatively, you can generate a CLI command from the [Get Started](https://abp.io/get-started) page. We will use the ABP Studio for this guide. -First, install the ABP CLI if you haven't installed before: +First, install the ABP Studio if you haven't installed before. You can follow the [installation guide](../../studio/installation.md) for this. -```bash -dotnet tool install -g Volo.Abp.Studio.Cli -``` +### Creating a New Empty Solution -Then use the `abp new` command in an empty folder to create a new solution: +Open the ABP Studio and click the `New solution` button in the welcome page or the `File > New Solution` top menu item. Select the `Empty Solution` template and click the `Next` button. -```bash -abp new-module Acme.BookStore -``` +![New Solution](images/new-solution.png) + +Enter the solution name, select the solution folder and click the `Create` button. + +![Solution Properties](images/solution-properties.png) - `Acme.IssueManagement` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming. -### Specifying the User Interface +> To understand the terms solution, module, and package, refer to the ABP Studio [concepts](../../studio/concepts.md) document. + +### Creating a New DDD Module + +When you create a new solution, the solution explorer on the left side of the screen will appear empty. Right-click on the root of the solution and select `Add > New Module > DDD Module` from the context menu. + +![New Module](images/new-module.png) + +The `Create New Module` dialog will open. Enter the module name and click the `Next` button. + +![Create New Module](images/create-new-module.png) + +Now, you can select the user interface options or leave it empty to create a module without a user interface. A module can support multiple user interfaces, such as MVC, Blazor, Angular, etc., or none at all. Click the `Next` button to specify the database provider. -The template comes without a user interface by default. You can use the `mvc`, `blazor`, `blazor-server`, or `angular` options to include any of these UI layers. You can also combine them. For example, you can use `mvc,angular` to include both MVC and Angular UI. To create a module without a user interface, don't specify any value. +![Select User Interface](images/select-user-interface.png) -````bash -abp new-module Acme.IssueManagement -u mvc,angular -```` +Select the database provider(s) you want to use in your module. You can choose `EntityFrameworkCore`, `MongoDB`, or both. Unlike the user interface options, you must select at least one database provider. Click the `Next` button to see the additional options. -#### Specifying the Database Provider +![Select Database Provider](images/select-database-provider.png) -The template comes with the *EntityFrameworkCore* database provider by default. You can use the `ef` or `mongodb` options to include either of these providers. You can also combine them. For example, you can use `ef,mongodb` to include both EntityFrameworkCore and MongoDB. +You can exclude the test projects from the module by unchecking the `Include Tests` option. Click the `Create` button to create the module. -````bash -abp new-module Acme.IssueManagement -d ef,mongodb -```` +![Additional Options](images/additional-options.png) ## Solution Structure Based on the options you've specified, you will get a slightly different solution structure. If you don't specify any option, you will have a solution like shown below: -![issuemanagement-module-solution](../../images/issuemanagement-module-solution.png) +![issuemanagement-module-solution](images/issuemanagement-module-solution.png) Projects are organized as `src` and`test` folders: diff --git a/docs/en/solution-templates/layered-web-application/_index.md b/docs/en/solution-templates/layered-web-application/_index.md deleted file mode 100644 index 5e0d64b2d8..0000000000 --- a/docs/en/solution-templates/layered-web-application/_index.md +++ /dev/null @@ -1,465 +0,0 @@ -# Layered Application Solution Template - -This template provides a layered application structure based on the [Domain Driven Design](../../framework/architecture/domain-driven-design) (DDD) practices. - -## Getting Started - -This document explains **the solution structure** and projects in details. If you want to start quickly, follow the guides below: - -* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application in a few minutes. -* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development. - -## How to Start With? - -You can use the [ABP CLI](../../cli) to create a new project using this startup template. Alternatively, you can generate a CLI command from the [Get Started](https://abp.io/get-started) page. CLI approach is used here. - -First, install the ABP CLI if you haven't installed it before: - -````bash -dotnet tool install -g Volo.Abp.Studio.Cli -```` - -Then use the `abp new` command in an empty folder to create a new solution: - -````bash -abp new Acme.BookStore -t app -```` - -* `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single-level, two-level or three-level naming. -* This example specified the template name (`-t` or `--template` option). However, `app` is already the default template if you didn't specify it. - -### Specify the UI Framework - -This template provides multiple UI frameworks: - -* `mvc`: ASP.NET Core MVC UI with Razor Pages (default) -* `blazor`: Blazor UI -* `blazor-server`: Blazor Server UI -* `angular`: Angular UI - -Use the `-u` or `--ui` option to specify the UI framework: - -````bash -abp new Acme.BookStore -u angular -```` - -### Specify the Database Provider - -This template supports the following database providers: - -- `ef`: Entity Framework Core (default) -- `mongodb`: MongoDB - -Use `-d` (or `--database-provider`) option to specify the database provider: - -````bash -abp new Acme.BookStore -d mongodb -```` - -### Specify the Mobile Application Framework - -This template supports the following mobile application frameworks: - -- `react-native`: React Native (*Available for* ***Team*** *or higher licenses*) - -Use the `-m` (or `--mobile`) option to specify the mobile application framework: - -````bash -abp new Acme.BookStore -m react-native -```` - -* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application with this startup template. -* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development with this startup template. - -## Solution Structure - -Based on the options you've specified, you will get a slightly different solution structure. - -### Default Structure - -If you don't specify any additional options, you will have a solution as shown below: - -![bookstore-rider-solution-v6](../../images/solution-structure-solution-explorer-rider.png) - -Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../../framework/architecture/domain-driven-design) principles as mentioned before. - -The diagram below shows the layers & project dependencies of the application: - -![layered-project-dependencies](../../images/layered-project-dependencies.png) - -Each section below will explain the related project & its dependencies. - -#### .Domain.Shared Project - -This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution. - -A `BookType` enum and a `BookConsts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project. - -* This project has no dependency on other projects in the solution. All other projects depend on this one directly or indirectly. - -#### .Domain Project - -This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../../framework/architecture/domain-driven-design/entities.md), [domain services](../../framework/architecture/domain-driven-design/domain-services.md), [value objects](../../framework/architecture/domain-driven-design/value-objects.md), [repository interfaces](../../framework/architecture/domain-driven-design/repositories.md) and other domain objects. - -A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project. - -* Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project. - -#### .Application.Contracts Project - -This project mainly contains [application service](../../framework/architecture/domain-driven-design/application-services.md) **interfaces** and [Data Transfer Objects](../../framework/architecture/domain-driven-design/data-transfer-objects.md) (DTO) of the application layer. It exists to separate the interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. - -An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project. - -* Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs. - -#### .Application Project - -This project contains the [application service](../../framework/architecture/domain-driven-design/application-services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project. - -A `BookAppService` class is a good candidate for this project. - -* Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs. -* Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic. - -#### .EntityFrameworkCore Project - -This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project. - -* Depends on the `.Domain` project to be able to reference to entities and repository interfaces. - -> This project is available only if you are using EF Core as the database provider. If you select another database provider, its name will be different. - -#### .DbMigrator Project - -This is a console application that simplifies the execution of database migrations on development and production environments. When you run this application, it: - -* Creates the database if necessary. -* Applies the pending database migrations. -* Seeds initial data if needed. - -> This project has its own `appsettings.json` file. So, if you want to change the database connection string, remember to change this file too. - -Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../../framework/infrastructure/data-seeding.md) for more about the data seeding. - -While creating database & applying migrations seem only necessary for relational databases, this project comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application. - -* Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations. -* Depends on the `.Application.Contracts` project to be able to access permission definitions, because the initial data seeder grants all permissions to the admin role by default. - -#### .HttpApi Project - -This project is used to define your API Controllers. - -Most of the time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../../framework/api-development/auto-controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it. - -* Depends on the `.Application.Contracts` project to be able to inject the application service interfaces. - -#### .HttpApi.Client Project - -This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other types of applications, they can still use your APIs, either manually or using a tool in their own platform) - -Most of the time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../../framework/api-development/dynamic-csharp-clients.md) feature. - -`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies. - -* Depends on the `.Application.Contracts` project to be able to share the same application service interfaces and DTOs with the remote service. - -> You can delete this project & dependencies if you don't need to create C# client proxies for your APIs. - -#### .Web Project - -This project contains the User Interface (UI) of the application if you are using ASP.NET Core MVC UI. It contains Razor pages, JavaScript files, CSS files, images and so on... - -This project contains the main `appsettings.json` file that contains the connection string and other configurations of the application. - -* Depends on the `.HttpApi` project since the UI layer needs to use APIs and the application service interfaces of the solution. - -> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects. -> -> These references are actually not needed while coding your UI layer, because the UI layer normally doesn't depend on the EF Core or the Application layer's implementation. These startup templates are ready for tiered deployment, where the API layer is hosted on a separate server than the UI layer. -> -> However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint. -> -> This gives you the ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to DDD. - -#### Test Projects - -The solution has multiple test projects, one for each layer: - -* `.Domain.Tests` is used to test the domain layer. -* `.Application.Tests` is used to test the application layer. -* `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories. -* `.Web.Tests` is used to test the UI (if you are using ASP.NET Core MVC UI). -* `.TestBase` is a base (shared) project for all tests. - -In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an automated test project) which demonstrate the usage of HTTP APIs from a .NET application. - -Test projects are prepared for integration testing; - -* It is fully integrated into the ABP and all services in your application. -* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library. -* Authorization is disabled, so any application service can be easily used in tests. - -You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all the initialization processes). - -#### How to Run? - -Set `.Web` as the startup project and run the application. The default username is `admin` and the password is `1q2w3E*`. - -See [Getting Started With the ASP.NET Core MVC Template](../../get-started/layered-web-application.md) for more information. - -### Tiered Structure - -If you have selected the ASP.NET Core UI and specified the `--tiered` option, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web applications and HTTP API to different servers**: - -![bookstore-visual-studio-solution-v3](../../images/tiered-solution-servers.png) - -* Browser runs your UI by executing HTML, CSS & JavaScript. -* Web servers host static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application. -* The API Server hosts the HTTP APIs which then use the application & domain layers of the application to perform the business logic. -* Finally, database server hosts your database. - -So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiered deployment of the default structure explained before. - -> Unless you actually need such a 4-tiered deployment, it's suggested to go with the default structure which is simpler to develop, deploy and maintain. - -The solution structure is shown below: - -![bookstore-rider-solution-v6](../../images/bookstore-rider-solution-tiered.png) - -As different from the default structure, two new projects come into play: `.AuthServer` & `.HttpApi.Host`. - -#### .AuthServer Project - -This project is used as an authentication server for other projects. `.Web` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the AuthServer. Then uses the access token to call the HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. - -![tiered-solution-applications](../../images/tiered-solution-applications-authserver.png) - -ABP uses the [OpenIddict Module](../../modules/openiddict.md) that uses the open-source [OpenIddict-core](https://github.com/openiddict/openiddict-core) library for the authentication between applications. See [OpenIddict documentation](https://documentation.openiddict.com/) for details about the OpenIddict and OpenID Connect protocol. - -It has its own `appsettings.json` that contains database connection and other configurations. - -#### .HttpApi.Host Project - -This project is an application that hosts the API of the solution. It has its own `appsettings.json` that contains database connection and other configurations. - -#### .Web Project - -Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on... - -This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains the endpoint of the remote API server and the authentication server. - -#### Pre-requirements - -* [Redis](https://redis.io/): The applications use Redis as a distributed cache. So, you need to have Redis installed & running. - -#### How to Run? - -You should run the application with the given order: - -* First, run the `.AuthServer` since other applications depend on it. -* Then run the `.HttpApi.Host` since it is used by the `.Web` application. -* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password). - -### Blazor UI -If you choose `Blazor` as the UI Framework (using the `-u blazor` or `-u blazor-server` option), the solution will have a project named `.Blazor`. This project contains the Blazor UI application. According to your choice, it will be a Blazor WebAssembly or Blazor Server application. If Blazor WebAssembly is selected, the solution will also have a `.HttpApi.Host`. This project is an ASP.NET Core application that hosts the backend application for the Blazor single page application. - -#### .Blazor Project (Server) -The Blazor Server project is similar to the ASP.NET Core MVC project. It replaces `.Web` project with `.Blazor` in the solution structure above. It has the same folder structure and the same application flow. Since it's an ASP.NET Core application, it can contain **.cshtml** files and **.razor** components at the same time. If routing matches a razor component, the Blazor UI will be used. Otherwise, the request will be handled by the MVC framework. - -![abp solution structure blazor server](../../images/layered-project-dependencies-blazor-server.png) - -#### .Blazor Project (WebAssembly) -The Blazor WebAssembly project is a single page application that runs on the browser. You'll see it as `.Blazor` project in the solution. It uses the `.HttpApi.Host` project to communicate with the backend. It can't be used without the backend application. It contains only **.razor** components. It's a pure client-side application. It doesn't have any server-side code. Everything in this layer will be for the client side. - -![abp solution structure blazor wasm](../../images/layered-project-dependencies-blazor-wasm.png) - -### Angular UI - -If you choose `Angular` as the UI framework (using the `-u angular` option), the solution is being separated into two folders: - -* `angular` folder contains the Angular UI application, the client-side code. -* `aspnet-core` folder contains the ASP.NET Core solution, the server-side code. - -The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the `Angular` application consumes it. - -Angular application folder structure looks like below: - -![angular-folder-structure](../../images/angular-folder-structure.png) - - -Each of ABP modules is an NPM package. Some ABP modules are added as a dependency in `package.json`. These modules install with their dependencies. To see all ABP packages, you can run the following command in the `angular` folder: - -```bash -yarn list --pattern abp -``` - -Angular application module structure: - -![Angular template structure diagram](../../images/angular-template-structure-diagram.png) - -#### AppModule - -`AppModule` is the root module of the application. Some of the ABP modules and some essential modules are imported to `AppModule`. - -ABP Config modules have also been imported to `AppModule`ย for initial requirements of the lazy-loadable ABP modules. - -#### AppRoutingModule - -There are lazy-loadable ABP modules in the `AppRoutingModule` as routes. - -> Paths of ABP Modules should not be changed. - -You should add `routes` property in the `data` object to add a link on the menu to redirect to your custom pages. - -```js -{ - path: 'dashboard', - loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule), - canActivate: [authGuard, permissionGuard], - data: { - routes: { - name: 'ProjectName::Menu:Dashboard', - order: 2, - iconClass: 'fa fa-dashboard', - requiredPolicy: 'ProjectName.Dashboard.Host' - } as ABP.Route - } -} -``` -In the above example; -* If the user is not logged in, authGuard blocks access and redirects to the login page. -* permissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears. -* The `name` property of `routes` is the menu link label. A localization key can be defined. -* The `iconClass` property of the `routes` object is the menu link icon class. -* The `requiredPolicy` property of the `routes` object is the required policy key to access the page. - -After the above `routes` definition, if the user is authorized, the dashboard link will appear on the menu. - -#### Shared Module - -The modules that may be required for all modules have been imported to the `SharedModule`. You should import `SharedModule` to all modules. - -See the [Sharing Modules](https://angular.io/guide/sharing-ngmodules) document. - -#### Environments - -The files under the `src/environments` folder have the essential configuration of the application. - -#### Home Module - -Home module is an example lazy-loadable module that loads on the root address of the application. - -#### Styles - -The required style files are added to the `styles` array in `angular.json`. `AppComponent` loads some style files lazily via `LazyLoadService` after the main bundle is loaded to shorten the first rendering time. - -#### Testing - -You should create your tests in the same folder as the file you want to test. - -See the [testing document](https://angular.io/guide/testing). - -#### Depended Packages - -* [NG Bootstrap](https://ng-bootstrap.github.io/) is used as UI component library. -* [NGXS](https://www.ngxs.io/) is used as state management library. -* [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) is used to support for OAuth 2 and OpenId Connect (OIDC). -* [Chart.js](https://www.chartjs.org/) is used to create widgets. -* [ngx-validate](https://github.com/ng-turkey/ngx-validate) is used for dynamic validation of reactive forms. - -### React Native - -If the `-m react-native` option is specified in the new project command, the solution includes the [React Native](https://reactnative.dev/) application in the `react-native` folder. - -The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the React Native application consumes it. - -The React Native application was generated with [Expo](https://expo.io/). Expo is a set of tools built around React Native to help you quickly start an app and, while it has many features. - -React Native application folder structure as like below: - -![react-native-folder-structure](../../images/react-native-folder-structure.png) - -* `App.js` is the bootstrap component of the application. -* `Environment.js` file has the essential configuration of the application. `prod` and `dev` configurations are defined in this file. -* [Contexts](https://reactjs.org/docs/context.html) are created in the `src/contexts` folder. -* [Higher order components](https://reactjs.org/docs/higher-order-components.html) are created in the `src/hocs` folder. -* [Custom hooks](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook) are created in `src/hooks`. -* [Axios interceptors](https://github.com/axios/axios#interceptors) are created in the `src/interceptors` folder. -* Utility functions are exported from `src/utils` folder. - -#### Components - -Components that can be used on all screens are created in the `src/components` folder. All components have been created as a function that is able to use [hooks](https://reactjs.org/docs/hooks-intro.html). - -#### Screens - -![react-native-navigation-structure](../../images/react-native-navigation-structure.png) - -Screens are created by creating folders that separate their names in the `src/screens` folder. Certain parts of some screens can be split into components. - -Each screen is used in a navigator in the `src/navigators` folder. - -#### Navigation - -[React Navigation](https://reactnavigation.org/) is used as a navigation library. Navigators are created in the `src/navigators`. A [drawer](https://reactnavigation.org/docs/drawer-based-navigation/) navigator and several [stack](https://reactnavigation.org/docs/hello-react-navigation/#installing-the-stack-navigator-library) navigators have been created in this folder. See the [above diagram](#screens) for the navigation structure. - -#### State Management - -[Redux](https://redux.js.org/) is used as a state management library. [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development. - -Actions, reducers, sagas and selectors are created in the `src/store` folder. Store folder is as below: - -![react-native-store-folder](../../images/react-native-store-folder.png) - -* [**Store**](https://redux.js.org/basics/store) is defined in the `src/store/index.js` file. -* [**Actions**](https://redux.js.org/basics/actions/) are payloads of information that send data from your application to your store. -* [**Reducers**](https://redux.js.org/basics/reducers) specify how the application's state changes in response to actions sent to the store. -* [**Redux-Saga**](https://redux-saga.js.org/) is a library that aims to make application side effects (i.e. asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage. Sagas are created in the `src/store/sagas` folder. -* [**Reselect**](https://github.com/reduxjs/reselect) library is used to create memoized selectors. Selectors are created in the `src/store/selectors` folder. - -#### APIs - -[Axios](https://github.com/axios/axios) is used as an HTTP client library. An Axios instance has exported from `src/api/API.js` file to make HTTP calls with the same config. `src/api` folder also has the API files that have been created for API calls. - -#### Theming - -[Native Base](https://nativebase.io/) is used as UI components library. Native Base components can customize easily. See the [Native Base customize](https://docs.nativebase.io/customizing-components) documentation. We followed the same way. - -* Native Base theme variables are in the `src/theme/variables` folder. -* Native Base component styles are in the `src/theme/components` folder. These files have been generated with Native Base's `ejectTheme` script. -* Styles of components override with the files under the `src/theme/overrides` folder. - -#### Testing - -Unit tests will be created. - -See the [Testing Overview](https://reactjs.org/docs/testing.html) document. - -#### Depended Libraries - -* [Native Base](https://nativebase.io/) is used as UI components library. -* [React Navigation](https://reactnavigation.org/) is used as navigation library. -* [Axios](https://github.com/axios/axios) is used as an HTTP client library. -* [Redux](https://redux.js.org/) is used as state management library. -* [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development. -* [Redux-Saga](https://redux-saga.js.org/) is used to manage asynchronous processes. -* [Redux Persist](https://github.com/rt2zz/redux-persist) is used as state persistence. -* [Reselect](https://github.com/reduxjs/reselect) is used to create memoized selectors. -* [i18n-js](https://github.com/fnando/i18n-js) is used as i18n library. -* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) library allows loading fonts easily. -* [Formik](https://github.com/jaredpalmer/formik) is used to build forms. -* [Yup](https://github.com/jquense/yup) is used for form validations. - -## Social / External Logins - -If you want to configure social/external logins for your application, please follow the [Social/External Logins](../../social-external-logins.md) document. - -## What's Next? - -- [The getting started document](../../get-started) explains how to create a new application in a few minutes. -- [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development. - -## See Also -* [Video tutorial](https://abp.io/video-courses/essentials/app-template) diff --git a/docs/en/solution-templates/layered-web-application/blob-storing.md b/docs/en/solution-templates/layered-web-application/blob-storing.md index 8815348349..9e1332e03a 100644 --- a/docs/en/solution-templates/layered-web-application/blob-storing.md +++ b/docs/en/solution-templates/layered-web-application/blob-storing.md @@ -44,6 +44,8 @@ public class MyService : ITransientDependency } ``` +## File Management Module + The *File Management* module is optional and can be added to the solution during the creation process. It provides a user interface to manage folders and files. You can learn more about the module in the [File Management *](../../modules/file-management.md) document. ![file-management](images/file-management-index-page.png) diff --git a/docs/en/solution-templates/layered-web-application/cors-configuration.md b/docs/en/solution-templates/layered-web-application/cors-configuration.md index bae5f9acc6..6df207c107 100644 --- a/docs/en/solution-templates/layered-web-application/cors-configuration.md +++ b/docs/en/solution-templates/layered-web-application/cors-configuration.md @@ -16,12 +16,13 @@ Cross-Origin Resource Sharing (CORS) is a security feature that allows web applications to make requests to a different domain than the one that served the web page. -In the layered solution template, CORS configuration is applied in the following cases: -- If you select the [Tiered solution](solution-structure.md#tiered-structure-). -- If you choose [Angular](web-applications.md#angular) as the web application type. -- If you choose [No UI](web-applications.md#no-ui) as the web application type. +In the layered solution template, CORS configuration is applied in the following cases: +- If you select the [Tiered solution](solution-structure.md#tiered-structure-). +- If you choose [Angular](web-applications.md#angular) as the web application type. +- If you choose [Blazor WebAssembly](web-applications.md#blazor-webassembly) as the web application type. +- If you choose [No UI](web-applications.md#no-ui) as the web application type. -The CORS settings are configured in the `appsettings.json` file of the corresponding project. Typically, the web application serves as the entry point for front-end applications, so it must be configured to accept requests from different origins. +The CORS settings are configured in the `appsettings.json` file of the corresponding project. Typically, the web application serves as the entry point for front-end applications, so it must be configured to accept requests from different origins. The default configuration in `appsettings.json` is as follows: diff --git a/docs/en/solution-templates/layered-web-application/multi-tenancy.md b/docs/en/solution-templates/layered-web-application/multi-tenancy.md index 73284a272c..53727f1c85 100644 --- a/docs/en/solution-templates/layered-web-application/multi-tenancy.md +++ b/docs/en/solution-templates/layered-web-application/multi-tenancy.md @@ -24,7 +24,7 @@ The layered solution templates use the *Multi-Tenancy* architecture only if you ![saas-module-selection](images/saas-module-selection.png) -You can use different databases for each tenant or a shared database for all tenants. In the *SaaS **\*** module, you can specify the database connection strings in the [Connection Strings Management Modal](../../modules/saas.md#connection-string). All cached data is isolated by tenant. Each event, background job, and other data is stored with the tenant id. +You can use different databases for each tenant or a shared database for some tenants. In the *SaaS **\*** module, you can specify the database connection strings in the [Connection Strings Management Modal](../../modules/saas.md#connection-string). All cached data is isolated by tenant. Each event, background job, and other data is stored with the tenant id. You can use the `ICurrentTenant` service to get the current tenant information in your application. diff --git a/docs/en/solution-templates/single-layer-web-application/_index.md b/docs/en/solution-templates/single-layer-web-application/_index.md new file mode 100644 index 0000000000..d5720f5602 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/_index.md @@ -0,0 +1,59 @@ +# Single Layer Application Solution Template + +This template provides a simple solution structure with a single project. This document explains that solution structure in details. + +## Getting Started + +* Follow the [Getting Started guide](../../get-started/single-layer-web-application.md) to create a new solution using this startup solution template. +* Follow the [TODO application tutorial](../../tutorials/todo/single-layer/index.md) to learn how to create a simple application with this startup solution template. + +## The Solution Structure + +If you created your solution with the default options, you will have a .NET solution as shown below: + +![](../../images/bookstore-single-layer-solution-structure.png) + +In the next sections, we will explain the structure based on this example. Your startup solution can be slightly different based on your preferences. + +### Folder Structure + +Since this template provides a single-project solution, we've separated concerns into folders instead of projects. You can see the pre-defined folders as shown below: + +![](../../images/single-layer-folder-structure.png) + +* Define your database mappings (for [EF Core](../../framework/data/entity-framework-core) or [MongoDB](../../framework/data/mongodb) and [repositories](../../framework/architecture/domain-driven-design/repositories.md) in the `Data` folder. +* Define your [entities](../../framework/architecture/domain-driven-design/entities.md) in the `Entities` folder. +* Define your UI localization keys/values in the `Localization` folder. +* Define your UI menu items in the `Menus` folder. +* Define your [object-to-object mapping](../../framework/infrastructure/object-to-object-mapping.md) classes in the `ObjectMapping` folder. +* Define your UI pages (Razor Pages) in the `Pages` folder (create `Controllers` and `Views` folder yourself if you prefer the MVC pattern). +* Define your [application services](../../framework/architecture/domain-driven-design/application-services.md) in the `Services` folder. + +### How to Run? + +Before running the application, you need to create the database and seed the initial data. To do that, you can run the following command in the directory of your project (in the same folder of the `.csproj` file): + +```bash +dotnet run --migrate-database +``` + +This command will create the database and seed the initial data for you. Then you can run the application with any IDE that supports .NET or by running the `dotnet run` command in the directory of your project. The default username is `admin` and the password is `1q2w3E*`. + +> While creating a database & applying migrations seem only necessary for relational databases, you should run this command even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application. + +### The Angular UI + +If you choose `Angular` as the UI framework, the solution will be separated into two folders: + +* An `angular` folder that contains the Angular UI application, the client-side code. +* An `aspnet-core` folder that contains the ASP.NET Core solution (a single project), the server-side code. + +The server-side is similar to the solution described in the *Solution Structure* section above. This project serves the API, so the Angular application can consume it. + +The client-side application consumes the HTTP APIs as mentioned. You can see the folder structure of the Angular project shown below: + +![](../../images/single-layer-angular-folder-structure.png) + + ## See Also + +* [Video tutorial](https://abp.io/video-courses/essentials/app-template) \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/authentication.md b/docs/en/solution-templates/single-layer-web-application/authentication.md new file mode 100644 index 0000000000..17a6f0f2c5 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/authentication.md @@ -0,0 +1,52 @@ +# Single Layer Solution: Authentication + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Built-In Features", + "Path": "solution-templates/layered-web-application/built-in-features" + }, + "Next": { + "Name": "Database configurations in the Single-Layer solution", + "Path": "solution-templates/layered-web-application/database-configurations" + } +} +``` + +> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. + +The [Single Layer solution template](index.md) is fully configured for authentication. All the services and applications are configured to use the [OpenIddict](https://documentation.openiddict.com) library for authentication. They are configured in a common way for authentication. This document explains that common authentication structure. + +## OpenIddict + +[OpenIddict](https://documentation.openiddict.com) is an open-source library that provides a simple and easy way to implement an OpenID Connect server in your application. ABP has built-in modules ([OpenIddict](../../modules/openiddict.md), [OpenIddict UI **\***](../../modules/openiddict-pro.md)) to integrate OpenIddict into the solution. + +## Initial Data Seeding + +The Single Layer solution template includes an initial data seeding mechanism to create default clients (applications) and scopes for the solution, if necessary (e.g., when using an Angular UI). The `OpenIddictDataSeedContributor` class can be found in the `Data` folder of the host project. If authentication is handled by the UI application(e.g., MVC / Razor Pages), this class is not included. + +The [OpenIddict UI **\***](../../modules/openiddict-pro.md) module is added only if you select it while creating the solution. + +![new-solution-openiddict-module](images/new-solution-openiddict-module.png) + +The OpenIddict UI **\*** module provides a user interface to manage the OpenIddict entities such as applications, scopes, etc. You can manage these entities from the application UI. + +![openiddict-ui](images/openiddict-ui.png) + +### External Providers + +The authentication server handles token generation, validation, and user account management (e.g., login, registration). It uses the [Account](../../modules/account.md) or [Account Pro **\***](../../modules/account-pro.md) module. The [Account Pro **\***](../../modules/account-pro.md) module additionally supports [social logins](../../modules/account-pro.md#social--external-logins) (e.g., Google, Facebook). Social logins can be enabled, disabled, and configured directly from the application's user interface. + +![account-external-provider](images/account-external-provider.png) + +## Authentication Flows + +Applications in the solution use different authentication flows depending on the application type: + +- **MVC UI Web Application**: + Uses the [Hybrid Flow](https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth) (OpenID Connect Authentication) for user authentication. +- **SPA and Swagger Applications**: + Use the [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) to authenticate users. + +If the UI is a SPA application (such as an Angular app), the API host uses [JWT Bearer Authentication](https://jwt.io/introduction/) to authorize user actions. \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/blob-storing.md b/docs/en/solution-templates/single-layer-web-application/blob-storing.md new file mode 100644 index 0000000000..d316c009c6 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/blob-storing.md @@ -0,0 +1,51 @@ +# Single Layer Solution: BLOB Storing + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Multi-Tenancy", + "Path": "solution-templates/single-layer-web-application/multi-tenancy" + }, + "Next": { + "Name": "CORS Configuration", + "Path": "solution-templates/single-layer-web-application/cors-configuration" + } +} +``` + +> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. + +This document explains how to store BLOBs (Binary Large Objects) in a single-layer solution. Storing files, images, videos, and other large objects is common in distributed systems. For more details, refer to the [BLOB Storing System](../../framework/infrastructure/blob-storing/index.md) documentation. + +In the single-layer solution template, the [Database Provider](../../framework/infrastructure/blob-storing/database.md) is used to store BLOBs in the database. The `Volo.Abp.BlobStoring.Database.EntityFrameworkCore` or `Volo.Abp.BlobStoring.Database.MongoDB` package provides the required implementations for storing and retrieving BLOBs in the database. This setup is integrated into the single-layer solution template and is used across all related projects. You can modify the database configuration in the `appsettings.json` file of the API project. + +You can use the `IBlobContainer` or `IBlobContainer` service to store and retrieve BLOBs. Here is an example of storing a BLOB: + +```csharp +public class MyService : ITransientDependency +{ + private readonly IBlobContainer _blobContainer; + + public MyService(IBlobContainer blobContainer) + { + _blobContainer = blobContainer; + } + + public async Task SaveBytesAsync(byte[] bytes) + { + await _blobContainer.SaveAsync("my-blob-1", bytes); + } + + public async Task GetBytesAsync() + { + return await _blobContainer.GetAllBytesOrNullAsync("my-blob-1"); + } +} +``` + +## File Management Module + +The *File Management* module is optional and can be added to the solution during the creation process. It provides a user interface for managing folders and files. For more information, see the [File Management *](../../modules/file-management.md) document. + +![file-management](images/file-management-index-page.png) \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/built-in-features.md b/docs/en/solution-templates/single-layer-web-application/built-in-features.md new file mode 100644 index 0000000000..2700c1d8dd --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/built-in-features.md @@ -0,0 +1,25 @@ +# Single Layer Solution: Built-In Features + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Db Migrator", + "Path": "solution-templates/single-layer-web-application/db-migrator" + }, + "Next": { + "Name": "Authentication", + "Path": "solution-templates/single-layer-web-application/authentication" + } +} +``` + +The Single Layer solution template includes several built-in features to help you get started with your single-layer web application. These features are designed to provide a solid foundation for your application and help you focus on your business logic. This document provides an overview of the built-in features included in the Single Layer solution template. The following documents explain these features in detail: + +* [Authentication](authentication.md) +* [Database configurations](database-configurations.md) +* [Logging (with Serilog)](logging.md) +* [Swagger integration](swagger-integration.md) +* [Multi-Tenancy](multi-tenancy.md) +* [BLOB storing](blob-storing.md) +* [CORS configuration](cors-configuration.md) \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/cors-configuration.md b/docs/en/solution-templates/single-layer-web-application/cors-configuration.md new file mode 100644 index 0000000000..f54c73ad79 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/cors-configuration.md @@ -0,0 +1,32 @@ +# Single Layer Solution: CORS Configuration + +```json +//[doc-nav] +{ + "Previous": { + "Name": "BLOB Storing", + "Path": "solution-templates/single-layer-web-application/blob-storing" + } +} +``` + +Cross-Origin Resource Sharing (CORS) is a security feature that allows web applications to make requests to a different domain than the one that served the web page. + +In the single-layer solution template, CORS configuration is applied in the following cases: +- When [Angular](web-applications.md#angular) is selected as the web application type. +- When [Blazor WebAssembly](web-applications.md#blazor-webassembly) is selected as the web application type. +- When [No UI](web-applications.md#no-ui) is selected as the web application type. + +CORS settings are configured in the `appsettings.json` file of the corresponding project. The web application usually serves as the entry point for front-end applications, so it must be set up to accept requests from different origins. + +The default configuration in `appsettings.json` is as follows: + +```json +{ + "App": { + "CorsOrigins": "https://*.MyProjectName.com" + } +} +``` + +You can modify the `CorsOrigins` property to include additional domains or wildcard subdomains as needed for your application. \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/database-configurations.md b/docs/en/solution-templates/single-layer-web-application/database-configurations.md new file mode 100644 index 0000000000..ec48fcf6f0 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/database-configurations.md @@ -0,0 +1,190 @@ +# Single Layer Solution: Database configurations + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Authentication", + "Path": "solution-templates/single-layer-web-application/authentication" + }, + "Next": { + "Name": "Logging (with Serilog)", + "Path": "solution-templates/single-layer-web-application/logging" + } +} +``` + +> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. + +ABP Studio's Single-Layer Solution Template includes pre-configured database settings. This document explains how to manage database configurations in your solution. + +## Connection String + +Connection strings are stored in the `appsettings.json` file and can be customized for different environments by editing this file. [Web Application](web-applications.md) projects use the `Default` connection string by default. + +To update the connection string for the `Default` key, modify the `appsettings.json` file in your project. Connection strings are defined under the `ConnectionStrings` section, as shown below: + +```json +{ + "ConnectionStrings": { + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Bookstore;Trusted_Connection=True;TrustServerCertificate=true" + } +} +``` + +## The DbContext Class + +In the Single-Layer Solution Template, the `DbContext` class is defined in the main project. This class manages the database schema and is derived from the `AbpDbContext` class, which offers additional features and configurations. You can customize the `DbContext` class to add new entities, relationships, and configurations. It is located in the `Data` folder of the main project. + +```csharp +public class BookstoreDbContext : AbpDbContext +{ + + public const string DbTablePrefix = "App"; + public const string DbSchema = null; + + public BookstoreDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureFeatureManagement(); + builder.ConfigurePermissionManagement(); + builder.ConfigureBlobStoring(); + builder.ConfigureIdentityPro(); + builder.ConfigureOpenIddictPro(); + builder.ConfigureGdpr(); + builder.ConfigureLanguageManagement(); + builder.ConfigureSaas(); + builder.ConfigureTextTemplateManagement(); + + /* Configure your own entities here */ + } +} +``` + +### OnModelCreating Method + +The `OnModelCreating` method is used to configure the database schema. It calls the `Configure*` methods of the ABP Framework to configure the database schema for the modules. You can also configure your own tables/entities inside this method. + +```csharp +protected override void OnModelCreating(ModelBuilder builder) +{ + base.OnModelCreating(builder); + + builder.ConfigurePermissionManagement(); + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureFeatureManagement(); + builder.ConfigureIdentityPro(); + builder.ConfigureOpenIddictPro(); + builder.ConfigureLanguageManagement(); + builder.ConfigureSaas(); + builder.ConfigureTextTemplateManagement(); + builder.ConfigureGdpr(); + builder.ConfigureCmsKit(); + builder.ConfigureCmsKitPro(); + builder.ConfigureBlobStoring(); + + /* Configure your own tables/entities inside here */ + + //builder.Entity(b => + //{ + // b.ToTable(DbTablePrefix + "YourEntities", DbSchema); + // b.ConfigureByConvention(); //auto configure for the base class props + // //... + //}); +} +``` + +> The `Configure*` methods are extension methods defined in each module's `EntityFrameworkCore` project. These methods are used to configure the database schema for their respective modules. + +### Configuration + +In the `BookstoreModule` class, the `ConfigureEfCore` method is used to configure the database context. It registers the `BookstoreDbContext` class to the [dependency injection](../../framework/fundamentals/dependency-injection.md) system and sets the SQL Server as the default DBMS for the application. + +```csharp +private void ConfigureEfCore(ServiceConfigurationContext context) +{ + context.Services.AddAbpDbContext(options => + { + /* You can remove "includeAllEntities: true" to create + * default repositories only for aggregate roots + * Documentatidon: https://docs.abp.io/en/abp/latest/Entity-Framework-Core#add-default-repositories + */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + options.Configure(configurationContext => + { + configurationContext.UseSqlServer(); + }); + }); + +} +``` + +## The `IDesignTimeDbContextFactory` Implementation + +The `IDesignTimeDbContextFactory` interface is used to create a `DbContext` instance at design time. It is used by EF Core tools to create migrations and update the database. The `BookstoreDbContextFactory` class implements the `IDesignTimeDbContextFactory` interface to create a `BookstoreMigrationsDbContext` instance. + +```csharp +public class BookstoreDbContextFactory : IDesignTimeDbContextFactory +{ + public BookstoreDbContext CreateDbContext(string[] args) + { + BookstoreEfCoreEntityExtensionMappings.Configure(); + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseSqlServer(configuration.GetConnectionString("Default")); + + return new BookstoreDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} +``` + +## SaaS Module: The Tenant Management UI **\*** + +SaaS module provides the necessary UI to set and change connection string for tenants and trigger the database migrations. + +### The Connection String Management Modal + +You can click to the *Database Connection Strings* command in the *Actions* dropdown button for a tenant in the *Tenants* page of the SaaS module: + +![Database Connection Strings](images/database-connection-strings.png) + +It opens the *Database Connection Strings* modal as shown below: + +![Database Connection Strings Modal](images/database-connection-strings-modal.png) + +Here, we can set a *Default connection string* for the tenant. + +When you make the changes and save the dialog, the database is automatically created and migrated. If you later update the connection string (for example if you change the database name), it will also trigger the database migration process again. + +### Manually Applying the Database Migrations + +If you need to manually trigger the database migrations for a specific tenant, click the *Actions* dropdown for the related tenant and select the *Apply Database Migrations* command on the *Tenant Management* page of the SaaS module: + +![Apply Database Migrations](images/apply-database-migrations.png) diff --git a/docs/en/solution-templates/single-layer-web-application/db-migrator.md b/docs/en/solution-templates/single-layer-web-application/db-migrator.md new file mode 100644 index 0000000000..988b16cef6 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/db-migrator.md @@ -0,0 +1,107 @@ +# Single Layer Solution: Db Migrator + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Web Applications", + "Path": "solution-templates/single-layer-web-application/web-applications" + }, + "Next": { + "Name": "Built-In Features", + "Path": "solution-templates/single-layer-web-application/built-in-features" + } +} +```` + +Unlike the Layered solution template, the Single Layer solution template does not include a separate database migrator project. Instead, the main application project handles database migration and seed data operations. The `*.DbMigrator` project is excluded from this template. To manage database migrations and seed data, you can use the `migrate-database.ps1` script in the root directory or run the `dotnet run --migrate-database` command from the main application project directory. + +![Single Layer Solution: Db Migrator](images/single-layer-db-migrator.png) + +After the migration completes, a message will appear in the console. You can verify the success of the migration by checking the database. + +## Database Migration Service + +Under the `Data` folder of the project, the `BookstoreDbMigrationService` class is responsible for database migration and seed data operations. The `MigrateAsync` method is called in the `Program` class to migrate the database when the application starts with the `--migrate-database` argument. + +First, it checks if the database is created and applies the pending migrations. Then, it seeds the initial data using the `SeedAsync` method. + +```csharp +public async Task MigrateAsync() +{ + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); +} +``` + +The `BookstoreDbSchemaMigrator` class is used in the `MigrateDatabaseSchemaAsync` method for the database migration process. It is responsible for applying migrations to the database. + +```csharp +public class BookstoreDbSchemaMigrator : ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + + public BookstoreDbSchemaMigrator( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + + /* We intentionally resolving the BookstoreDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + + } +} +``` \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/images/account-external-provider.png b/docs/en/solution-templates/single-layer-web-application/images/account-external-provider.png new file mode 100644 index 0000000000..acfefeee7c Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/account-external-provider.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/apply-database-migrations.png b/docs/en/solution-templates/single-layer-web-application/images/apply-database-migrations.png new file mode 100644 index 0000000000..28d5f73786 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/apply-database-migrations.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/database-connection-strings-modal.png b/docs/en/solution-templates/single-layer-web-application/images/database-connection-strings-modal.png new file mode 100644 index 0000000000..7dc2fd7243 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/database-connection-strings-modal.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/database-connection-strings.png b/docs/en/solution-templates/single-layer-web-application/images/database-connection-strings.png new file mode 100644 index 0000000000..bc13bbf932 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/database-connection-strings.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/file-management-index-page.png b/docs/en/solution-templates/single-layer-web-application/images/file-management-index-page.png new file mode 100644 index 0000000000..c19d41f006 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/file-management-index-page.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/new-solution-openiddict-module.png b/docs/en/solution-templates/single-layer-web-application/images/new-solution-openiddict-module.png new file mode 100644 index 0000000000..5c849d9f8c Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/new-solution-openiddict-module.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/openiddict-ui.png b/docs/en/solution-templates/single-layer-web-application/images/openiddict-ui.png new file mode 100644 index 0000000000..fdbbc4530b Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/openiddict-ui.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/saas-module-selection.png b/docs/en/solution-templates/single-layer-web-application/images/saas-module-selection.png new file mode 100644 index 0000000000..8904c4eaec Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/saas-module-selection.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/single-layer-db-migrator.png b/docs/en/solution-templates/single-layer-web-application/images/single-layer-db-migrator.png new file mode 100644 index 0000000000..08d8319268 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/single-layer-db-migrator.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-folders.png b/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-folders.png new file mode 100644 index 0000000000..d2cf400a66 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-folders.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-in-explorer.png b/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-in-explorer.png new file mode 100644 index 0000000000..66a47e24e8 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-in-explorer.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-in-visual-studio.png b/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-in-visual-studio.png new file mode 100644 index 0000000000..adcb33247e Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/single-layer-solution-in-visual-studio.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/solution-runner.png b/docs/en/solution-templates/single-layer-web-application/images/solution-runner.png new file mode 100644 index 0000000000..fdc9e28a52 Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/solution-runner.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/images/web-applications.png b/docs/en/solution-templates/single-layer-web-application/images/web-applications.png new file mode 100644 index 0000000000..5c12767c2f Binary files /dev/null and b/docs/en/solution-templates/single-layer-web-application/images/web-applications.png differ diff --git a/docs/en/solution-templates/single-layer-web-application/index.md b/docs/en/solution-templates/single-layer-web-application/index.md index d5720f5602..e83100e7cf 100644 --- a/docs/en/solution-templates/single-layer-web-application/index.md +++ b/docs/en/solution-templates/single-layer-web-application/index.md @@ -1,59 +1,33 @@ -# Single Layer Application Solution Template - -This template provides a simple solution structure with a single project. This document explains that solution structure in details. - -## Getting Started - -* Follow the [Getting Started guide](../../get-started/single-layer-web-application.md) to create a new solution using this startup solution template. -* Follow the [TODO application tutorial](../../tutorials/todo/single-layer/index.md) to learn how to create a simple application with this startup solution template. - -## The Solution Structure - -If you created your solution with the default options, you will have a .NET solution as shown below: - -![](../../images/bookstore-single-layer-solution-structure.png) - -In the next sections, we will explain the structure based on this example. Your startup solution can be slightly different based on your preferences. - -### Folder Structure - -Since this template provides a single-project solution, we've separated concerns into folders instead of projects. You can see the pre-defined folders as shown below: - -![](../../images/single-layer-folder-structure.png) - -* Define your database mappings (for [EF Core](../../framework/data/entity-framework-core) or [MongoDB](../../framework/data/mongodb) and [repositories](../../framework/architecture/domain-driven-design/repositories.md) in the `Data` folder. -* Define your [entities](../../framework/architecture/domain-driven-design/entities.md) in the `Entities` folder. -* Define your UI localization keys/values in the `Localization` folder. -* Define your UI menu items in the `Menus` folder. -* Define your [object-to-object mapping](../../framework/infrastructure/object-to-object-mapping.md) classes in the `ObjectMapping` folder. -* Define your UI pages (Razor Pages) in the `Pages` folder (create `Controllers` and `Views` folder yourself if you prefer the MVC pattern). -* Define your [application services](../../framework/architecture/domain-driven-design/application-services.md) in the `Services` folder. - -### How to Run? - -Before running the application, you need to create the database and seed the initial data. To do that, you can run the following command in the directory of your project (in the same folder of the `.csproj` file): - -```bash -dotnet run --migrate-database -``` - -This command will create the database and seed the initial data for you. Then you can run the application with any IDE that supports .NET or by running the `dotnet run` command in the directory of your project. The default username is `admin` and the password is `1q2w3E*`. - -> While creating a database & applying migrations seem only necessary for relational databases, you should run this command even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application. - -### The Angular UI - -If you choose `Angular` as the UI framework, the solution will be separated into two folders: - -* An `angular` folder that contains the Angular UI application, the client-side code. -* An `aspnet-core` folder that contains the ASP.NET Core solution (a single project), the server-side code. - -The server-side is similar to the solution described in the *Solution Structure* section above. This project serves the API, so the Angular application can consume it. - -The client-side application consumes the HTTP APIs as mentioned. You can see the folder structure of the Angular project shown below: - -![](../../images/single-layer-angular-folder-structure.png) - - ## See Also - -* [Video tutorial](https://abp.io/video-courses/essentials/app-template) \ No newline at end of file +# ABP Studio: Single Layer Solution Template + +````json +//[doc-nav] +{ + "Next": { + "Name": "Overview", + "Path": "solution-templates/single-layer-web-application/overview" + } +} +```` + +ABP Studio offers pre-architected, production-ready templates to quickly start a new solution. One of these is the Single Layer solution template, designed for building monolithic systems with minimal layers. It follows [Domain-Driven Design](../../framework/architecture/domain-driven-design) (DDD) principles and common application patterns. The template includes a single project, integrates existing modules, and provides host applications based on your selections, making it a solid foundation for your system. + +> **This document explains the Single Layer solution template in detail. It is a reference document to fully understand the solution and refer to when you have trouble.** +> +> **If you want to quickly create a single-layer solution, please refer to *[Quick Start: Creating a Single Layer Web Application with ABP Studio](../../get-started/single-layer-web-application.md)* document.** + +## Contents + +* [Overview](overview.md) +* [Solution structure](solution-structure.md) +* [Main Components](main-components.md) + * [Web Applications](web-applications.md) + * [Db Migrator](db-migrator.md) +* [Built-In Features](built-in-features.md) + * [Authentication](authentication.md) + * [Database configurations](database-configurations.md) + * [Logging (with Serilog)](logging.md) + * [Swagger integration](swagger-integration.md) + * [Multi-Tenancy](multi-tenancy.md) + * [BLOB storing](blob-storing.md) + * [CORS configuration](cors-configuration.md) \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/logging.md b/docs/en/solution-templates/single-layer-web-application/logging.md new file mode 100644 index 0000000000..5b3483822b --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/logging.md @@ -0,0 +1,35 @@ +# Single Layer Solution: Logging + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Database configurations", + "Path": "solution-templates/single-layer-web-application/database-configurations" + }, + "Next": { + "Name": "Swagger integration", + "Path": "solution-templates/single-layer-web-application/swagger-integration" + } +} +``` + +The ABP Studio [single-layer solution template](index.md) is fully configured for [logging](../../framework/fundamentals/logging.md). All the applications are configured to use the [Serilog](https://serilog.net/) library for structured logging. They are configured in a common way for logging. This document explains that common logging structure. + +## The Serilog Sinks + +The Serilog library is configured so it writes the logs to the following targets (a.k.a. [sinks](https://github.com/serilog/serilog/wiki/Provided-Sinks)) in parallel: + +* **[Console](https://github.com/serilog/serilog-sinks-console)**: Logs are written to the standard output of the executing application. Logging to console is useful when you want to see logs easily while it is running in a container. +* **[File](https://github.com/serilog/serilog-sinks-file)**: Logs are written to a file named `logs.txt` located under the `Logs` folder of the executing application. File logging is useful when you run the application on your local computer. You can check logs easily when you have a trouble. This sinks is only configured for DEBUG mode. It won't be available in your production environment (you can change the behavior in your `Program.cs` file). +* **ABP Studio**: This is a Sink provided by ABP Studio. It sends all logs to ABP Studio, so you can easily monitor your logs in real-time on your ABP Studio Application Monitoring panel. + +The solution can work with [any sink](https://github.com/serilog/serilog/wiki/Provided-Sinks) supported by Serilog. You can add more sinks, remove pre-installed sinks or fine tune their configuration for your solution. + +## Program.cs + +The `Program.cs` file is the main point that configures the logging system. It is done here, because we want to initialize and start the logging in the very beginning of the application. + +## Additional Information + +We are using ABP Serilog Enrichers in the module class of the application. It is done by the `app.UseAbpSerilogEnrichers();` line in the `OnApplicationInitialization` method of your module class. That ASP.NET Core middleware adds current [tenant](../../framework/architecture/multi-tenancy/index.md), [user](../../framework/infrastructure/current-user.md), client and correlation id information to the log records. \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/main-components.md b/docs/en/solution-templates/single-layer-web-application/main-components.md new file mode 100644 index 0000000000..d219c69155 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/main-components.md @@ -0,0 +1,20 @@ +# Single Layer Solution: Main Components + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Solution structure", + "Path": "solution-templates/single-layer-web-application/solution-structure" + }, + "Next": { + "Name": "Web Applications", + "Path": "solution-templates/single-layer-web-application/web-applications" + } +} +```` + +The single-layer solution template is a single project containing all the essential components for building a monolithic application. It supports the `--migrate-database` command-line argument to create the database and seed initial data. The main components of the solution are: + +* [Web Applications](web-applications.md) +* [Db Migrator](db-migrator.md) \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md b/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md new file mode 100644 index 0000000000..452cfa9bcd --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md @@ -0,0 +1,74 @@ +# Single Layer Solution: Multi-Tenancy + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Swagger integration", + "Path": "solution-templates/single-layer-web-application/swagger-integration" + }, + "Next": { + "Name": "BLOB storing", + "Path": "solution-templates/single-layer-web-application/blob-storing" + } +} +``` + +> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. + +Multi-tenancy is a software architecture where a single instance(codebase) of software runs on a server and serves multiple tenants. Tenants are isolated from each other and can have their own data, configurations, and users. This document explains how the multi-tenancy mechanism works in the single-layer solution template. You can learn more about multi-tenancy in the [Multi-Tenancy](../../framework/architecture/multi-tenancy/index.md), [Tenant Management](../../modules/tenant-management.md) and [SaaS **\***](../../modules/saas.md) documents. + +## Multi-Tenancy in Single Layer Solutions + +The single-layer solution templates use the *Multi-Tenancy* architecture only if you *Enable Multi-Tenancy **\**** option while creating the solution. + +![saas-module-selection](images/saas-module-selection.png) + +You can use different databases for each tenant or a shared database for some tenants. In the *SaaS **\*** module, you can specify the database connection strings in the [Connection Strings Management Modal](../../modules/saas.md#connection-string). All cached data is isolated by tenant. Each event, background job, and other data is stored with the tenant id. + +You can use the `ICurrentTenant` service to get the current tenant information in your application. + +```csharp +public class MyService : ITransientDependency +{ + private readonly ICurrentTenant _currentTenant; + + public MyService(ICurrentTenant currentTenant) + { + _currentTenant = currentTenant; + } + + public void MyMethod() + { + var tenantId = _currentTenant.Id; + var tenantName = _currentTenant.Name; + } +} +``` + +Additionally, you can use the [DataFilter](../../framework/infrastructure/data-filtering.md#idatafilter-service-enabledisable-data-filters) system to disable the tenant filter and list all data in the same database. + +```csharp +public class MyBookService : ITransientDependency +{ + private readonly IDataFilter _multiTenantFilter; + private readonly IRepository _bookRepository; + + public MyBookService( + IDataFilter multiTenantFilter, + IRepository bookRepository) + { + _multiTenantFilter = multiTenantFilter; + _bookRepository = bookRepository; + } + + public async Task> GetAllBooksIncludingDeletedAsync() + { + //Temporary disable the IMultiTenant filter + using (_multiTenantFilter.Disable()) + { + return await _bookRepository.GetListAsync(); + } + } +} +``` \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/overview.md b/docs/en/solution-templates/single-layer-web-application/overview.md new file mode 100644 index 0000000000..8592dc1e8a --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/overview.md @@ -0,0 +1,95 @@ +# Single Layer Solution: Overview + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Index", + "Path": "solution-templates/single-layer-web-application/index" + }, + "Next": { + "Name": "Solution Structure", + "Path": "solution-templates/single-layer-web-application/solution-structure" + } +} +```` + +> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. + +This document explains what the Single-Layer solution template offers. + +## Pre-Installed Libraries & Services + +The following **libraries and services** come **pre-installed** and **configured** for both **development** and **production** environments. After creating your solution, you can **modify** or **remove** most of them as needed. + +* **[Autofac](https://autofac.org/)** for [Dependency Injection](../../framework/fundamentals/dependency-injection.md). +* **[Serilog](https://serilog.net/)** with File and Console [logging](../../framework/fundamentals/logging.md) providers. +* **[Swagger](https://swagger.io/)** for exploring and testing HTTP APIs. +* **[OpenIddict](https://github.com/openiddict/openiddict-core)** as the built-in authentication server. + +## Pre-Configured Features + +The solution comes with the following built-in and pre-configured features: + +* **Authentication** is fully configured based on best practices. +* **[Permission](../../framework/fundamentals/authorization.md)** (authorization), **[setting](../../framework/infrastructure/settings.md)**, **[feature](../../framework/infrastructure/features.md)** and the **[localization](../../framework/fundamentals/localization.md)** management systems are pre-configured and ready to use. +* **[Background job system](../../framework/infrastructure/background-jobs/index.md)**. +* **[BLOB storge](../../framework/infrastructure/blob-storing/index.md)** system is installed with the [database provider](../../framework/infrastructure/blob-storing/database.md). +* **On-the-fly database migration** system (services automatically migrated their database schema when you deploy a new version). **\*** +* **[Swagger](https://swagger.io/)** authentication is configured to test the authorized HTTP APIs. + +## Fundamental Modules + +The following modules are pre-installed and configured for the solution: + +* **[Account](../../modules/account.md)** to authenticate users (login, register, two factor auth **\***, etc) +* **[Identity](../../modules/identity.md)** to manage roles and users +* **[OpenIddict](../../modules/openiddict.md)** (the core part) to implement the OAuth authentication flows + +In addition, [Feature Management](../../modules/feature-management.md), [Permission Management](../../modules/permission-management.md) and [Setting Management](../../modules/setting-management.md) modules are pre-installed as they are the fundamental feature modules of the ABP. + +## Optional Modules + +The following modules are optionally included in the solution, so you can select the ones you need: + +* **[Audit Logging](../../modules/audit-logging.md)** +* **[Chat](../../modules/chat.md)** **\*** +* **[File Management](../../modules/file-management.md)** **\*** +* **[GDPR](../../modules/gdpr.md)** **\*** +* **[Language Management](../../modules/language-management.md)** **\*** +* **[OpenIddict (Management UI)](../../modules/openiddict.md)** **\*** +* **[Tenant Management](../../modules/tenant-management.md) (Multi-Tenancy) or [SaaS](../../modules/saas.md)** **\*** +* **[Text Template Management](../../modules/text-template-management.md)** **\*** + +## UI Theme + +The **[LeptonX Lite](../../ui-themes/lepton-x-lite/index.md) or [LeptonX theme](https://leptontheme.com/)** **\*** is pre-configured for the solution. You can select one of the color palettes (System, Light, or Dark) as default, while the end-user dynamically change it on the fly. + +## Other Options + +Single-layer startup template asks for some preferences while creating your solution. + +### Database Providers + +There are two database provider options are provided on a new solution creation: + +* **[Entity Framework Core](../../framework/data/entity-framework-core/index.md)** with SQL Server, MySQL and PostgreSQL DBMS options. You can [switch to another DBMS](../../framework/data/entity-framework-core/other-dbms.md) manually after creating your solution. +* **[MongoDB](../../framework/data/mongodb/index.md)** + +### UI Frameworks + +The solution comes with a main web application with the following UI Framework options: + +* **None** (doesn't include a UI application to the solution) +* **Angular** +* **MVC / Razor Pages UI** +* **Blazor WebAssembly** +* **Blazor Server** + +### Multi-Tenancy & SaaS Module **\*** + +The **[SaaS module](../../modules/saas.md)** is included as an option. When you select it, the **[multi-tenancy](../../framework/architecture/multi-tenancy/index.md)** system is automatically configured. Otherwise, the system will not include any multi-tenancy overhead. + +## See Also + +* [Quick Start: Creating a Single Layer Web Application with ABP Studio](../../get-started/single-layer-web-application.md) diff --git a/docs/en/solution-templates/single-layer-web-application/solution-structure.md b/docs/en/solution-templates/single-layer-web-application/solution-structure.md new file mode 100644 index 0000000000..45448b46b4 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/solution-structure.md @@ -0,0 +1,71 @@ +# Single Layer Solution: The Structure + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Overview", + "Path": "solution-templates/single-layer-web-application/overview" + }, + "Next": { + "Name": "Main Components", + "Path": "solution-templates/single-layer-web-application/main-components" + } +} +```` + +> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. + +This document explains the solution and folder structure of ABP Studio's [single layer solution template](index.md). + +> This document assumes that you've created a new single-layer solution by following the *[Quick Start: Creating a Single Layer Web Application with ABP Studio](../../get-started/single-layer-web-application.md)* guide. (Choose the *Entity Framework Core* as the database provider.) + +## Understanding the ABP Solution Structure + +The single-layer solution template is designed to be simple and easy to understand. It includes a single project that contains all the necessary components to build a monolithic application. The solution structure is as follows: + +![single-layer-solution-in-explorer](images/single-layer-solution-in-explorer.png) + +`Acme.Bookstore` is the main **ABP Studio module** in the solution. It also includes the **ABP Studio package** `Acme.Bookstore` as the host application. + +> Refer to the *[Concepts](../../studio/concepts.md)* document for a comprehensive definition of ABP Studio solution, module, and package terms. + +## The Solution Structure + +If you create the solution based on *[Quick Start: Creating a Single Layer Web Application with ABP Studio](../../get-started/single-layer-web-application.md)* guide, the solution structure will be as follows: + +![single-layer-solution-in-visual-studio](images/single-layer-solution-in-visual-studio.png) + +### Folder Structure + +This template uses a single-project structure, with concerns separated into folders instead of projects. The pre-defined folders are shown below: + +![single-layer-solution-folders](images/single-layer-solution-folders.png) + +* **Data**: Define your database mappings (for [EF Core](../../framework/data/entity-framework-core) or [MongoDB](../../framework/data/mongodb) and [repositories](../../framework/architecture/domain-driven-design/repositories.md)) in this folder. +* **Entities**: Define your [entities](../../framework/architecture/domain-driven-design/entities.md) in this folder. +* **Localization**: Define your UI localization keys/values in this folder. +* **Menus**: Define your UI menu items in this folder. +* **Migrations**: Contains the database migration files. It is created automatically by EF Core. +* **ObjectMapping**: Define your [object-to-object mapping](../../framework/infrastructure/object-to-object-mapping.md) classes in this folder. +* **Pages**: Define your UI pages (Razor Pages) in this folder (create `Controllers` and `Views` folders yourself if you prefer the MVC pattern). +* **Permissions**: Define your [permissions](../../framework/fundamentals/authorization.md) in this folder. +* **Services**: Define your [application services](../../framework/architecture/domain-driven-design/application-services.md) in this folder. + +### How to Run? + +When you create a new solution it automatically creates initial migration and run database migrator for you (unless you uncheck these options). However, you can run the following command in the directory of your project (in the same folder of the `.csproj` file) to create the database and seed the initial data: + +```bash +dotnet run --migrate-database +``` + +This command will create the database and seed the initial data for you. Then you can run the application with the ABP Studio [Solution Runner](../../studio/running-applications.md). The default username is `admin` and the password is `1q2w3E*`. + +![solution-runner](images/solution-runner.png) + +> While creating a database & applying migrations seem only necessary for relational databases, you should run this command even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application. + +## See Also + +* [Video tutorial](https://abp.io/video-courses/essentials/app-template) \ No newline at end of file diff --git a/docs/en/solution-templates/single-layer-web-application/swagger-integration.md b/docs/en/solution-templates/single-layer-web-application/swagger-integration.md new file mode 100644 index 0000000000..bd6ddcf584 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/swagger-integration.md @@ -0,0 +1,19 @@ +# Single Layer Solution: Swagger Integration + +```json +//[doc-nav] +{ + "Previous": { + "Name": "Logging (with Serilog)", + "Path": "solution-templates/single-layer-web-application/logging" + }, + "Next": { + "Name": "Multi-Tenancy", + "Path": "solution-templates/single-layer-web-application/multi-tenancy" + } +} +``` + +[Swagger](https://swagger.io/) is a tool that helps to create, document, and consume RESTful web services. It provides a user interface to interact with the APIs and also a way to generate client SDKs for the APIs. + +In the [Swagger Integration](../../framework/api-development/swagger.md) document, you can find general information about Swagger integration with ABP Framework. diff --git a/docs/en/solution-templates/single-layer-web-application/web-applications.md b/docs/en/solution-templates/single-layer-web-application/web-applications.md new file mode 100644 index 0000000000..94945ba757 --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/web-applications.md @@ -0,0 +1,72 @@ +# Single Layer Solution: Web Applications + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Main Components", + "Path": "solution-templates/single-layer-web-application/main-components" + }, + "Next": { + "Name": "Db Migrator", + "Path": "solution-templates/single-layer-web-application/db-migrator" + } +} +```` + +The single-layer solution template includes a web application project that acts as the main application. This ASP.NET Core application hosts the API endpoints and may also serve the user interface, depending on the selected UI framework. + +- **MVC / Razor Pages**: This is an ASP.NET Core MVC application. It is a traditional web application that serves HTML pages to users and is suitable for building web applications with server-side rendering. +- **Angular**: This is an Angular application, a single-page application (SPA) that runs on the client side. It communicates with the server using HTTP requests and is ideal for building modern web applications with rich user interfaces. +- **Blazor UI**: A flexible framework for building web applications with .NET. It supports various hosting models: + - **Blazor WebAssembly**: This is a client-side SPA that runs entirely in the user's browser. It communicates with the server using HTTP requests and is suitable for modern web applications with rich interactivity and offline capabilities. + - **Blazor Server**: This is a server-side SPA that runs on the server and communicates with the client in real time using SignalR. It is ideal for applications requiring constant connectivity and rapid server updates. +- **No UI**: This option creates a backend-only solution without a web interface, suitable for scenarios like API-only applications or headless services. + +You can select the web application type that fits your requirements during the solution creation process in the *UI Framework* step. The single-layer solution template generates the selected web applications with the necessary configurations and integrations. + +![Web Applications](images/web-applications.png) + +## MVC / Razor Pages + +MVC (Model-View-Controller) is a design pattern commonly used for building web applications. Razor Pages, on the other hand, is a page-based programming model designed to make building web applications simpler and more productive. + +When you select the MVC / Razor Pages option in the single-layer solution template, it generates an ASP.NET Core MVC application named something like `Acme.BookStore`. This application serves as the web interface for your solution, using server-side rendering to deliver dynamic HTML pages to users. + +## Angular + +Angular is a popular front-end framework for building single-page applications (SPAs). It offers a rich set of features for creating modern web applications with dynamic and interactive user interfaces. + +When you select the Angular option in the single-layer solution template, it generates: +- An Angular application located under the solution's root folder, typically named `angular`. +- An ASP.NET Core application, usually named something like `Acme.Bookstore`. + +The Angular application runs as a client-side SPA in the user's browser and communicates with the server by sending HTTP requests to the ASP.NET Core host application. + +## Blazor UI + +Blazor is a flexible framework for building web applications with .NET. It supports various hosting models, including Blazor WebAssembly, Blazor Server, Blazor WebApp, and Maui Blazor (Hybrid). + +### Blazor WebAssembly + +Blazor WebAssembly is a client-side SPA that runs entirely in the user's browser. It communicates with the server using HTTP requests and is suitable for modern web applications with rich interactivity and offline capabilities. + +When you select the Blazor WebAssembly option in the Layered Solution Template, it generates: +- A Blazor application located under the solution's root folder, typically named `*.Blazor`, which serves as the main Blazor host project. +- A Blazor client application, named `*.Blazor.Client`, where you can write the client-side (UI logic) code. +- An ASP.NET Core application, named `*.HttpApi.Host`, where the server-side (business logic) code runs. + +The Blazor client application communicates with the server by sending HTTP requests to the `*.HttpApi.Host` application. + +### Blazor Server + +Blazor Server is a server-side SPA that runs on the server and communicates with the client in real time using SignalR. It is ideal for applications requiring constant connectivity and rapid server updates. + +When you select the Blazor Server option in the Layered Solution Template, it generates: +- A Blazor application located under the solution's root folder, typically named `*.Blazor`, which serves as the main Blazor host project. + +## No UI + +This option creates a backend-only solution without a web interface, suitable for scenarios like API-only applications or headless services. + +When you select the No UI option in the Layered Solution Template, it generates an ASP.NET Core application named `*.HttpApi.Host` that serves as the backend API for your solution. diff --git a/docs/en/tutorials/book-store/images/maui-blazor-add-books-component.png b/docs/en/tutorials/book-store/images/maui-blazor-add-books-component.png new file mode 100644 index 0000000000..72cf46e620 Binary files /dev/null and b/docs/en/tutorials/book-store/images/maui-blazor-add-books-component.png differ diff --git a/docs/en/tutorials/book-store/part-01.md b/docs/en/tutorials/book-store/part-01.md index 91700a1a25..51bfcd1b09 100644 --- a/docs/en/tutorials/book-store/part-01.md +++ b/docs/en/tutorials/book-store/part-01.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp","NG","MAUIBlazor"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-02.md b/docs/en/tutorials/book-store/part-02.md index 3ff19437cd..43fcb55d47 100644 --- a/docs/en/tutorials/book-store/part-02.md +++ b/docs/en/tutorials/book-store/part-02.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp", "NG"], + "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp", "NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` @@ -518,14 +518,17 @@ Now you can see the final result on your browser: ## Create a Books Page -It's time to create something visible and usable! Right click on the `Pages` folder under the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add a new **razor component**, named `Books.razor`: +It's time to create something visible and usable! Right click on the `Pages` folder under the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else if UI == "Blazor" || UI == "BlazorWebApp" }}`Acme.BookStore.Blazor.Client`{{else}} `Acme.BookStore.MauiBlazor` {{ end }} project and add a new **razor component**, named `Books.razor`: {{ if UI == "Blazor" || UI == "BlazorWebApp" }} ![blazor-add-books-component](images/blazor-add-books-component-client.png) -{{ else }} +{{ else if UI == "BlazorServer" }} ![blazor-add-books-component](images/blazor-add-books-component.png) +{{ else if UI == "MAUIBlazor" }} +![maui-blazor-add-books-component](images/maui-blazor-add-books-component.png) {{ end }} + Replace the contents of this component as shown below: ````html @@ -540,7 +543,7 @@ Replace the contents of this component as shown below: ### Add the Books Page to the Main Menu -Open the `BookStoreMenuContributor` class in the {{ if UI == "BlazorServer"}}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project add the following code to the end of the `ConfigureMainMenuAsync` method: +Open the `BookStoreMenuContributor` class in the {{ if UI == "BlazorServer"}}`Acme.BookStore.Blazor`{{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project add the following code to the end of the `ConfigureMainMenuAsync` method: ````csharp context.Menu.AddItem( diff --git a/docs/en/tutorials/book-store/part-03.md b/docs/en/tutorials/book-store/part-03.md index fc4e851b94..45444ee76f 100644 --- a/docs/en/tutorials/book-store/part-03.md +++ b/docs/en/tutorials/book-store/part-03.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` @@ -1101,7 +1101,7 @@ Clicking the "Delete" action calls the `delete` method which then shows a confir {{end}} -{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} +{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" || UI == "MAUIBlazor"}} ## Creating a New Book @@ -1292,13 +1292,13 @@ We can now define a modal to edit the book. Add the following code to the end of The base `AbpCrudPageBase` uses the [object to object mapping](../../framework/infrastructure/object-to-object-mapping.md) system to convert an incoming `BookDto` object to a `CreateUpdateBookDto` object. So, we need to define the mapping. -Open the `BookStoreBlazorAutoMapperProfile` inside the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and change the content as the following: +Open the `BookStoreBlazorAutoMapperProfile` inside the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor` {{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor` {{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and change the content as the following: ````csharp using Acme.BookStore.Books; using AutoMapper; -{{ if UI == "BlazorServer" }}namespace Acme.BookStore.Blazor;{{ else }}namespace Acme.BookStore.Blazor.Client;{{ end }} +{{ if UI == "BlazorServer" }}namespace Acme.BookStore.Blazor; {{ else if UI == "MAUIBlazor" }}namespace Acme.BookStore.MauiBlazor; {{ else }}namespace Acme.BookStore.Blazor.Client;{{ end }} public class BookStoreBlazorAutoMapperProfile : Profile { diff --git a/docs/en/tutorials/book-store/part-04.md b/docs/en/tutorials/book-store/part-04.md index 4ab950b0e1..fba15db253 100644 --- a/docs/en/tutorials/book-store/part-04.md +++ b/docs/en/tutorials/book-store/part-04.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-05.md b/docs/en/tutorials/book-store/part-05.md index d4815c5a96..0acc5cac9f 100644 --- a/docs/en/tutorials/book-store/part-05.md +++ b/docs/en/tutorials/book-store/part-05.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` @@ -389,11 +389,11 @@ Open the `/src/app/book/book.component.html` file and replace the edit and delet * Added `*abpPermission="'BookStore.Books.Edit'"` that hides the edit action if the current user has no editing permission. * Added `*abpPermission="'BookStore.Books.Delete'"` that hides the delete action if the current user has no delete permission. -{{else if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} +{{else if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" || UI == "MAUIBlazor"}} ### Authorize the Razor Component -Open the `/Pages/Books.razor` file in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add an `Authorize` attribute just after the `@page` directive and the following namespace imports (`@using` lines), as shown below: +Open the `/Pages/Books.razor` file in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor` {{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor` {{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add an `Authorize` attribute just after the `@page` directive and the following namespace imports (`@using` lines), as shown below: ````html @page "/books" @@ -481,7 +481,7 @@ You can run and test the permissions. Remove a book related permission from the Even we have secured all the layers of the book management page, it is still visible on the main menu of the application. We should hide the menu item if the current user has no permission. -Open the `BookStoreMenuContributor` class in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project, find the code block below: +Open the `BookStoreMenuContributor` class in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project, find the code block below: ````csharp context.Menu.AddItem( diff --git a/docs/en/tutorials/book-store/part-06.md b/docs/en/tutorials/book-store/part-06.md index 05e1d04460..d24b68f569 100644 --- a/docs/en/tutorials/book-store/part-06.md +++ b/docs/en/tutorials/book-store/part-06.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp", "NG"], + "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp", "NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-07.md b/docs/en/tutorials/book-store/part-07.md index b8aa17ace8..0708ecfcb9 100644 --- a/docs/en/tutorials/book-store/part-07.md +++ b/docs/en/tutorials/book-store/part-07.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-08.md b/docs/en/tutorials/book-store/part-08.md index 679b6d84ca..a7d73f0209 100644 --- a/docs/en/tutorials/book-store/part-08.md +++ b/docs/en/tutorials/book-store/part-08.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-09.md b/docs/en/tutorials/book-store/part-09.md index d481dbe92e..5bf9f90af1 100644 --- a/docs/en/tutorials/book-store/part-09.md +++ b/docs/en/tutorials/book-store/part-09.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` @@ -848,13 +848,13 @@ That's all! This is a fully working CRUD page, you can create, edit and delete a {{end}} -{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} +{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" || UI == "MAUIBlazor"}} ## The Author Management Page ### Authors Razor Component -Create a new Razor Component Page, `/Pages/Authors.razor`, in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project with the following content: +Create a new Razor Component Page, `/Pages/Authors.razor`, in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project with the following content: ````xml @page "/authors" @@ -1055,7 +1055,7 @@ using Blazorise.DataGrid; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; -{{ if UI == "BlazorServer" }}namespace Acme.BookStore.Blazor.Pages;{{ else }}namespace Acme.BookStore.Blazor.Client.Pages;{{ end }} +{{ if UI == "BlazorServer" }}namespace Acme.BookStore.Blazor.Pages;{{ else if UI == "MAUIBlazor" }}namespace Acme.BookStore.MauiBlazor.Pages;{{ else }}namespace Acme.BookStore.Blazor.Client.Pages;{{ end }} public partial class Authors { @@ -1201,7 +1201,7 @@ This class typically defines the properties and methods used by the `Authors.raz `Authors` class uses the `IObjectMapper` in the `OpenEditAuthorModal` method. So, we need to define this mapping. -Open the `BookStoreBlazorAutoMapperProfile.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following mapping code in the constructor: +Open the `BookStoreBlazorAutoMapperProfile.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following mapping code in the constructor: ````csharp CreateMap(); @@ -1211,7 +1211,7 @@ You will need to declare a `using Acme.BookStore.Authors;` statement to the begi ### Add to the Main Menu -Open the `BookStoreMenuContributor.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following code to the end of the `ConfigureMainMenuAsync` method: +Open the `BookStoreMenuContributor.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following code to the end of the `ConfigureMainMenuAsync` method: ````csharp context.Menu.AddItem(new ApplicationMenuItem( diff --git a/docs/en/tutorials/book-store/part-10.md b/docs/en/tutorials/book-store/part-10.md index c4383aa5c9..d4137e3681 100644 --- a/docs/en/tutorials/book-store/part-10.md +++ b/docs/en/tutorials/book-store/part-10.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG", "MAUIBlazor"], "DB": ["EF","Mongo"] } ```` @@ -105,7 +105,7 @@ migrationBuilder.AddForeignKey( * Creates an index on the `AuthorId` field. * Declares the foreign key to the `AppAuthors` table. -> If you are using Visual Studio, you may want to use `Add-Migration Added_AuthorId_To_Book -c BookStoreDbContext` and `Update-Database -Context BookStoreDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore` is the *Default Project* in PMC. +> If you are using Visual Studio, you may want to use `Add-Migration Added_AuthorId_To_Book -c BookStoreDbContext` and `Update-Database -Context BookStoreDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer" || UI=="BlazorWebApp"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG" || UI=="MAUIBlazor"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore` is the *Default Project* in PMC. {{end}} @@ -1071,11 +1071,11 @@ That's all. Just run the application and try to create or edit an author. {{end}} -{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" }} +{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" || UI == "MAUIBlazor" }} ### The Book List -It is very easy to show the *Author Name* in the book list. Open the `/Pages/Books.razor` file in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following `DataGridColumn` definition just after the `Name` (book name) column: +It is very easy to show the *Author Name* in the book list. Open the `/Pages/Books.razor` file in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor` {{ else if UI == "MAUIBlazor" }}`Acme.BookStore.MauiBlazor` {{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following `DataGridColumn` definition just after the `Name` (book name) column: ````xml You must have an ABP Team or a higher license to be able to create a mobile application. + +Mobile application development tutorials are designed for developers who have completed [the web development part of the tutorial](../book-store/index.md) and wish to continue building the mobile version of the application. + +## Tutorials + +You can choose between two mobile applications: [**.NET MAUI**](../../framework/ui/maui/index.md) or [**React Native**](../../framework/ui/react-native/index.md). Choose your framework and continue building your mobile application! + +- Both guides assume you have completed the web development section of the tutorial and have the necessary backend APIs in place. +- Each guide is self-contained and provides step-by-step instructions to build the mobile app. + +### .NET MAUI + +The .NET MAUI tutorial walks you through creating a mobile version of your bookstore app using .NET technologies. + +* [.NET MAUI - Mobile Application Tutorial](./maui/index.md) +* [Source Code](https://abp.io/Account/Login?returnUrl=/api/download/samples/bookstore-maui-efcore-mobile) + +### React Native + +The React Native tutorial provides instructions for building the bookstore app using JavaScript. + +* [React Native - Mobile Application Tutorial](./react-native/index.md) +* [Source Code](https://abp.io/Account/Login?returnUrl=/api/download/samples/bookstore-react-native-mongodb) \ No newline at end of file diff --git a/docs/en/tutorials/mobile/maui/index.md b/docs/en/tutorials/mobile/maui/index.md index a9f1f92d75..c9bb520e57 100644 --- a/docs/en/tutorials/mobile/maui/index.md +++ b/docs/en/tutorials/mobile/maui/index.md @@ -2,6 +2,8 @@ ## About This Tutorial +> You must have an ABP Team or a higher license to be able to create a mobile application. + This tutorial assumes that you have completed the [Web Application Development tutorial](../../book-store/part-01.md) and built an ABP based application named `Acme.BookStore` with [MAUI](../../../get-started/maui.md) as the mobile option. Therefore, if you haven't completed the [Web Application Development tutorial](../../book-store/part-01.md), you either need to complete it or download the source code from down below and follow this tutorial. In this tutorial, we will only focus on the UI side of the `Acme.BookStore` application and we will implement the CRUD operations for a MAUI mobile application. This tutorial follows the [MVVM (Model-View-ViewModel) Pattern ](https://learn.microsoft.com/en-us/dotnet/architecture/maui/mvvm), which separates the UI from the business logic of an application. diff --git a/docs/en/tutorials/mobile/react-native/index.md b/docs/en/tutorials/mobile/react-native/index.md index 74abfa3418..2dfa3df957 100644 --- a/docs/en/tutorials/mobile/react-native/index.md +++ b/docs/en/tutorials/mobile/react-native/index.md @@ -4,6 +4,8 @@ React Native mobile option is *available for* ***Team*** *or higher licenses*. T ## About This Tutorial +> You must have an ABP Team or a higher license to be able to create a mobile application. + - This tutorial assumes that you have completed the [Web Application Development tutorial](../../book-store/part-01.md) and built an ABP based application named `Acme.BookStore` with [React Native](../../../framework/ui/react-native) as the mobile option.. Therefore, if you haven't completed the [Web Application Development tutorial](../../book-store/part-01.md), you either need to complete it or download the source code from down below and follow this tutorial. - In this tutorial, we will only focus on the UI side of the `Acme.BookStore` application and will implement the CRUD operations. - Before starting, please make sure that the [React Native Development Environment](../../../framework/ui/react-native/index.md) is ready on your machine. diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.Designer.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.Designer.cs index 9d30ea018c..4fe8e51000 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.Designer.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.Designer.cs @@ -27,20 +27,100 @@ using Volo.Abp.AspNetCore.RazorViews; #line hidden #nullable disable WriteLiteral(@" - - - - Error - The Libs folder is missing! - - -

⚠️ The Libs folder under the wwwroot/libs directory is empty!

- + + + + + + Error - The Libs Folder is Missing! + + + +
+

⚠️ The Libs folder is missing!

+
+

The Libs folder contains mandatory NPM Packages for running the project.

- -

Make sure you run the abp install-libs CLI tool command.

- -

For more information, check out the ABP CLI documentation

- +

Make sure you run the abp install-lib"); + WriteLiteral(@"s CLI tool command.

+

+ If your application does not use any client-side libraries, you can disable this check by setting + AbpMvcLibsOptions.CheckLibs to false, as shown below: +

+
+Configure<AbpMvcLibsOptions>(options =>
+{
+    options.CheckLibs = false;
+});
+

For more information, check out the ABP CLI documentation.

+
+
+ © ABP Framework +
+ "); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.cshtml index 5a5d6c8d19..7b15ce94bf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsErrorPage.cshtml @@ -5,18 +5,96 @@ Response.StatusCode = 500; } - - - - Error - The Libs folder is missing! - - -

⚠️ The Libs folder under the wwwroot/libs directory is empty!

- + + + + + + Error - The Libs Folder is Missing! + + + +
+

⚠️ The Libs folder is missing!

+
+

The Libs folder contains mandatory NPM Packages for running the project.

- -

Make sure you run the abp install-libs CLI tool command.

- -

For more information, check out the ABP CLI documentation

- +

Make sure you run the abp install-libs CLI tool command.

+

+ If your application does not use any client-side libraries, you can disable this check by setting + AbpMvcLibsOptions.CheckLibs to false, as shown below: +

+
+Configure<AbpMvcLibsOptions>(options =>
+{
+    options.CheckLibs = false;
+});
+

For more information, check out the ABP CLI documentation.

+
+
+ © ABP Framework +
+ diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs index 410260674b..dc6faf723c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs @@ -64,7 +64,7 @@ public class AbpMvcLibsService : IAbpMvcLibsService, ITransientDependency var webHostEnvironment = httpContext.RequestServices.GetRequiredService(); if (webHostEnvironment.WebRootPath.IsNullOrWhiteSpace()) { - logger.LogWarning("The 'WebRootPath' is not set! The 'CheckLibs' feature is disabled!"); + logger.LogInformation("The 'WebRootPath' is not set, The 'CheckLibs' feature not needed."); return Task.FromResult(true); } @@ -72,7 +72,8 @@ public class AbpMvcLibsService : IAbpMvcLibsService, ITransientDependency var libsFolder = fileProvider.GetDirectoryContents("/libs"); if (!libsFolder.Exists || !libsFolder.Any()) { - logger.LogError("The 'wwwroot/libs' folder does not exist or empty!"); + logger.LogError("The 'wwwroot/libs' folder does not exist or empty! " + + "If your application does not use any client-side libraries, you can disable this check by setting 'AbpMvcLibsOptions.CheckLibs' to 'false'"); return Task.FromResult(false); } } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs index 4542dd32e1..2d231c46ee 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs @@ -23,6 +23,14 @@ public class AbpSecurityHeadersMiddleware : AbpMiddlewareBase, ITransientDepende public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { + var endpoint = context.GetEndpoint(); + + if (endpoint?.Metadata.GetMetadata() != null) + { + await next.Invoke(context); + return; + } + /*X-Content-Type-Options header tells the browser to not try and โ€œguessโ€ what a mimetype of a resource might be, and to just take what mimetype the server has returned as fact.*/ AddHeader(context, "X-Content-Type-Options", "nosniff"); @@ -35,14 +43,6 @@ public class AbpSecurityHeadersMiddleware : AbpMiddlewareBase, ITransientDepende var requestAcceptTypeHtml = context.Request.Headers["Accept"].Any(x => x!.Contains("text/html") || x.Contains("*/*") || x.Contains("application/xhtml+xml")); - var endpoint = context.GetEndpoint(); - - if (endpoint?.Metadata.GetMetadata() != null) - { - await next.Invoke(context); - return; - } - if (!requestAcceptTypeHtml || !Options.Value.UseContentSecurityPolicyHeader || await AlwaysIgnoreContentTypes(context) diff --git a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs index c66d74b381..3dfc5218d0 100644 --- a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs +++ b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs @@ -108,6 +108,11 @@ public static class AbpAuthorizationServiceExtensions return (await authorizationService.AuthorizeAsync(resource, policyName)).Succeeded; } + /// + /// Checks if CurrentPrincipal meets a specific authorization policy, throwing an if not. + /// + /// The providing authorization. + /// The name of the policy to evaluate. public static async Task CheckAsync(this IAuthorizationService authorizationService, string policyName) { if (!await authorizationService.IsGrantedAsync(policyName)) @@ -117,6 +122,12 @@ public static class AbpAuthorizationServiceExtensions } } + /// + /// Checks if CurrentPrincipal meets a specific requirement for the specified resource, throwing an if not. + /// + /// The providing authorization. + /// The resource to evaluate the policy against. + /// The requirement to evaluate the policy against. public static async Task CheckAsync(this IAuthorizationService authorizationService, object resource, IAuthorizationRequirement requirement) { if (!await authorizationService.IsGrantedAsync(resource, requirement)) @@ -126,6 +137,12 @@ public static class AbpAuthorizationServiceExtensions } } + /// + /// Checks if CurrentPrincipal meets a specific authorization policy against the specified resource, throwing an if not. + /// + /// The providing authorization. + /// The resource to evaluate the policy against. + /// The policy to evaluate. public static async Task CheckAsync(this IAuthorizationService authorizationService, object resource, AuthorizationPolicy policy) { if (!await authorizationService.IsGrantedAsync(resource, policy)) @@ -135,6 +152,11 @@ public static class AbpAuthorizationServiceExtensions } } + /// + /// Checks if CurrentPrincipal meets a specific authorization policy, throwing an if not. + /// + /// The providing authorization. + /// The policy to evaluate. public static async Task CheckAsync(this IAuthorizationService authorizationService, AuthorizationPolicy policy) { if (!await authorizationService.IsGrantedAsync(policy)) @@ -143,6 +165,12 @@ public static class AbpAuthorizationServiceExtensions } } + /// + /// Checks if CurrentPrincipal meets a specific authorization policy against the specified resource, throwing an if not. + /// + /// The providing authorization. + /// The resource to evaluate the policy against. + /// The requirements to evaluate the policy against. public static async Task CheckAsync(this IAuthorizationService authorizationService, object resource, IEnumerable requirements) { if (!await authorizationService.IsGrantedAsync(resource, requirements)) @@ -152,6 +180,12 @@ public static class AbpAuthorizationServiceExtensions } } + /// + /// Checks if CurrentPrincipal meets a specific authorization policy against the specified resource, throwing an if not. + /// + /// The providing authorization. + /// The resource to evaluate the policy against. + /// The name of the policy to evaluate. public static async Task CheckAsync(this IAuthorizationService authorizationService, object resource, string policyName) { if (!await authorizationService.IsGrantedAsync(resource, policyName)) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor index 29010dded6..2547a7930c 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor @@ -112,7 +112,7 @@ Sortable="@column.Sortable" Displayable="column.Visible"> - @(GetConvertedFieldValue(context, column)) + @((MarkupString)GetConvertedFieldValue(context, column))
} @@ -140,7 +140,7 @@ { if (column.ValueConverter != null) { - @(GetConvertedFieldValue(context, column)) + @((MarkupString)GetConvertedFieldValue(context, column)) } else { diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs index dacbb195ab..4f07c8a1c5 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs @@ -92,7 +92,7 @@ public abstract class EmailSenderBase : IEmailSender public virtual async Task QueueAsync(string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs? additionalEmailSendingArgs = null) { - ValidateEmailAddress(to); + await ValidateEmailAddressAsync(to); if (!BackgroundJobManager.IsAvailable()) { @@ -115,7 +115,7 @@ public abstract class EmailSenderBase : IEmailSender public virtual async Task QueueAsync(string from, string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs? additionalEmailSendingArgs = null) { - ValidateEmailAddress(to); + await ValidateEmailAddressAsync(to); if (!BackgroundJobManager.IsAvailable()) { @@ -176,13 +176,16 @@ public abstract class EmailSenderBase : IEmailSender } } - private static void ValidateEmailAddress(string emailAddress) + protected virtual Task ValidateEmailAddressAsync(string emailAddress) { - if(ValidationHelper.IsValidEmailAddress(emailAddress)) + try { - return; + _ = new MailAddressCollection { emailAddress }; + return Task.CompletedTask; + } + catch (Exception e) + { + throw new ArgumentException($"Email address '{emailAddress}' is not valid!"); } - - throw new ArgumentException($"Email address '{emailAddress}' is not valid!"); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj index db32e24bef..bfe9bea75a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj @@ -22,7 +22,6 @@ - diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs index f5953ea3b1..54ddfd0e5e 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventInbox.cs @@ -1,6 +1,7 @@ ๏ปฟusing System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -36,14 +37,21 @@ public class DbContextEventInbox : IDbContextEventInbox } [UnitOfWork] - public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingEventsAsync(int maxCount, Expression>? filter = null, CancellationToken cancellationToken = default) { var dbContext = await DbContextProvider.GetDbContextAsync(); + Expression>? transformedFilter = null; + if (filter != null) + { + transformedFilter = InboxOutboxFilterExpressionTransformer.Transform(filter)!; + } + var outgoingEventRecords = await dbContext .IncomingEvents .AsNoTracking() .Where(x => !x.Processed) + .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) .ToListAsync(cancellationToken: cancellationToken); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs index fecfd1e8ce..a541698b3e 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/DbContextEventOutbox.cs @@ -1,6 +1,7 @@ ๏ปฟusing System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -28,13 +29,20 @@ public class DbContextEventOutbox : IDbContextEventOutbox> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingEventsAsync(int maxCount, Expression>? filter = null, CancellationToken cancellationToken = default) { var dbContext = (IHasEventOutbox)await DbContextProvider.GetDbContextAsync(); + Expression>? transformedFilter = null; + if (filter != null) + { + transformedFilter = InboxOutboxFilterExpressionTransformer.Transform(filter)!; + } + var outgoingEventRecords = await dbContext .OutgoingEvents .AsNoTracking() + .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) .ToListAsync(cancellationToken: cancellationToken); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs index 6cb37a72d5..be7da15890 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs @@ -8,6 +8,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents; public class IncomingEventRecord : BasicAggregateRoot, + IIncomingEventInfo, IHasExtraProperties, IHasCreationTime { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs index 7272c9ac30..625a93b25a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs @@ -8,6 +8,7 @@ namespace Volo.Abp.EntityFrameworkCore.DistributedEvents; public class OutgoingEventRecord : BasicAggregateRoot, + IOutgoingEventInfo, IHasExtraProperties, IHasCreationTime { diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventInbox.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventInbox.cs index 3700f74232..c154330495 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventInbox.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventInbox.cs @@ -1,5 +1,6 @@ ๏ปฟusing System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ public interface IEventInbox { Task EnqueueAsync(IncomingEventInfo incomingEvent); - Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default); + Task> GetWaitingEventsAsync(int maxCount, Expression>? filter = null, CancellationToken cancellationToken = default); Task MarkAsProcessedAsync(Guid id); diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventOutbox.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventOutbox.cs index 018747945c..bc538ef839 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventOutbox.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IEventOutbox.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ public interface IEventOutbox { Task EnqueueAsync(OutgoingEventInfo outgoingEvent); - Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default); + Task> GetWaitingEventsAsync(int maxCount, Expression>? filter = null, CancellationToken cancellationToken = default); Task DeleteAsync(Guid id); diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IIncomingEventInfo.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IIncomingEventInfo.cs new file mode 100644 index 0000000000..e52325b71f --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IIncomingEventInfo.cs @@ -0,0 +1,17 @@ +using System; +using Volo.Abp.Data; + +namespace Volo.Abp.EventBus.Distributed; + +public interface IIncomingEventInfo : IHasExtraProperties +{ + Guid Id { get; } + + string MessageId { get; } + + string EventName { get; } + + byte[] EventData { get; } + + DateTime CreationTime { get; } +} diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IOutgoingEventInfo.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IOutgoingEventInfo.cs new file mode 100644 index 0000000000..58dd4a9713 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IOutgoingEventInfo.cs @@ -0,0 +1,15 @@ +using System; +using Volo.Abp.Data; + +namespace Volo.Abp.EventBus.Distributed; + +public interface IOutgoingEventInfo : IHasExtraProperties +{ + Guid Id { get; } + + string EventName { get; } + + byte[] EventData { get; } + + DateTime CreationTime { get; } +} diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxOutboxFilterExpressionTransformer.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxOutboxFilterExpressionTransformer.cs new file mode 100644 index 0000000000..935e760546 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxOutboxFilterExpressionTransformer.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq.Expressions; + +namespace Volo.Abp.EventBus.Distributed; + +public static class InboxOutboxFilterExpressionTransformer +{ + public static Expression> Transform(Expression> originalExpression) + { + var originalParam = originalExpression.Parameters[0]; + var newParam = Expression.Parameter(typeof(TTarget), originalParam.Name); + var body = ReplaceParameter(originalExpression.Body, originalParam, newParam); + return Expression.Lambda>(body, newParam); + } + + private static Expression ReplaceParameter(Expression body, ParameterExpression oldParam, ParameterExpression newParam) + { + var visitor = new ParameterReplacer(oldParam, newParam); + return visitor.Visit(body); + } + + private class ParameterReplacer : ExpressionVisitor + { + private readonly ParameterExpression _oldParam; + private readonly ParameterExpression _newParam; + + public ParameterReplacer(ParameterExpression oldParam, ParameterExpression newParam) + { + _oldParam = oldParam; + _newParam = newParam; + } + + protected override Expression VisitParameter(ParameterExpression node) + { + return node == _oldParam ? _newParam : base.VisitParameter(node); + } + } +} diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs index ffd135845a..1be24a3d02 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs @@ -4,7 +4,7 @@ using Volo.Abp.Data; namespace Volo.Abp.EventBus.Distributed; -public class IncomingEventInfo : IHasExtraProperties +public class IncomingEventInfo : IIncomingEventInfo { public static int MaxEventNameLength { get; set; } = 256; diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs index 43e9c42bf8..74b5bca7d4 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs @@ -4,7 +4,7 @@ using Volo.Abp.Data; namespace Volo.Abp.EventBus.Distributed; -public class OutgoingEventInfo : IHasExtraProperties +public class OutgoingEventInfo : IOutgoingEventInfo { public static int MaxEventNameLength { get; set; } = 256; diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpEventBusBoxesOptions.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpEventBusBoxesOptions.cs index 67facf5d42..cc91cad5df 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpEventBusBoxesOptions.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpEventBusBoxesOptions.cs @@ -1,4 +1,5 @@ ๏ปฟusing System; +using System.Linq.Expressions; namespace Volo.Abp.EventBus.Distributed; @@ -14,11 +15,21 @@ public class AbpEventBusBoxesOptions /// public int InboxWaitingEventMaxCount { get; set; } + /// + /// Default: null, means all events + /// + public Expression>? InboxProcessorFilter { get; set; } + /// /// Default: 1000 /// public int OutboxWaitingEventMaxCount { get; set; } + /// + /// Default: null, means all events + /// + public Expression>? OutboxProcessorFilter { get; set; } + /// /// Period time of and /// Default: 2 seconds @@ -34,7 +45,7 @@ public class AbpEventBusBoxesOptions /// Default: 2 hours /// public TimeSpan WaitTimeToDeleteProcessedInboxEvents { get; set; } - + /// /// Default: true /// @@ -44,7 +55,9 @@ public class AbpEventBusBoxesOptions { CleanOldEventTimeIntervalSpan = TimeSpan.FromHours(6); InboxWaitingEventMaxCount = 1000; + InboxProcessorFilter = null; OutboxWaitingEventMaxCount = 1000; + OutboxProcessorFilter = null; PeriodTimeSpan = TimeSpan.FromSeconds(2); DistributedLockWaitDuration = TimeSpan.FromSeconds(15); WaitTimeToDeleteProcessedInboxEvents = TimeSpan.FromHours(2); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs index e2c0a3c0c6..06014701a2 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -27,7 +28,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency protected DateTime? LastCleanTime { get; set; } - protected string DistributedLockName { get; private set; } = default!; + protected string DistributedLockName { get; set; } = default!; public ILogger Logger { get; set; } protected CancellationTokenSource StoppingTokenSource { get; } protected CancellationToken StoppingToken { get; } @@ -60,7 +61,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency await RunAsync(); } - public Task StartAsync(InboxConfig inboxConfig, CancellationToken cancellationToken = default) + public virtual Task StartAsync(InboxConfig inboxConfig, CancellationToken cancellationToken = default) { InboxConfig = inboxConfig; Inbox = (IEventInbox)ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); @@ -69,7 +70,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency return Task.CompletedTask; } - public Task StopAsync(CancellationToken cancellationToken = default) + public virtual Task StopAsync(CancellationToken cancellationToken = default) { StoppingTokenSource.Cancel(); Timer.Stop(cancellationToken); @@ -92,7 +93,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency while (true) { - var waitingEvents = await Inbox.GetWaitingEventsAsync(EventBusBoxesOptions.InboxWaitingEventMaxCount, StoppingToken); + var waitingEvents = await GetWaitingEventsAsync(); if (waitingEvents.Count <= 0) { break; @@ -129,6 +130,11 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency } } + protected virtual async Task> GetWaitingEventsAsync() + { + return await Inbox.GetWaitingEventsAsync(EventBusBoxesOptions.InboxWaitingEventMaxCount, EventBusBoxesOptions.InboxProcessorFilter, StoppingToken); + } + protected virtual async Task DeleteOldEventsAsync() { if (LastCleanTime != null && LastCleanTime + EventBusBoxesOptions.CleanOldEventTimeIntervalSpan > Clock.Now) diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs index 99ee06ca10..2e610d4471 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs @@ -22,7 +22,7 @@ public class OutboxSender : IOutboxSender, ITransientDependency protected IEventOutbox Outbox { get; private set; } = default!; protected OutboxConfig OutboxConfig { get; private set; } = default!; protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } - protected string DistributedLockName { get; private set; } = default!; + protected string DistributedLockName { get; set; } = default!; public ILogger Logger { get; set; } protected CancellationTokenSource StoppingTokenSource { get; } @@ -77,14 +77,14 @@ public class OutboxSender : IOutboxSender, ITransientDependency { while (true) { - var waitingEvents = await Outbox.GetWaitingEventsAsync(EventBusBoxesOptions.OutboxWaitingEventMaxCount, StoppingToken); + var waitingEvents = await GetWaitingEventsAsync(); if (waitingEvents.Count <= 0) { break; } Logger.LogInformation($"Found {waitingEvents.Count} events in the outbox."); - + if (EventBusBoxesOptions.BatchPublishOutboxEvents) { await PublishOutgoingMessagesInBatchAsync(waitingEvents); @@ -107,6 +107,11 @@ public class OutboxSender : IOutboxSender, ITransientDependency } } + protected virtual async Task> GetWaitingEventsAsync() + { + return await Outbox.GetWaitingEventsAsync(EventBusBoxesOptions.OutboxWaitingEventMaxCount, EventBusBoxesOptions.OutboxProcessorFilter, StoppingToken); + } + protected virtual async Task PublishOutgoingMessagesAsync(List waitingEvents) { foreach (var waitingEvent in waitingEvents) @@ -119,7 +124,7 @@ public class OutboxSender : IOutboxSender, ITransientDependency ); await Outbox.DeleteAsync(waitingEvent.Id); - + Logger.LogInformation($"Sent the event to the message broker with id = {waitingEvent.Id:N}"); } } @@ -129,9 +134,9 @@ public class OutboxSender : IOutboxSender, ITransientDependency await DistributedEventBus .AsSupportsEventBoxes() .PublishManyFromOutboxAsync(waitingEvents, OutboxConfig); - + await Outbox.DeleteManyAsync(waitingEvents.Select(x => x.Id).ToArray()); - + Logger.LogInformation($"Sent {waitingEvents.Count} events to message broker"); } } diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs index b954578ba6..4bc2a5433c 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs @@ -52,6 +52,11 @@ public static class FeatureCheckerExtensions return false; } + /// + /// Checks if the specified feature is enabled and throws an if it is not. + /// + /// The + /// The name of the feature to be checked. public static async Task CheckEnabledAsync(this IFeatureChecker featureChecker, string featureName) { if (!(await featureChecker.IsEnabledAsync(featureName))) @@ -61,6 +66,13 @@ public static class FeatureCheckerExtensions } } + /// + /// Checks if the specified features are enabled and throws an if they are not. + /// The check can either require all features to be enabled or just one, based on the parameter. + /// + /// The + /// True: Requires all features to be enabled. False: Requires at least one of the features to be enabled. + /// The names of the features to be checked. public static async Task CheckEnabledAsync(this IFeatureChecker featureChecker, bool requiresAll, params string[] featureNames) { if (featureNames.IsNullOrEmpty()) 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 55b40fa29b..6a73af27f5 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 @@ -1,6 +1,7 @@ ๏ปฟusing System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Options; @@ -50,16 +51,24 @@ public class MongoDbContextEventInbox : IMongoDbContextEventInb } [UnitOfWork] - public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingEventsAsync(int maxCount, Expression>? filter = null, CancellationToken cancellationToken = default) { var dbContext = await DbContextProvider.GetDbContextAsync(cancellationToken); + Expression>? transformedFilter = null; + if (filter != null) + { + transformedFilter = InboxOutboxFilterExpressionTransformer.Transform(filter)!; + } + var outgoingEventRecords = await dbContext .IncomingEvents .AsQueryable() .Where(x => !x.Processed) + .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 cc6c4d42df..57b59038b5 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 @@ -1,6 +1,7 @@ ๏ปฟusing System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; @@ -40,14 +41,22 @@ public class MongoDbContextEventOutbox : IMongoDbContextEventOu } [UnitOfWork] - public virtual async Task> GetWaitingEventsAsync(int maxCount, CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingEventsAsync(int maxCount, Expression>? filter = null, CancellationToken cancellationToken = default) { var dbContext = (IHasEventOutbox)await MongoDbContextProvider.GetDbContextAsync(cancellationToken); + Expression>? transformedFilter = null; + if (filter != null) + { + transformedFilter = InboxOutboxFilterExpressionTransformer.Transform(filter)!; + } + var outgoingEventRecords = await dbContext .OutgoingEvents.AsQueryable() + .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) + .As>() .ToListAsync(cancellationToken: cancellationToken); return outgoingEventRecords diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingOptions.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingOptions.cs index c8a06736b6..e4bbb4fe00 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingOptions.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingOptions.cs @@ -11,10 +11,17 @@ public class AbpSettingOptions public HashSet DeletedSettings { get; } + /// + /// Default: true. + /// This is useful when you change of an existing setting definition to true and don't want to lose the original value. + /// + public bool ReturnOriginalValueIfDecryptFailed { get; set; } + public AbpSettingOptions() { DefinitionProviders = new TypeList(); ValueProviders = new TypeList(); DeletedSettings = new HashSet(); + ReturnOriginalValueIfDecryptFailed = true; } } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs index 45a3362d30..2af6b7b4af 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs @@ -1,6 +1,7 @@ ๏ปฟusing System; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Encryption; @@ -10,10 +11,12 @@ public class SettingEncryptionService : ISettingEncryptionService, ITransientDep { protected IStringEncryptionService StringEncryptionService { get; } public ILogger Logger { get; set; } + protected IOptions Options { get; } - public SettingEncryptionService(IStringEncryptionService stringEncryptionService) + public SettingEncryptionService(IStringEncryptionService stringEncryptionService, IOptions options) { StringEncryptionService = stringEncryptionService; + Options = options; Logger = NullLogger.Instance; } @@ -40,7 +43,14 @@ public class SettingEncryptionService : ISettingEncryptionService, ITransientDep } catch (Exception e) { + if (Options.Value.ReturnOriginalValueIfDecryptFailed) + { + Logger.LogWarning(e, "Failed to decrypt the setting: {0}. Returning the original value...", settingDefinition.Name); + return encryptedValue; + } + Logger.LogException(e); + return string.Empty; } } diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 6e2383dcbd..47447e1fdf 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -1,4 +1,4 @@ -//#define MONGODB +#define MONGODB using System.Collections.Generic; using System.Globalization; @@ -26,9 +26,14 @@ using Volo.Abp.Autofac; using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring.Database; using Volo.Abp.Data; +#if MONGODB +using Volo.Abp.MongoDB; +#else using Volo.Abp.EntityFrameworkCore; +#endif using Volo.Abp.Identity; using Volo.Abp.Identity.Web; +using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement; using Volo.Abp.PermissionManagement.HttpApi; @@ -39,7 +44,11 @@ using Volo.Abp.VirtualFileSystem; using Volo.Blogging; using Volo.Blogging.Admin; using Volo.Blogging.Files; +#if MONGODB +using Volo.BloggingTestApp.MongoDB; +#else using Volo.BloggingTestApp.EntityFrameworkCore; +#endif namespace Volo.BloggingTestApp { @@ -78,7 +87,7 @@ namespace Volo.BloggingTestApp Configure(options => { options.RoutePrefix = null; - options.SingleBlogMode.Enabled = true; + options.SingleBlogMode.Enabled = false; }); Configure(options => @@ -146,6 +155,22 @@ namespace Volo.BloggingTestApp container.UseDatabase(); }); }); + + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "ุงู„ุนุฑุจูŠุฉ")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("cs", "cs", "ฤŒeลกtina")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Franรงais")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Tรผrkรงe")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Portuguรชs")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "็ฎ€ไฝ“ไธญๆ–‡")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "็นไฝ“ไธญๆ–‡")); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) diff --git a/modules/blogging/app/Volo.BloggingTestApp/Program.cs b/modules/blogging/app/Volo.BloggingTestApp/Program.cs index 2741daf2fe..cb0948096d 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Program.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/Program.cs @@ -1,6 +1,9 @@ ๏ปฟusing System; using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; using Serilog.Events; @@ -9,7 +12,7 @@ namespace Volo.BloggingTestApp { public class Program { - public static int Main(string[] args) + public async static Task Main(string[] args) { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() //TODO: Should be configurable! @@ -22,7 +25,14 @@ namespace Volo.BloggingTestApp try { Log.Information("Starting web host."); - CreateHostBuilder(args).Build().Run(); + var builder = WebApplication.CreateBuilder(args); + builder.Host + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); return 0; } catch (Exception ex) @@ -35,14 +45,5 @@ namespace Volo.BloggingTestApp Log.CloseAndFlush(); } } - - internal static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }) - .UseAutofac() - .UseSerilog(); } } diff --git a/modules/blogging/app/Volo.BloggingTestApp/Startup.cs b/modules/blogging/app/Volo.BloggingTestApp/Startup.cs deleted file mode 100644 index 0f4a310afc..0000000000 --- a/modules/blogging/app/Volo.BloggingTestApp/Startup.cs +++ /dev/null @@ -1,39 +0,0 @@ -๏ปฟusing System; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Volo.Abp; -using Volo.Abp.Localization; - -namespace Volo.BloggingTestApp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(); - - services.Configure(options => - { - options.Languages.Add(new LanguageInfo("ar", "ar", "ุงู„ุนุฑุจูŠุฉ")); - options.Languages.Add(new LanguageInfo("en", "en", "English")); - options.Languages.Add(new LanguageInfo("cs", "cs", "ฤŒeลกtina")); - options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); - options.Languages.Add(new LanguageInfo("fr", "fr", "Franรงais")); - options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); - options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); - options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); - options.Languages.Add(new LanguageInfo("tr", "tr", "Tรผrkรงe")); - options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Portuguรชs")); - options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "็ฎ€ไฝ“ไธญๆ–‡")); - options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "็นไฝ“ไธญๆ–‡")); - }); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) - { - app.InitializeApplication(); - } - } -} diff --git a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj index 4e58d52df0..e157d32f25 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj +++ b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj @@ -23,7 +23,7 @@ - + diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml index 926c8073ca..e0264603fb 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml @@ -2,12 +2,16 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor @using Volo.Blogging.Posts @using Microsoft.AspNetCore.Mvc.Localization +@using Microsoft.Extensions.Options +@using Volo.Blogging @using Volo.Blogging.Localization @using Volo.Blogging.Pages.Blogs.Posts @inject IHtmlLocalizer L @model Volo.Blogging.Pages.Blogs.Posts.EditModel +@inject IOptions BloggingUrlOptions @{ ViewBag.PageTitle = "Edit Blog Post"; + var blogShortNameRouteParam = BloggingUrlOptions.Value.SingleBlogMode.Enabled ? null : Model.BlogShortName; } @section styles { @@ -86,7 +90,7 @@ diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs index 231a8cddba..f19b9f41df 100644 --- a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs @@ -16,6 +16,9 @@ namespace Volo.Docs.Documents [JsonPropertyName("items")] public List Items { get; set; } + [JsonPropertyName("isLazyExpandable")] + public bool IsLazyExpandable { get; set; } + [JsonPropertyName("isIndex")] public bool IsIndex { get; set; } diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/DocumentNavigationController.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/DocumentNavigationController.cs new file mode 100644 index 0000000000..cac52e8d5f --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/DocumentNavigationController.cs @@ -0,0 +1,80 @@ +using System; +using System.Threading.Tasks; +using Asp.Versioning; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Docs.Areas.Models.DocumentNavigation; +using Volo.Docs.Documents; +using Volo.Docs.Utils; + +namespace Volo.Docs.Areas.Documents; + +[RemoteService(Name = DocsRemoteServiceConsts.RemoteServiceName)] +[Area(DocsRemoteServiceConsts.ModuleName)] +[ControllerName("DocumentNavigation")] +[Route("/docs/document-navigation")] +public class DocumentNavigationController : AbpController +{ + private readonly IDocumentAppService _documentAppService; + private readonly IDocsLinkGenerator _docsLinkGenerator; + + public DocumentNavigationController(IDocumentAppService documentAppService, IDocsLinkGenerator docsLinkGenerator) + { + _documentAppService = documentAppService; + _docsLinkGenerator = docsLinkGenerator; + } + + [HttpGet] + [Route("")] + public virtual async Task GetNavigationAsync(GetNavigationNodeWithLinkModel input) + { + var navigationNode = await _documentAppService.GetNavigationAsync(new GetNavigationDocumentInput + { + LanguageCode = input.LanguageCode, + Version = input.Version, + ProjectId = input.ProjectId + }); + + NormalPath(navigationNode, input); + + return navigationNode; + } + + protected virtual void NormalPath(NavigationNode node, GetNavigationNodeWithLinkModel input) + { + if (node.HasChildItems) + { + foreach (var item in node.Items) + { + NormalPath(item, input); + } + } + + if (UrlHelper.IsExternalLink(node.Path)) + { + return; + } + + node.Path = RemoveFileExtensionFromPath(node.Path, input.ProjectFormat); + if (node.Path.IsNullOrWhiteSpace()) + { + node.Path = "javascript:;"; + return; + } + + node.Path = _docsLinkGenerator.GenerateLink(input.ProjectName, input.LanguageCode, input.RouteVersion, node.Path); + } + + private string RemoveFileExtensionFromPath(string path, string projectFormat) + { + if (path == null) + { + return null; + } + + return path.EndsWith("." + projectFormat) + ? path.Left(path.Length - projectFormat.Length - 1) + : path; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index 6d2cb8c9ba..e6c75d0161 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -72,11 +72,14 @@ namespace Volo.Docs.Areas.Documents.TagHelpers var isAnyNodeOpenedInThisLevel = IsAnyNodeOpenedInThisLevel(node); - node.Items?.ForEach(innerNode => + if (!node.IsLazyExpandable || isAnyNodeOpenedInThisLevel) { - content += GetParentNode(innerNode, isAnyNodeOpenedInThisLevel); - }); - + node.Items?.ForEach(innerNode => + { + content += GetParentNode(innerNode, isAnyNodeOpenedInThisLevel); + }); + } + var result = node.IsEmpty ? content : GetLeafNode(node, content); return result; @@ -121,6 +124,11 @@ namespace Volo.Docs.Areas.Documents.TagHelpers listItemCss += " selected-tree"; } + if (node.IsLazyExpandable) + { + listItemCss += " lazy-expand"; + } + string listInnerItem; if (node.Path.IsNullOrEmpty() && node.IsLeaf) { diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Models/DocumentNavigation/GetNavigationNodeWithLinkModel.cs b/modules/docs/src/Volo.Docs.Web/Areas/Models/DocumentNavigation/GetNavigationNodeWithLinkModel.cs new file mode 100644 index 0000000000..085cc2de0e --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Areas/Models/DocumentNavigation/GetNavigationNodeWithLinkModel.cs @@ -0,0 +1,28 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; +using Volo.Docs.Language; +using Volo.Docs.Projects; + +namespace Volo.Docs.Areas.Models.DocumentNavigation; + +public class GetNavigationNodeWithLinkModel +{ + public Guid ProjectId { get; set; } + + [DynamicStringLength(typeof(ProjectConsts), nameof(ProjectConsts.MaxVersionNameLength))] + public string Version { get; set; } + + [Required] + [DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxLanguageCodeLength))] + public string LanguageCode { get; set; } + + [Required] + public string ProjectName { get; set; } + + [Required] + public string ProjectFormat { get; set; } + + [Required] + public string RouteVersion { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 976154c630..fb1f232cb3 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -53,6 +53,17 @@ @if (Model.LoadSuccess) { + 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 41896bb2fd..0cfbdff32f 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 @@ -1,5 +1,76 @@ +var doc = doc || {}; + (function ($) { $(function () { + + doc.lazyExpandableNavigation = { + isAllLoaded: false, + findNode : function(text, href, node){ + if(node.text === text && node.path === href && node.isLazyExpandable){ + return node; + } + if(node.items){ + for (let i = 0; i < node.items.length; i++) { + var result = doc.lazyExpandableNavigation.findNode(text, href, node.items[i]); + if(result){ + return result; + } + } + } + return null; + }, + renderNodeAsHtml : function($lazyLiElement, node, isRootLazyNode){ + if(node.isEmpty){ + return; + } + + var textCss = node.path === "javascript:;" ? "": "tree-toggle"; + var uiCss = isRootLazyNode ? "" : "style='display: none;'"; + var $ul = $(``); + var $li = $(`
  • `); + + $li.append(` ${node.text}`) + + if(node.isLazyExpandable){ + $li.addClass("lazy-expand"); + }else if(node.hasChildItems){ + node.items.forEach(function(item){ + doc.lazyExpandableNavigation.renderNodeAsHtml($li, item, false); + }); + } + + $ul.append($li); + $lazyLiElement.append($ul) + + window.Toc.helpers.initNavEvent(); + }, + loadAll : function(lazyLiElements){ + if(doc.lazyExpandableNavigation.isAllLoaded){ + return; + } + for(var i = 0; i < lazyLiElements.length; i++){ + var $li = $(lazyLiElements[i]); + if($li.has("ul").length === 0){ + var $a = $li.find("a"); + var node = doc.lazyExpandableNavigation.findNode($a.text(), $a.attr("href"), doc.project.navigation); + node.items.forEach(item => { + doc.lazyExpandableNavigation.renderNodeAsHtml($li, item, true); + }) + } + + var childLazyLiElements = $li.find("li.lazy-expand"); + if(childLazyLiElements.length > 0){ + doc.lazyExpandableNavigation.isAllLoaded = false; + doc.lazyExpandableNavigation.loadAll(childLazyLiElements); + } + + initLazyExpandNavigation(); + } + + doc.lazyExpandableNavigation.isAllLoaded = true; + } + } + var initNavigationFilter = function (navigationContainerId) { var $navigation = $('#' + navigationContainerId); @@ -23,6 +94,8 @@ return; } + doc.lazyExpandableNavigation.loadAll($navigation.find("li.lazy-expand")); + var filteredItems = $navigation .find('li > a') .filter(function () { @@ -98,6 +171,23 @@ }); }; + var initDocProject = function(){ + abp.ajax({ + type :"GET", + url: '/docs/document-navigation', + data: { + projectId: doc.project.id, + version: doc.project.version, + routeVersion: doc.project.routeVersion, + languageCode: doc.project.languageCode, + projectName: doc.project.name, + projectFormat: doc.project.format + } + }).done(data => { + doc.project.navigation = data; + }) + } + var initSocialShareLinks = function () { var pageHeader = $('.docs-body').find('h1, h2').first().text(); @@ -272,6 +362,26 @@ } }; + var initLazyExpandNavigation = function(){ + $("li .lazy-expand").off('click'); + $("li .lazy-expand").on('click', function(){ + var $this = $(this); + if($this.has("ul").length > 0){ + return; + } + + var $a = $this.find("a"); + var node = doc.lazyExpandableNavigation.findNode($a.text(), $a.attr("href") , doc.project.navigation); + node.items.forEach(item => { + doc.lazyExpandableNavigation.renderNodeAsHtml($this, item, true); + }) + + initLazyExpandNavigation(); + }); + } + + initDocProject(); + initNavigationFilter('sidebar-scroll'); initAnchorTags('.docs-page .docs-body'); @@ -279,6 +389,8 @@ initSocialShareLinks(); initSections(); + + initLazyExpandNavigation(); Element.prototype.querySelector = function (selector) { var result = $(this).find(decodeURI(selector)); diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js index 74767bf56b..5208ac99c0 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js @@ -1,23 +1,7 @@ (function ($) { $(function () { - $('li:not(.last-link) a.tree-toggle').click(function () { - $(this).parent().children('ul.tree').toggle(100); - $(this).closest('li').toggleClass('selected-tree'); - }); - - $('li:not(.last-link) span.plus-icon i.fa-chevron-right').click( - function () { - var $element = $(this).parent(); - var $filter = $('.docs-version #filter'); - if ($filter && $filter.val() != ''){ - return; - } - - $element.parent().children('ul.tree').toggle(100); - $element.closest('li').toggleClass('selected-tree'); - } - ); + window.Toc.helpers.initNavEvent(); var scrollTopBtn = $('.scroll-top-btn'); var enoughHeight = $('.docs-sidebar-wrapper > .docs-top').height(); @@ -159,6 +143,30 @@ $li.append($a); return $li; }; + + window.Toc.helpers.initNavEvent = function () { + $('li:not(.last-link) a.tree-toggle').off('click'); + $('li:not(.last-link) span.plus-icon i.fa-chevron-right').off('click'); + + $('li:not(.last-link) a.tree-toggle').click(function () { + $(this).parent().children('ul.tree').toggle(100); + $(this).closest('li').toggleClass('selected-tree'); + }); + + $('li:not(.last-link) span.plus-icon i.fa-chevron-right').click( + function () { + var $element = $(this).parent(); + var $filter = $('.docs-version #filter'); + + if ($filter && $filter.val() != ''){ + return; + } + + $element.parent().children('ul.tree').toggle(100); + $element.closest('li').toggleClass('selected-tree'); + } + ); + } function docsCriteria() { var docsContentWidth = $('.docs-content').width() - 74; diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs index 71185cf288..1232045903 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs @@ -1,10 +1,11 @@ ๏ปฟusing System; using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Entities; +using Volo.Abp.Auditing; namespace Volo.Abp.Identity; -public class IdentityRoleDto : ExtensibleEntityDto, IHasConcurrencyStamp +public class IdentityRoleDto : ExtensibleEntityDto, IHasConcurrencyStamp , IHasCreationTime { public string Name { get; set; } @@ -15,4 +16,6 @@ public class IdentityRoleDto : ExtensibleEntityDto, IHasConcurrencyStamp public bool IsPublic { get; set; } public string ConcurrencyStamp { get; set; } + + public DateTime CreationTime { get; set; } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySecurityLogRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySecurityLogRepository.cs index 8a1e50795f..af163253b4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySecurityLogRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySecurityLogRepository.cs @@ -21,6 +21,7 @@ public interface IIdentitySecurityLogRepository : IBasicRepository GetByUserIdAsync( diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs index 2f988948a3..98e0a26a6d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs @@ -1,10 +1,11 @@ ๏ปฟusing JetBrains.Annotations; using System; +using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; namespace Volo.Abp.Identity; -public class IdentityClaimType : AggregateRoot +public class IdentityClaimType : AggregateRoot, IHasCreationTime { public virtual string Name { get; protected set; } @@ -19,6 +20,8 @@ public class IdentityClaimType : AggregateRoot public virtual string Description { get; set; } public virtual IdentityClaimValueType ValueType { get; set; } + + public virtual DateTime CreationTime { get; protected set; } protected IdentityClaimType() { diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs index 68439c9d4b..bfe9e4546d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.Identity; /// /// Represents a role in the identity system /// -public class IdentityRole : AggregateRoot, IMultiTenant, IHasEntityVersion +public class IdentityRole : AggregateRoot, IMultiTenant, IHasEntityVersion, IHasCreationTime { public virtual Guid? TenantId { get; protected set; } @@ -53,6 +53,8 @@ public class IdentityRole : AggregateRoot, IMultiTenant, IHasEntityVersion /// A version value that is increased whenever the entity is changed. /// public virtual int EntityVersion { get; protected set; } + + public virtual DateTime CreationTime { get; protected set; } /// /// Initializes a new instance of . diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs index 0c9af27055..2fb073dc34 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs @@ -40,7 +40,7 @@ public class EfCoreIdentityClaimTypeRepository : EfCoreRepository u.Name.Contains(filter) ) - .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityClaimType.Name) : sorting) + .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityClaimType.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs index 293b786eca..9f6085339a 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs @@ -119,7 +119,7 @@ public class EfCoreIdentityRoleRepository : EfCoreRepository x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) - .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityRole.Name) : sorting) + .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityRole.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySecurityLogRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySecurityLogRepository.cs index 2043293395..808d7f48f4 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySecurityLogRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySecurityLogRepository.cs @@ -31,6 +31,7 @@ public class EfCoreIdentitySecurityLogRepository : EfCoreRepository securityLog.UserId == userId) .WhereIf(!userName.IsNullOrWhiteSpace(), securityLog => securityLog.UserName == userName) .WhereIf(!clientId.IsNullOrWhiteSpace(), securityLog => securityLog.ClientId == clientId) - .WhereIf(!correlationId.IsNullOrWhiteSpace(), securityLog => securityLog.CorrelationId == correlationId); + .WhereIf(!correlationId.IsNullOrWhiteSpace(), securityLog => securityLog.CorrelationId == correlationId) + .WhereIf(!clientIpAddress.IsNullOrWhiteSpace(), securityLog => securityLog.ClientIpAddress == clientIpAddress); } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index a05e59a1d0..86682b85db 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -232,7 +232,7 @@ public class EfCoreIdentityUserRepository : EfCoreRepository u.Name.Contains(filter) ) - .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityClaimType.Name) : sorting) + .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityClaimType.CreationTime) + " desc" : sorting) .As>() .PageBy>(skipCount, maxResultCount) .ToListAsync(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 ca67864975..3a57f69902 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 @@ -125,7 +125,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) - .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityRole.Name) : sorting) + .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityRole.CreationTime) + " desc" : sorting) .As>() .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 6a875444f9..f173272009 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 @@ -32,6 +32,7 @@ public class MongoIdentitySecurityLogRepository : string userName = null, string clientId = null, string correlationId = null, + string clientIpAddress = null, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -45,6 +46,7 @@ public class MongoIdentitySecurityLogRepository : userName, clientId, correlationId, + clientIpAddress, cancellationToken ); @@ -64,6 +66,7 @@ public class MongoIdentitySecurityLogRepository : string userName = null, string clientId = null, string correlationId = null, + string clientIpAddress = null, CancellationToken cancellationToken = default) { var query = await GetListQueryAsync( @@ -76,6 +79,7 @@ public class MongoIdentitySecurityLogRepository : userName, clientId, correlationId, + clientIpAddress, cancellationToken ); @@ -101,19 +105,19 @@ public class MongoIdentitySecurityLogRepository : string userName = null, string clientId = null, string correlationId = null, + string clientIpAddress = null, CancellationToken cancellationToken = default) { return (await GetMongoQueryableAsync(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) + .WhereIf(!applicationName.IsNullOrWhiteSpace(), securityLog => securityLog.ApplicationName == applicationName) .WhereIf(!identity.IsNullOrWhiteSpace(), securityLog => securityLog.Identity == identity) .WhereIf(!action.IsNullOrWhiteSpace(), securityLog => securityLog.Action == action) .WhereIf(userId.HasValue, securityLog => securityLog.UserId == userId) .WhereIf(!userName.IsNullOrWhiteSpace(), securityLog => securityLog.UserName == userName) .WhereIf(!clientId.IsNullOrWhiteSpace(), securityLog => securityLog.ClientId == clientId) - .WhereIf(!correlationId.IsNullOrWhiteSpace(), - securityLog => securityLog.CorrelationId == correlationId); + .WhereIf(!correlationId.IsNullOrWhiteSpace(), securityLog => securityLog.CorrelationId == correlationId) + .WhereIf(!clientIpAddress.IsNullOrWhiteSpace(), securityLog => securityLog.ClientIpAddress == clientIpAddress); } } 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 2c99f872ba..58486893ec 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 @@ -200,7 +200,7 @@ public class MongoIdentityUserRepository : MongoDbRepository>() .PageBy>(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); 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 f085b2eedc..c3a168033b 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 @@ -71,7 +71,7 @@ public class MongoOrganizationUnitRepository CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) - .OrderBy(sorting.IsNullOrEmpty() ? nameof(OrganizationUnit.DisplayName) : sorting) + .OrderBy(sorting.IsNullOrEmpty() ? nameof(OrganizationUnit.CreationTime) + " desc" : sorting) .As>() .PageBy>(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/index.js b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/index.js index fe2c4c5bba..b83db95758 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/index.js +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/index.js @@ -114,7 +114,7 @@ _dataTable = _$table.DataTable( abp.libs.datatables.normalizeConfiguration({ - order: [[1, 'asc']], + order: [], searching: false, processing: true, serverSide: true, diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/index.js b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/index.js index 320e7ff508..fa63b96af4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/index.js +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/index.js @@ -150,7 +150,7 @@ var _$table = _$wrapper.find('table'); _dataTable = _$table.DataTable( abp.libs.datatables.normalizeConfiguration({ - order: [[1, 'asc']], + order: [], processing: true, serverSide: true, scrollX: true, diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs index 88fdf44c72..3963e09630 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs @@ -24,7 +24,7 @@ public class EfCoreOpenIddictApplicationRepository : EfCoreRepository x.ClientId.Contains(filter)) - .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictApplication.ClientId) : sorting) + .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictApplication.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs index 754970c46d..87a609825f 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs @@ -27,7 +27,7 @@ public class EfCoreOpenIddictScopeRepository : EfCoreRepository x.ClientId.Contains(filter)) - .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictApplication.ClientId) : sorting) + .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictApplication.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) .As>() .ToListAsync(GetCancellationToken(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 4813695e02..3e16df4e9b 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 @@ -26,7 +26,7 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository>() .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs index a0b7de8c07..b2c998eb4f 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs @@ -55,8 +55,9 @@ public partial class PermissionManagementModal _grantedPermissionCount = 0; _notGrantedPermissionCount = 0; + Task.Run(()=>OnPermissionGroupSearchTextChangedAsync(null)); - foreach (var permission in _groups.SelectMany(x => x.Permissions)) + foreach (var permission in _allGroups.SelectMany(x => x.Permissions)) { if (!IsDisabledPermission(permission)) { diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js index 9f97800cbc..f783e944b8 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js @@ -4,7 +4,7 @@ var abp = abp || {}; abp.modals.PermissionManagement = function () { var l = abp.localization.getResource("AbpPermissionManagement"); - + function checkParents($tab, $checkBox) { var parentName = $checkBox .closest('.custom-checkbox') @@ -155,6 +155,7 @@ var abp = abp || {}; } function setSelectAllInAllTabs() { + var $checkBox = $('#SelectAllInAllTabs'); var anyIndeterminate = false; @@ -237,7 +238,7 @@ var abp = abp || {}; $('input[name="SelectAllInThisTab"]').each(function () { var $this = $(this); - if($this.is(':indeterminate') === true) { + if ($this.is(':indeterminate') === true) { $this.prop('indeterminate', false); $this.prop('checked', true); } @@ -268,14 +269,14 @@ var abp = abp || {}; var $form = $("#PermissionManagementForm"); var $submitButton = $form.find("button[type='submit']"); - if($submitButton) { + if ($submitButton) { $submitButton.click(function (e) { e.preventDefault(); - - if(!$form.find("input:checked").length > 0) { + + if (!$form.find("input:checked").length > 0) { abp.message.confirm(l("SaveWithoutAnyPermissionsWarningMessage")) .then(function (confirmed) { - if(confirmed) { + if (confirmed) { $form.submit(); } }); @@ -285,18 +286,24 @@ var abp = abp || {}; } }); } - - $permissionSearchInput = $('#permission-search'); - $permissionSearchInput.keyup(throttle(function() { + var $permissionSearchInput = $('#permission-search'); + + $permissionSearchInput.keyup(throttle(function () { var searchTerm = $permissionSearchInput.val().toLowerCase(); filterTabs(searchTerm); setFirstVisibleTabActive(); }, 300)); + $('#SelectAllInAllTabs').change(function () { + // Reset search input + $permissionSearchInput.val(''); + $permissionSearchInput.trigger('keyup'); + }); + function filterTabs(searchTerm) { var $tabs = $('#PermissionsTabs .nav-link'); - $tabs.each(function(i) { + $tabs.each(function (i) { var $tabItem = $(this); var $tab = $tabItem.parent(); @@ -309,7 +316,7 @@ var abp = abp || {}; var tabContentFilters = $($tabItem.attr('href')).find('[data-filter-text]'); let includedInTabContent = false; - tabContentFilters.each(function(i) { + tabContentFilters.each(function (i) { var permissionName = $(this).attr('data-filter-text').toLowerCase(); includedInTabContent = permissionName.includes(searchTerm); if (includedInTabContent === true) { @@ -317,7 +324,7 @@ var abp = abp || {}; } }); - if(includedInTabContent || tabName.includes(searchTerm)) { + if (includedInTabContent || tabName.includes(searchTerm)) { $tab.show(); } else { $tab.hide(); @@ -332,24 +339,24 @@ var abp = abp || {}; var $firstVisibleTab = $tabs.filter(':visible').first(); $tabs.removeClass('active'); $firstVisibleTab.addClass('active'); - + var $firstVisibleTabContent = $($firstVisibleTab.attr('href')); $firstVisibleTabContent.addClass('active show'); } function throttle(mainFunction, delay) { let timerFlag = null; // Variable to keep track of the timer - + // Returning a throttled version return (...args) => { - if (timerFlag === null) { // If there is no timer currently running - mainFunction(...args); // Execute the main function - timerFlag = setTimeout(() => { // Set a timer to clear the timerFlag after the specified delay - timerFlag = null; // Clear the timerFlag to allow the main function to be executed again - }, delay); - } + if (timerFlag === null) { // If there is no timer currently running + mainFunction(...args); // Execute the main function + timerFlag = setTimeout(() => { // Set a timer to clear the timerFlag after the specified delay + timerFlag = null; // Clear the timerFlag to allow the main function to be executed again + }, delay); + } }; - } + } }; }; diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs index 27ef7ea355..4b2c43079c 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs +++ b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs @@ -1,5 +1,7 @@ using System; -using Microsoft.AspNetCore.Hosting; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; using Serilog.Events; @@ -8,7 +10,7 @@ namespace Volo.Abp.VirtualFileExplorer.DemoApp; public class Program { - public static int Main(string[] args) + public static async Task Main(string[] args) { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() @@ -19,8 +21,17 @@ public class Program try { - Log.Information("Starting web host."); - CreateHostBuilder(args).Build().Run(); + Log.Information("Starting web host."); + var builder = WebApplication.CreateBuilder(args); + builder.Host + .AddAppSettingsSecretsJson() + .UseSerilog() + .UseAutofac() + ; + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); return 0; } catch (Exception ex) @@ -33,10 +44,4 @@ public class Program Log.CloseAndFlush(); } } - - internal static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }) - .UseAutofac() - .UseSerilog(); } diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Startup.cs b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Startup.cs deleted file mode 100644 index b963f84056..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Startup.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace Volo.Abp.VirtualFileExplorer.DemoApp; - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) - { - app.InitializeApplication(); - } -} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuNames.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuNames.cs index 9a8f1c8971..ab59638650 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuNames.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuNames.cs @@ -2,7 +2,7 @@ public class VirtualFileExplorerMenuNames { - public const string GroupName = "AbpVirualFileExplorer"; + public const string GroupName = "AbpVirtualFileExplorer"; public const string Index = GroupName + ".Index"; } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml index 509bdc248c..83d6688252 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml @@ -62,10 +62,10 @@ diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts index 17c99f8f93..a5a912e3eb 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts +++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts @@ -372,30 +372,14 @@ export class PermissionManagementComponent onClickSelectAll() { if (this.filter()) { - this.permissionGroups().forEach(group => { - group.permissions.forEach(permission => { - if ( - permission.isGranted && - this.isGrantedByOtherProviderName(permission.grantedProviders) - ) - return; - - const index = this.permissions.findIndex(per => per.name === permission.name); - - this.permissions = [ - ...this.permissions.slice(0, index), - { ...this.permissions[index], isGranted: !this.selectAllTab }, - ...this.permissions.slice(index + 1), - ]; - }); - }); - } else { - this.permissions = this.permissions.map(permission => ({ - ...permission, - isGranted: - this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab, - })); - } + this.filter.set(''); + } + + this.permissions = this.permissions.map(permission => ({ + ...permission, + isGranted: + this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab, + })); if (!this.disableSelectAllTab) { this.selectThisTab = !this.selectAllTab; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.Designer.cs new file mode 100644 index 0000000000..041cf03236 --- /dev/null +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.Designer.cs @@ -0,0 +1,1911 @@ +๏ปฟ// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyCompanyName.MyProjectName.Data; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations +{ + [DbContext(typeof(MyProjectNameDbContext))] + [Migration("20241226032336_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("datetime2") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("tinyint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EntityChangeId") + .HasColumnType("uniqueidentifier"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime2"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientUri") + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("nvarchar(max)"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Requirements") + .HasColumnType("nvarchar(max)"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scopes") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Descriptions") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Resources") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Payload") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedemptionDate") + .HasColumnType("datetime2"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.cs new file mode 100644 index 0000000000..f016eda970 --- /dev/null +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.cs @@ -0,0 +1,1120 @@ +๏ปฟusing System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationName = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + TenantName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ImpersonatorUserId = table.Column(type: "uniqueidentifier", nullable: true), + ImpersonatorUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ImpersonatorTenantId = table.Column(type: "uniqueidentifier", nullable: true), + ImpersonatorTenantName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ExecutionTime = table.Column(type: "datetime2", nullable: false), + ExecutionDuration = table.Column(type: "int", nullable: false), + ClientIpAddress = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + HttpMethod = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + Url = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Exceptions = table.Column(type: "nvarchar(max)", nullable: true), + Comments = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + HttpStatusCode = table.Column(type: "int", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "bit", nullable: false), + IsStatic = table.Column(type: "bit", nullable: false), + Regex = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + GroupName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + DefaultValue = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + IsVisibleToClients = table.Column(type: "bit", nullable: false), + IsAvailableToHost = table.Column(type: "bit", nullable: false), + AllowedProviders = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SourceUserId = table.Column(type: "uniqueidentifier", nullable: false), + SourceTenantId = table.Column(type: "uniqueidentifier", nullable: true), + TargetUserId = table.Column(type: "uniqueidentifier", nullable: false), + TargetTenantId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ParentId = table.Column(type: "uniqueidentifier", nullable: true), + Code = table.Column(type: "nvarchar(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + GroupName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "bit", nullable: false), + MultiTenancySide = table.Column(type: "tinyint", nullable: false), + Providers = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "bit", nullable: false), + IsStatic = table.Column(type: "bit", nullable: false), + IsPublic = table.Column(type: "bit", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ApplicationName = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SessionId = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), + SignedIn = table.Column(type: "datetime2", nullable: false), + LastAccessed = table.Column(type: "datetime2", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "bit", nullable: false), + Providers = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "bit", nullable: false), + IsEncrypted = table.Column(type: "bit", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + SourceUserId = table.Column(type: "uniqueidentifier", nullable: false), + TargetUserId = table.Column(type: "uniqueidentifier", nullable: false), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + IsActive = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "int", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "bit", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + LastPasswordChangeTime = table.Column(type: "datetimeoffset", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ClientId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "nvarchar(max)", nullable: true), + ClientType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "nvarchar(max)", nullable: true), + DisplayNames = table.Column(type: "nvarchar(max)", nullable: true), + JsonWebKeySet = table.Column(type: "nvarchar(max)", nullable: true), + Permissions = table.Column(type: "nvarchar(max)", nullable: true), + PostLogoutRedirectUris = table.Column(type: "nvarchar(max)", nullable: true), + Properties = table.Column(type: "nvarchar(max)", nullable: true), + RedirectUris = table.Column(type: "nvarchar(max)", nullable: true), + Requirements = table.Column(type: "nvarchar(max)", nullable: true), + Settings = table.Column(type: "nvarchar(max)", nullable: true), + ClientUri = table.Column(type: "nvarchar(max)", nullable: true), + LogoUri = table.Column(type: "nvarchar(max)", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + Descriptions = table.Column(type: "nvarchar(max)", nullable: true), + DisplayName = table.Column(type: "nvarchar(max)", nullable: true), + DisplayNames = table.Column(type: "nvarchar(max)", nullable: true), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "nvarchar(max)", nullable: true), + Resources = table.Column(type: "nvarchar(max)", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + AuditLogId = table.Column(type: "uniqueidentifier", nullable: false), + ServiceName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + MethodName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + Parameters = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + ExecutionTime = table.Column(type: "datetime2", nullable: false), + ExecutionDuration = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + AuditLogId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ChangeTime = table.Column(type: "datetime2", nullable: false), + ChangeType = table.Column(type: "tinyint", nullable: false), + EntityTenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityId = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + EntityTypeFullName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationUnitId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ClaimType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ClaimType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + LoginProvider = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ProviderKey = table.Column(type: "nvarchar(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationUnitId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + LoginProvider = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationId = table.Column(type: "uniqueidentifier", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: true), + Properties = table.Column(type: "nvarchar(max)", nullable: true), + Scopes = table.Column(type: "nvarchar(max)", nullable: true), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + EntityChangeId = table.Column(type: "uniqueidentifier", nullable: false), + NewValue = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + OriginalValue = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + PropertyName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + PropertyTypeFullName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationId = table.Column(type: "uniqueidentifier", nullable: true), + AuthorizationId = table.Column(type: "uniqueidentifier", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: true), + ExpirationDate = table.Column(type: "datetime2", nullable: true), + Payload = table.Column(type: "nvarchar(max)", nullable: true), + Properties = table.Column(type: "nvarchar(max)", nullable: true), + RedemptionDate = table.Column(type: "datetime2", nullable: true), + ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_ExecutionTime", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true, + filter: "[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_TargetTenantId", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true, + filter: "[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true, + filter: "[TenantId] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true, + filter: "[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs new file mode 100644 index 0000000000..c6f919612a --- /dev/null +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -0,0 +1,1908 @@ +๏ปฟ// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyCompanyName.MyProjectName.Data; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations +{ + [DbContext(typeof(MyProjectNameDbContext))] + partial class MyProjectNameDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("datetime2") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("tinyint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EntityChangeId") + .HasColumnType("uniqueidentifier"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime2"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientUri") + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("nvarchar(max)"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Requirements") + .HasColumnType("nvarchar(max)"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scopes") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Descriptions") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Resources") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Payload") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedemptionDate") + .HasColumnType("datetime2"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241010092009_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241010092009_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.Designer.cs index 19cf126fc2..8a28aa0c28 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241010092009_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241010092009_Initial")] + [Migration("20241226032120_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -425,6 +425,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -501,6 +505,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241010092009_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241010092009_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.cs index 866f5a6ee3..01342cbe1d 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241010092009_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.cs @@ -57,6 +57,7 @@ namespace MyCompanyName.MyProjectName.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -222,6 +223,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index e0ac67c697..032a7e08be 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -422,6 +422,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -498,6 +502,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241010091641_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241010091641_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.Designer.cs index 4cf20b0d84..bbc683e8c9 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241010091641_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241010091641_Initial")] + [Migration("20241226032219_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -425,6 +425,10 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -501,6 +505,10 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241010091641_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241010091641_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.cs index 791470c1e9..756c93f5be 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241010091641_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.cs @@ -57,6 +57,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -222,6 +223,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs index f46733e8f2..54276957a3 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -422,6 +422,10 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -498,6 +502,10 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241010091707_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241010091707_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.Designer.cs index 6c5b6b3dff..0702c60f89 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241010091707_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Mvc.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241010091707_Initial")] + [Migration("20241226032333_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -425,6 +425,10 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -501,6 +505,10 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241010091707_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241010091707_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.cs index 1dd9f60a23..744b52930e 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241010091707_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.cs @@ -57,6 +57,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -222,6 +223,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs index daf7f17a21..a003e4b6cc 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -422,6 +422,10 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -498,6 +502,10 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241010091723_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241010091723_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.Designer.cs index c177598fa7..94f4c9722f 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241010091723_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241010091723_Initial")] + [Migration("20241226031540_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -484,6 +484,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -558,6 +562,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241010091723_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241010091723_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.cs index e50f9af17c..13dee16800 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241010091723_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.cs @@ -78,6 +78,7 @@ namespace MyCompanyName.MyProjectName.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -243,6 +244,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 7de652e531..860b1fc689 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -481,6 +481,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -555,6 +559,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241010091821_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241010091821_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.Designer.cs index a06a1f61e8..35b5661fc4 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241010091821_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20241010091821_Initial")] + [Migration("20241226032427_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -425,6 +425,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -501,6 +505,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241010091821_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241010091821_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.cs index 866f5a6ee3..01342cbe1d 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241010091821_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.cs @@ -57,6 +57,7 @@ namespace MyCompanyName.MyProjectName.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -222,6 +223,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs index cee2ef145f..74d8f6d802 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -422,6 +422,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -498,6 +502,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241010091757_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241010091757_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.Designer.cs index 0c6fd4254f..b0eb5d07ff 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241010091757_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20241010091757_Initial")] + [Migration("20241226032535_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -425,6 +425,10 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -501,6 +505,10 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241010091757_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241010091757_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.cs index ffba76ab91..a7a41a3211 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241010091757_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.cs @@ -57,6 +57,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -222,6 +223,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 5ae81920d4..87d089ac54 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -422,6 +422,10 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -498,6 +502,10 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241010091929_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241010091929_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.Designer.cs index 37c3f63ff3..f278c04955 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241010091929_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20241010091929_Initial")] + [Migration("20241226032624_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -425,6 +425,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -501,6 +505,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241010091929_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241010091929_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.cs index c92f85eff3..85f0b91879 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241010091929_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.cs @@ -57,6 +57,7 @@ namespace MyCompanyName.MyProjectName.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -222,6 +223,7 @@ namespace MyCompanyName.MyProjectName.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 02ddb43bdf..393f21c825 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -422,6 +422,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -498,6 +502,10 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int");