Browse Source

Merge branch 'dev' into maliming/RequiredPermissionName

pull/7799/head
maliming 5 years ago
parent
commit
d81a9c367e
  1. 6
      docs/en/Best-Practices/Entity-Framework-Core-Integration.md
  2. 2
      docs/en/Blob-Storing-Aliyun.md
  3. 2
      docs/en/Blob-Storing-Aws.md
  4. 2
      docs/en/Blob-Storing-Azure.md
  5. 21
      docs/en/CLI.md
  6. 8
      docs/en/Customizing-Application-Modules-Overriding-Services.md
  7. 16
      docs/en/Tutorials/Part-2.md
  8. 23
      docs/en/Tutorials/Part-3.md
  9. 2
      docs/en/Tutorials/Part-5.md
  10. 6
      docs/en/Tutorials/Part-6.md
  11. 1
      docs/en/UI/Angular/Component-Replacement.md
  12. 288
      docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md
  13. BIN
      docs/en/UI/Angular/images/my-roles-component-form-extensions.jpg
  14. BIN
      docs/en/UI/Angular/images/my-roles-component-with-extensions.jpg
  15. 21
      docs/en/docs-nav.json
  16. 2
      docs/zh-Hans/Blob-Storing-Aliyun.md
  17. 2
      docs/zh-Hans/Blob-Storing-Aws.md
  18. 2
      docs/zh-Hans/Blob-Storing-Azure.md
  19. 14
      framework/Volo.Abp.sln
  20. 7
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor
  21. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs
  22. 27
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs
  23. 33
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
  24. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs
  25. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs
  26. 6
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  27. 30
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs
  28. 11
      framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs
  29. 2
      framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs
  30. 14
      framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs
  31. 2
      framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs
  32. 14
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs
  33. 2
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs
  34. 1
      framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobContainerConfigurationExtensions.cs
  35. 12
      framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs
  36. 2
      framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs
  37. 59
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs
  38. 7
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactory.cs
  39. 15
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNaming.cs
  40. 64
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs
  41. 2
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderBase.cs
  42. 11
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobNormalizeNamingService.cs
  43. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  44. 65
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigrator.cs
  45. 98
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
  46. 79
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs
  47. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  48. 30
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs
  49. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
  50. 28
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
  51. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
  52. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs
  53. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
  54. 16
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceProTemplate.cs
  55. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs
  56. 26
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs
  57. 63
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs
  58. 19
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs
  59. 14
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs
  60. 10
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs
  61. 30
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs
  62. 2
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs
  63. 10
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs
  64. 5
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs
  65. 4
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs
  66. 22
      framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingOptions.cs
  67. 2
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs
  68. 3
      framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xml
  69. 30
      framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xsd
  70. 24
      framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj
  71. 11
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs
  72. 16
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpSmsAliyunModule.cs
  73. 43
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AliyunSmsSender.cs
  74. 1
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
  75. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs
  76. 143
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention_Tests.cs
  77. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs
  78. 12
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController.cs
  79. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController_Tests.cs
  80. 54
      framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs
  81. 26
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj
  82. 12
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestBase.cs
  83. 18
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestsModule.cs
  84. 37
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AliyunSmsSender_Tests.cs
  85. 11
      framework/test/Volo.Abp.Sms.Aliyun.Tests/appsettings.json
  86. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs
  87. 10
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs
  88. 1576
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201224140744_Initial.Designer.cs
  89. 1647
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201225120048_Added_Page.Designer.cs
  90. 46
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201225120048_Added_Page.cs
  91. 1643
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201228083120_Updated_Tag_Removed_HexColor.Designer.cs
  92. 1725
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201231111657_Added_Blob_Storing.Designer.cs
  93. 95
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201231111657_Added_Blob_Storing.cs
  94. 106
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210209082122_UrlSlugToSlug.cs
  95. 73
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210210105857_Added_Media.cs
  96. 46
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219084931_PageSlugChange.cs
  97. 66
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219113255_Initial.Designer.cs
  98. 241
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219113255_Initial.cs
  99. 151
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219144454_BlogFeatureEnabledColumnRename.Designer.cs
  100. 23
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219144454_BlogFeatureEnabledColumnRename.cs

6
docs/en/Best-Practices/Entity-Framework-Core-Integration.md

@ -16,11 +16,13 @@
[ConnectionStringName("AbpIdentity")]
public interface IIdentityDbContext : IEfCoreDbContext
{
DbSet<IdentityUser> Users { get; set; }
DbSet<IdentityRole> Roles { get; set; }
DbSet<IdentityUser> Users { get; }
DbSet<IdentityRole> Roles { get; }
}
````
* **Do not** define `set;` for the properties in this interface.
### DbContext class
* **Do** inherit the `DbContext` from the `AbpDbContext<TDbContext>` class.

2
docs/en/Blob-Storing-Aliyun.md

@ -36,7 +36,7 @@ Configure<AbpBlobStoringOptions>(options =>
aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false;
aliyun.CreateContainerIfNotExists = true;
});
});
});

2
docs/en/Blob-Storing-Aws.md

@ -39,7 +39,7 @@ Configure<AbpBlobStoringOptions>(options =>
Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false;
Aws.CreateContainerIfNotExists = true;
});
});
});

2
docs/en/Blob-Storing-Azure.md

@ -29,7 +29,7 @@ Configure<AbpBlobStoringOptions>(options =>
{
azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false;
azure.CreateContainerIfNotExists = true;
});
});
});

21
docs/en/CLI.md

@ -31,6 +31,7 @@ Here, the list of all available commands before explaining their details:
* **`update`**: Automatically updates all ABP related NuGet and NPM packages in a solution.
* **`add-package`**: Adds an ABP package to a project.
* **`add-module`**: Adds a [multi-package application module](https://docs.abp.io/en/abp/latest/Modules/Index) to a solution.
* **`list-modules`**: Lists names of open-source application modules.
* **`get-source`**: Downloads the source code of a module.
* **`generate-proxy`**: Generates client side proxies to use HTTP API endpoints.
* **`remove-proxy`**: Removes previously generated client side proxies.
@ -202,6 +203,26 @@ abp add-module ProductManagement --new --add-to-solution-file
* `--with-source-code`: Downloads the source code of the module to your solution folder and uses local project references instead of NuGet/NPM packages. This options is always `True` if `--new` is used.
* `--add-to-solution-file`: Adds the downloaded/created module to your solution file, so you will also see the projects of the module when you open the solution on a IDE. (only available when `--with-source-code` is `True`.)
### list-modules
Lists names of open-source application modules.
Usage
````bash
abp list-modules [options]
````
Example:
```bash
abp list-modules
```
#### Options
* `--include-pro-modules`: Includes commercial (pro) modules in the output.
### get-source
Downloads the source code of a module to your computer.

8
docs/en/Customizing-Application-Modules-Overriding-Services.md

@ -196,12 +196,16 @@ This example replaces the `AccountController` (An API Controller defined in the
**`[ExposeServices(typeof(AccountController))]` is essential** here since it registers this controller for the `AccountController` in the dependency injection system. `[Dependency(ReplaceServices = true)]` is also recommended to clear the old registration (even the ASP.NET Core DI system selects the last registered one).
In addition, The `AccountController` will be removed from [`ApplicationModel`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationmodels.applicationmodel.controllers) because it defines `ExposeServicesAttribute`. If you don't want to remove it, you can configure `AbpAspNetCoreMvcOptions`:
In addition, the `MyAccountController` will be removed from [`ApplicationModel`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationmodels.applicationmodel.controllers) because it defines `ExposeServicesAttribute`.
If `IncludeSelf = true` is specified, i.e. `[ExposeServices(typeof(AccountController), IncludeSelf = true)]`, then `AccountController` will be removed instead. This is useful for **extending** a controller.
If you don't want to remove either controller, you can configure `AbpAspNetCoreMvcOptions`:
```csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.IgnoredControllersOnModelExclusion.AddIfNotContains(typeof(AccountController));
options.IgnoredControllersOnModelExclusion.AddIfNotContains(typeof(MyAccountController));
});
```

16
docs/en/Tutorials/Part-2.md

@ -103,7 +103,7 @@ Before starting to the UI development, we first want to prepare the localization
Localization texts are located under the `Localization/BookStore` folder of the `Acme.BookStore.Domain.Shared` project:
![bookstore-localization-files](./images/bookstore-localization-files-v2.png)
![bookstore-localization-files](images/bookstore-localization-files-v2.png)
Open the `en.json` (*the English translations*) file and change the content as below:
@ -157,7 +157,7 @@ It's time to create something visible and usable! Instead of classic MVC, we wil
Create `Books` folder under the `Pages` folder of the `Acme.BookStore.Web` project. Add a new Razor Page by right clicking the Books folder then selecting **Add > Razor Page** menu item. Name it as `Index`:
![bookstore-add-index-page](./images/bookstore-add-index-page-v2.png)
![bookstore-add-index-page](images/bookstore-add-index-page-v2.png)
Open the `Index.cshtml` and change the whole content as shown below:
@ -208,7 +208,7 @@ context.Menu.AddItem(
Run the project, login to the application with the username `admin` and the password `1q2w3E*` and see the new menu item has been added to the main menu:
![bookstore-menu-items](./images/bookstore-new-menu-item.png)
![bookstore-menu-items](images/bookstore-new-menu-item.png)
When you click to the Books menu item under the Book Store parent, you are being redirected to the new empty Books Page.
@ -250,7 +250,7 @@ Change the `Pages/Books/Index.cshtml` as following:
Create an `Index.js` file under the `Pages/Books` folder:
![bookstore-index-js-file](./images/bookstore-index-js-file-v3.png)
![bookstore-index-js-file](images/bookstore-index-js-file-v3.png)
The content of the file is shown below:
@ -344,8 +344,6 @@ It's time to create something visible and usable! There are some tools that we w
- [Ng Bootstrap](https://ng-bootstrap.github.io/#/home) will be used as the UI component library.
- [Ngx-Datatable](https://swimlane.gitbook.io/ngx-datatable/) will be used as the datatable library.
### BookModule
Run the following command line to create a new module, named `BookModule` in the root folder of the angular application:
```bash
@ -457,7 +455,7 @@ abp generate-proxy
This command will create the following files under the `/src/app/proxy/books` folder:
![Generated files](./images/generated-proxies-3.png)
![Generated files](images/generated-proxies-3.png)
### BookComponent
@ -490,7 +488,7 @@ export class BookComponent implements OnInit {
```
* We imported and injected the generated `BookService`.
* We are using the [ListService](https://docs.abp.io/en/abp/latest/UI/Angular/List-Service), a utility service of the ABP Framework which provides easy pagination, sorting and searching.
* We are using the [ListService](../UI/Angular/List-Service.md), a utility service of the ABP Framework which provides easy pagination, sorting and searching.
Open the `/src/app/book/book.component.html` and replace the content as below:
@ -531,7 +529,7 @@ Open the `/src/app/book/book.component.html` and replace the content as below:
Now you can see the final result on your browser:
![Book list final result](./images/bookstore-book-list.png)
![Book list final result](images/bookstore-book-list.png)
{{else if UI == "Blazor"}}

23
docs/en/Tutorials/Part-3.md

@ -48,13 +48,13 @@ This part is also recorded as a video tutorial and **<a href="https://www.youtub
In this section, you will learn how to create a new modal dialog form to create a new book. The modal dialog will look like in the image below:
![bookstore-create-dialog](./images/bookstore-create-dialog-2.png)
![bookstore-create-dialog](images/bookstore-create-dialog-2.png)
### Create the Modal Form
Create a new razor page, named `CreateModal.cshtml` under the `Pages/Books` folder of the `Acme.BookStore.Web` project.
![bookstore-add-create-dialog](./images/bookstore-add-create-dialog-v2.png)
![bookstore-add-create-dialog](images/bookstore-add-create-dialog-v2.png)
#### CreateModal.cshtml.cs
@ -186,7 +186,7 @@ The final content of the `Index.cshtml` is shown below:
This adds a new button called **New book** to the **top-right** of the table:
![bookstore-new-book-button](./images/bookstore-new-book-button-2.png)
![bookstore-new-book-button](images/bookstore-new-book-button-2.png)
Open the `Pages/Books/Index.js` and add the following code just after the `Datatable` configuration:
@ -281,7 +281,7 @@ Now, you can **run the application** and add some new books using the new modal
Create a new razor page, named `EditModal.cshtml` under the `Pages/Books` folder of the `Acme.BookStore.Web` project:
![bookstore-add-edit-dialog](./images/bookstore-add-edit-dialog.png)
![bookstore-add-edit-dialog](images/bookstore-add-edit-dialog.png)
### EditModal.cshtml.cs
@ -484,7 +484,7 @@ You can run the application and edit any book by selecting the edit action on a
The final UI looks as below:
![bookstore-books-table-actions](./images/bookstore-edit-button-2.png)
![bookstore-books-table-actions](images/bookstore-edit-button-2.png)
## Deleting a Book
@ -721,7 +721,7 @@ Open `/src/app/book/book.component.html` and make the following changes:
You can open your browser and click **New book** button to see the new modal.
![Empty modal for new book](./images/bookstore-empty-new-book-modal.png)
![Empty modal for new book](images/bookstore-empty-new-book-modal.png)
### Create a Reactive Form
@ -732,8 +732,7 @@ Open `/src/app/book/book.component.ts` and replace the content as below:
```js
import { ListService, PagedResultDto } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
// import bookTypeOptions from @proxy/books
import { BookService, BookDto, bookTypeOptions } from '@proxy/books';
import { BookService, BookDto, bookTypeOptions } from '@proxy/books'; // add bookTypeOptions
import { FormGroup, FormBuilder, Validators } from '@angular/forms'; // add this
@Component({
@ -959,7 +958,7 @@ export class BookComponent implements OnInit {
Now, you can open your browser to see the changes:
![Save button to the modal](./images/bookstore-new-book-form-v2.png)
![Save button to the modal](images/bookstore-new-book-form-v2.png)
## Updating a Book
@ -1087,7 +1086,7 @@ Open the `/src/app/book/book.component.html`  and add the following `ngx-datata
Added an "Actions" dropdown as the first column of the table that is shown below:
![Action buttons](./images/bookstore-actions-buttons.png)
![Action buttons](images/bookstore-actions-buttons.png)
Also, change the `ng-template #abpHeader` section as shown below:
@ -1151,11 +1150,11 @@ Open `/src/app/book/book.component.html` and modify the `ngbDropdownMenu` to add
The final actions dropdown UI looks like below:
![bookstore-final-actions-dropdown](./images/bookstore-final-actions-dropdown.png)
![bookstore-final-actions-dropdown](images/bookstore-final-actions-dropdown.png)
Clicking the "Delete" action calls the `delete` method which then shows a confirmation popup as shown below:
![bookstore-confirmation-popup](./images/bookstore-confirmation-popup.png)
![bookstore-confirmation-popup](images/bookstore-confirmation-popup.png)
{{end}}

2
docs/en/Tutorials/Part-5.md

@ -117,7 +117,7 @@ Finally, edit the localization file (`en.json` under the `Localization/BookStore
"Permission:Books.Delete": "Deleting the books"
````
> Localization key names are arbitrary and no forcing rule. But we prefer the convention used above.
> Localization key names are arbitrary and there is no forcing rule. But we prefer the convention used above.
### Permission Management UI

6
docs/en/Tutorials/Part-6.md

@ -124,7 +124,7 @@ Created this class inside the `Acme.BookStore.Domain.Shared` project since we wi
## AuthorManager: The Domain Service
`Author` constructor and `ChangeName` method is `internal`, so they can be usable only in the domain layer. Create an `AuthorManager` class in the `Authors` folder (namespace) of the `Acme.BookStore.Domain` project:
`Author` constructor and `ChangeName` methods are `internal`, so they can be used only in the domain layer. Create an `AuthorManager` class in the `Authors` folder (namespace) of the `Acme.BookStore.Domain` project:
````csharp
using System;
@ -186,7 +186,7 @@ namespace Acme.BookStore.Authors
* `AuthorManager` forces to create an author and change name of an author in a controlled way. The application layer (will be introduced later) will use these methods.
> **DDD tip**: Do not introduce domain service methods unless they are really needed and perform some core business rules. For this case, we needed to this service to be able to force the unique name constraint.
> **DDD tip**: Do not introduce domain service methods unless they are really needed and perform some core business rules. For this case, we needed this service to be able to force the unique name constraint.
Both methods checks if there is already an author with the given name and throws a special business exception, `AuthorAlreadyExistsException`, defined in the `Acme.BookStore.Domain` project (in the `Authors` folder) as shown below:
@ -226,7 +226,7 @@ This is a unique string represents the error code thrown by your application and
"BookStore:00001": "There is already an author with the same name: {name}"
````
Whenever you throw an `AuthorAlreadyExistsException`, the end use will see a this message on the UI.
Whenever you throw an `AuthorAlreadyExistsException`, the end user will see a nice error message on the UI.
## IAuthorRepository

1
docs/en/UI/Angular/Component-Replacement.md

@ -546,4 +546,5 @@ The final UI looks like below:
## See Also
- [How Replaceable Components Work with Extensions](./How-Replaceable-Components-Work-with-Extensions.md)
- [How to Replace PermissionManagementComponent](./Permission-Management-Component-Replacement.md)

288
docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md

@ -0,0 +1,288 @@
# How Replaceable Components Work with Extensions
Additional UI extensibility points ([Entity action extensions](https://docs.abp.io/en/abp/latest/UI/Angular/Entity-Action-Extensions), [data table column extensions](https://docs.abp.io/en/abp/latest/UI/Angular/Data-Table-Column-Extensions), [page toolbar extensions](https://docs.abp.io/en/abp/latest/UI/Angular/Page-Toolbar-Extensions) and others) are used in ABP pages to allow to control entity actions, table columns and page toolbar of a page. If you replace a page, you need to apply some configurations to be able to work extension components in your component. Let's see how to do this by replacing the roles page.
Create a new module called `MyRolesModule`:
```bash
yarn ng generate module my-roles --module app
```
Create a new component called `MyRolesComponent`:
```bash
yarn ng generate component my-roles/my-roles --flat --export
```
Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its content with the following:
```js
import { ListService, PagedAndSortedResultRequestDto } from '@abp/ng.core';
import {
CreateRole,
DeleteRole,
eIdentityComponents,
GetRoleById,
GetRoles,
IdentityRoleDto,
IdentityState,
RolesComponent,
UpdateRole,
} from '@abp/ng.identity';
import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared';
import {
EXTENSIONS_IDENTIFIER,
FormPropData,
generateFormFromProps,
} from '@abp/ng.theme.shared/extensions';
import { Component, Injector, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { finalize, pluck } from 'rxjs/operators';
@Component({
selector: 'app-my-roles',
templateUrl: './my-roles.component.html',
providers: [
ListService,
{
provide: EXTENSIONS_IDENTIFIER,
useValue: eIdentityComponents.Roles,
},
{ provide: RolesComponent, useExisting: MyRolesComponent },
],
})
export class MyRolesComponent implements OnInit {
@Select(IdentityState.getRoles)
data$: Observable<IdentityRoleDto[]>;
@Select(IdentityState.getRolesTotalCount)
totalCount$: Observable<number>;
form: FormGroup;
selected: IdentityRoleDto;
isModalVisible: boolean;
visiblePermissions = false;
providerKey: string;
modalBusy = false;
permissionManagementKey = ePermissionManagementComponents.PermissionManagement;
onVisiblePermissionChange = event => {
this.visiblePermissions = event;
};
constructor(
public readonly list: ListService<PagedAndSortedResultRequestDto>,
protected confirmationService: ConfirmationService,
protected store: Store,
protected injector: Injector
) {}
ngOnInit() {
this.hookToQuery();
}
buildForm() {
const data = new FormPropData(this.injector, this.selected);
this.form = generateFormFromProps(data);
}
openModal() {
this.buildForm();
this.isModalVisible = true;
}
add() {
this.selected = {} as IdentityRoleDto;
this.openModal();
}
edit(id: string) {
this.store
.dispatch(new GetRoleById(id))
.pipe(pluck('IdentityState', 'selectedRole'))
.subscribe(selectedRole => {
this.selected = selectedRole;
this.openModal();
});
}
save() {
if (!this.form.valid) return;
this.modalBusy = true;
this.store
.dispatch(
this.selected.id
? new UpdateRole({ ...this.selected, ...this.form.value, id: this.selected.id })
: new CreateRole(this.form.value)
)
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => {
this.isModalVisible = false;
this.list.get();
});
}
delete(id: string, name: string) {
this.confirmationService
.warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {
messageLocalizationParams: [name],
})
.subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) {
this.store.dispatch(new DeleteRole(id)).subscribe(() => this.list.get());
}
});
}
private hookToQuery() {
this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe();
}
openPermissionsModal(providerKey: string) {
this.providerKey = providerKey;
setTimeout(() => {
this.visiblePermissions = true;
}, 0);
}
sort(data) {
const { prop, dir } = data.sorts[0];
this.list.sortKey = prop;
this.list.sortOrder = dir;
}
}
```
```js
{
provide: EXTENSIONS_IDENTIFIER,
useValue: eIdentityComponents.Roles,
},
{
provide: RolesComponent,
useExisting: MyRolesComponent
}
```
The two providers we have defined in `MyRolesComponent` are required for the extension components to work correctly.
* With the first provider, we defined the extension identifier for using `RolesComponent`'s extension actions in the `MyRolesComponent`.
* With the second provider, we have replaced the `RolesComponent` injection with the `MyRolesComponent`. Default extension actions of the `RolesComponent` try to get `RolesComponent` instance. However, the actions can get the `MyRolesComponent` instance after defining the second provider.
Open the generated `src/app/my-role/my-role.component.html` file and replace its content with the following:
```html
<div id="identity-roles-wrapper" class="card">
<div class="card-header">
<div class="row">
<div class="col col-md-6">
<h5 class="card-title">My Roles</h5>
</div>
<div class="text-right col col-md-6">
<abp-page-toolbar [record]="data$ | async"></abp-page-toolbar>
</div>
</div>
</div>
<div class="card-body">
<abp-extensible-table
[data]="data$ | async"
[recordsTotal]="totalCount$ | async"
[list]="list"
></abp-extensible-table>
</div>
</div>
<abp-modal size="md" [(visible)]="isModalVisible" [busy]="modalBusy">
<ng-template #abpHeader>
<h3>{%{{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}}%}</h3>
</ng-template>
<ng-template #abpBody>
<form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit>
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" #abpClose>
{%{{{ 'AbpIdentity::Cancel' | abpLocalization }}}%}
</button>
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{%{{{
'AbpIdentity::Save' | abpLocalization
}}}%}</abp-button>
</ng-template>
</abp-modal>
<abp-permission-management
#abpPermissionManagement="abpPermissionManagement"
*abpReplaceableTemplate="
{
inputs: {
providerName: { value: 'R' },
providerKey: { value: providerKey },
visible: { value: visiblePermissions, twoWay: true },
hideBadges: { value: true }
},
outputs: { visibleChange: onVisiblePermissionChange },
componentKey: permissionManagementKey
};
let init = initTemplate
"
(abpInit)="init(abpPermissionManagement)"
>
</abp-permission-management>
```
We have added the `abp-page-toolbar`, `abp-extensible-table`, and `abp-extensible-form` extension components to template of the `MyRolesComponent`.
You should import the required modules for the `MyRolesComponent` to `MyRolesModule`. Open the `src/my-roles/my-roles.module.ts` file and replace the content with the following:
```js
import { UiExtensionsModule } from '@abp/ng.theme.shared/extensions';
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { MyRolesComponent } from './my-roles.component';
import { PermissionManagementModule } from '@abp/ng.permission-management';
@NgModule({
declarations: [MyRolesComponent],
imports: [SharedModule, UiExtensionsModule, PermissionManagementModule],
exports: [MyRolesComponent],
})
export class MyRolesModule {}
```
- `UiExtensionsModule` imported to be able to use the extension components in your component.
- `PermissionManagementModule` imported to be able to use the `abp-permission-*management` in your component.
As the last step, it is needs to be replaced the `RolesComponent` with the `MyRolesComponent`. Open the `app.component.ts` and modify its content as shown below:
```js
import { ReplaceableComponentsService } from '@abp/ng.core';
import { eIdentityComponents } from '@abp/ng.identity';
import { MyRolesComponent } from './my-roles/my-roles.component';
@Component(/* component metadata */)
export class AppComponent {
constructor(private replaceableComponents: ReplaceableComponentsService) {
this.replaceableComponents.add({ component: MyRolesComponent, key: eIdentityComponents.Roles });
}
}
```
After the steps above, the `RolesComponent` has been successfully replaced with the `MyRolesComponent`. When you navigate to the `/identity/roles` URL, you will see the `MyRolesComponent`'s template and see the extension components working correctly.
![my-roles-component-with-extensions](./images/my-roles-component-with-extensions.jpg)
![my-roles-component-form-extensions](./images/my-roles-component-form-extensions.jpg)

BIN
docs/en/UI/Angular/images/my-roles-component-form-extensions.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
docs/en/UI/Angular/images/my-roles-component-with-extensions.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

21
docs/en/docs-nav.json

@ -859,6 +859,27 @@
{
"text": "Custom Setting Page",
"path": "UI/Angular/Custom-Setting-Page.md"
},
{
"text": "Extensions",
"items": [
{
"text": "Entity Action Extensions",
"path": "UI/Angular/Entity-Action-Extensions.md"
},
{
"text": "Data Table Column Extensions",
"path": "UI/Angular/Data-Table-Column-Extensions.md"
},
{
"text": "Page Toolbar Extensions",
"path": "UI/Angular/Page-Toolbar-Extensions.md"
},
{
"text": "Dynamic Form Extensions",
"path": "UI/Angular/Dynamic-Form-Extensions.md"
}
]
}
]
}

2
docs/zh-Hans/Blob-Storing-Aliyun.md

@ -36,7 +36,7 @@ Configure<AbpBlobStoringOptions>(options =>
aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false;
aliyun.CreateContainerIfNotExists = true;
});
});
});

2
docs/zh-Hans/Blob-Storing-Aws.md

@ -39,7 +39,7 @@ Configure<AbpBlobStoringOptions>(options =>
Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false;
Aws.CreateContainerIfNotExists = true;
});
});
});

2
docs/zh-Hans/Blob-Storing-Azure.md

@ -29,7 +29,7 @@ Configure<AbpBlobStoringOptions>(options =>
{
azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false;
azure.CreateContainerIfNotExists = true;
});
});
});

14
framework/Volo.Abp.sln

@ -361,6 +361,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Tests", "test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Abstractions", "src\Volo.Abp.EventBus.Abstractions\Volo.Abp.EventBus.Abstractions.csproj", "{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.Aliyun", "src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj", "{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.Aliyun.Tests", "test\Volo.Abp.Sms.Aliyun.Tests\Volo.Abp.Sms.Aliyun.Tests.csproj", "{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1075,6 +1079,14 @@ Global
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.Build.0 = Release|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.Build.0 = Release|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1257,6 +1269,8 @@ Global
{00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

7
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor

@ -1,11 +1,14 @@
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Localization
@using Volo.Abp.Users
@using Volo.Abp.MultiTenancy
@using global::Localization.Resources.AbpUi
@inject ICurrentUser CurrentUser
@inject ICurrentTenant CurrentTenant
@inject IJSRuntime JsRuntime
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
@inject IStringLocalizer<AbpUiResource> UiLocalizer
<AuthorizeView>
<Authorized>
<Dropdown>
@ -28,12 +31,12 @@
}
}
<DropdownDivider />
<DropdownItem Clicked="BeginSignOut">Logout</DropdownItem>
<DropdownItem Clicked="BeginSignOut">@UiLocalizer["Logout"]</DropdownItem>
</DropdownMenu>
</Dropdown>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">Log in</a>
<a class="nav-link" href="authentication/login">@UiLocalizer["Login"]</a>
</NotAuthorized>
</AuthorizeView>
@code{

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs

@ -84,7 +84,6 @@ namespace Volo.Abp.AspNetCore.Mvc
);
var controllerModel = moduleModel.GetOrAddController(
controllerType.FullName,
_options.ControllerNameGenerator(controllerType, setting),
controllerType,
_modelOptions.IgnoredInterfaces
@ -272,6 +271,7 @@ namespace Volo.Abp.AspNetCore.Mvc
actionModel.AddParameter(ParameterApiDescriptionModel.Create(
parameterDescription.Name,
_options.ApiParameterNameGenerator?.Invoke(parameterDescription),
matchedMethodParamName,
parameterDescription.Type,
parameterDescription.RouteInfo?.IsOptional ?? false,

27
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs

@ -2,6 +2,9 @@
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Mvc.Conventions;
@ -13,6 +16,8 @@ namespace Volo.Abp.AspNetCore.Mvc
public Func<MethodInfo, string> ActionNameGenerator { get; set; }
public Func<ApiParameterDescription, string> ApiParameterNameGenerator { get; set; }
public AspNetCoreApiDescriptionModelProviderOptions()
{
ControllerNameGenerator = (controllerType, setting) =>
@ -52,6 +57,28 @@ namespace Volo.Abp.AspNetCore.Mvc
return methodNameBuilder.ToString();
};
ApiParameterNameGenerator = (apiParameterDescription) =>
{
if (apiParameterDescription.ModelMetadata is DefaultModelMetadata defaultModelMetadata)
{
var jsonPropertyNameAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is System.Text.Json.Serialization.JsonPropertyNameAttribute);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = (Newtonsoft.Json.JsonPropertyAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is Newtonsoft.Json.JsonPropertyAttribute);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
}
return null;
};
}
}
}

33
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs

@ -73,7 +73,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
protected virtual void RemoveDuplicateControllers(ApplicationModel application)
{
var derivedControllerModels = new List<ControllerModel>();
var controllerModelsToRemove = new List<ControllerModel>();
foreach (var controllerModel in application.Controllers)
{
@ -87,19 +87,42 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
continue;
}
var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType);
if (exposeServicesAttr.IncludeSelf)
{
var exposedControllerModels = application.Controllers
.Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType))
.ToArray();
controllerModelsToRemove.AddRange(exposedControllerModels);
Logger.LogInformation($"Removing the controller{(exposedControllerModels.Length > 1 ? "s" : "")} {exposeServicesAttr.ServiceTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")} from the application model since {(exposedControllerModels.Length > 1 ? "they are" : "it is")} replaced by the controller: {controllerModel.ControllerType.AssemblyQualifiedName}");
continue;
}
var baseControllerTypes = controllerModel.ControllerType
.GetBaseClasses(typeof(Controller), includeObject: false)
.Where(t => !t.IsAbstract)
.ToArray();
if (baseControllerTypes.Length > 0)
if (baseControllerTypes.Length == 0)
{
derivedControllerModels.Add(controllerModel);
Logger.LogInformation($"Removing the controller {controllerModel.ControllerType.AssemblyQualifiedName} from the application model since it replaces the controller(s): {baseControllerTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")}");
continue;
}
var baseControllerModels = application.Controllers
.Where(cm => baseControllerTypes.Contains(cm.ControllerType))
.ToArray();
if (baseControllerModels.Length == 0)
{
continue;
}
controllerModelsToRemove.Add(controllerModel);
Logger.LogInformation($"Removing the controller {controllerModel.ControllerType.AssemblyQualifiedName} from the application model since it replaces the controller(s): {baseControllerTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")}");
}
application.Controllers.RemoveAll(derivedControllerModels);
application.Controllers.RemoveAll(controllerModelsToRemove);
}
protected virtual void ConfigureRemoteService(ControllerModel controller, [CanBeNull] ConventionalControllerSetting configuration)

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

@ -50,7 +50,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
return;
}
//Begin a new, independent unit of work
using (var uow = unitOfWorkManager.Begin(options))
{
var result = await next();
@ -58,6 +57,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{
await uow.CompleteAsync(context.HttpContext.RequestAborted);
}
else
{
await uow.RollbackAsync(context.HttpContext.RequestAborted);
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs

@ -55,7 +55,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
return;
}
//Begin a new, independent unit of work
using (var uow = unitOfWorkManager.Begin(options))
{
var result = await next();
@ -63,6 +62,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{
await uow.CompleteAsync(context.HttpContext.RequestAborted);
}
else
{
await uow.RollbackAsync(context.HttpContext.RequestAborted);
}
}
}

6
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -6,6 +6,7 @@ using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Security;
using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow;
@ -82,5 +83,10 @@ namespace Microsoft.AspNetCore.Builder
{
return app.UseMiddleware<AbpClaimsMapMiddleware>();
}
public static IApplicationBuilder UseAbpSecurityHeaders(this IApplicationBuilder app)
{
return app.UseMiddleware<AbpSecurityHeadersMiddleware>();
}
}
}

30
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs

@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Security
{
public class AbpSecurityHeadersMiddleware : IMiddleware, ITransientDependency
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
/*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.*/
AddHeaderIfNotExists(context, "X-Content-Type-Options", "nosniff");
/*X-XSS-Protection is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks*/
AddHeaderIfNotExists(context, "X-XSS-Protection", "1; mode=block");
/*The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object>. SAMEORIGIN makes it being displayed in a frame on the same origin as the page itself. The spec leaves it up to browser vendors to decide whether this option applies to the top level, the parent, or the whole chain*/
AddHeaderIfNotExists(context, "X-Frame-Options", "SAMEORIGIN");
await next.Invoke(context);
}
protected virtual void AddHeaderIfNotExists(HttpContext context, string key, string value)
{
context.Response.Headers.AddIfNotContains(new KeyValuePair<string, StringValues>(key, value));
}
}
}

11
framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs

@ -10,13 +10,16 @@ namespace Volo.Abp.BlobStoring.Aliyun
{
protected IOssClientFactory OssClientFactory { get; }
protected IAliyunBlobNameCalculator AliyunBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public AliyunBlobProvider(
IOssClientFactory ossClientFactory,
IAliyunBlobNameCalculator aliyunBlobNameCalculator)
IAliyunBlobNameCalculator aliyunBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
OssClientFactory = ossClientFactory;
AliyunBlobNameCalculator = aliyunBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
protected virtual IOss GetOssClient(BlobContainerConfiguration blobContainerConfiguration)
@ -88,15 +91,15 @@ namespace Volo.Abp.BlobStoring.Aliyun
return memoryStream;
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetAliyunConfiguration();
return configuration.ContainerName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.ContainerName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName);
}
private bool BlobExists(IOss ossClient,string containerName, string blobName)
protected virtual bool BlobExists(IOss ossClient,string containerName, string blobName)
{
// Make sure Blob Container exists.
return ossClient.DoesBucketExist(containerName) &&

2
framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs

@ -82,7 +82,7 @@ namespace Volo.Abp.BlobStoring.Aliyun
public string ContainerName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(AliyunBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.ContainerName, value);
}
/// <summary>

14
framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs

@ -12,12 +12,16 @@ namespace Volo.Abp.BlobStoring.Aws
{
protected IAwsBlobNameCalculator AwsBlobNameCalculator { get; }
protected IAmazonS3ClientFactory AmazonS3ClientFactory { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public AwsBlobProvider(IAwsBlobNameCalculator awsBlobNameCalculator,
IAmazonS3ClientFactory amazonS3ClientFactory)
public AwsBlobProvider(
IAwsBlobNameCalculator awsBlobNameCalculator,
IAmazonS3ClientFactory amazonS3ClientFactory,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
AwsBlobNameCalculator = awsBlobNameCalculator;
AmazonS3ClientFactory = amazonS3ClientFactory;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
@ -111,7 +115,7 @@ namespace Volo.Abp.BlobStoring.Aws
return await AmazonS3ClientFactory.GetAmazonS3Client(configuration);
}
private async Task<bool> BlobExistsAsync(AmazonS3Client amazonS3Client, string containerName, string blobName)
protected virtual async Task<bool> BlobExistsAsync(AmazonS3Client amazonS3Client, string containerName, string blobName)
{
// Make sure Blob Container exists.
if (!await AmazonS3Util.DoesS3BucketExistV2Async(amazonS3Client, containerName))
@ -147,12 +151,12 @@ namespace Volo.Abp.BlobStoring.Aws
}
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetAwsConfiguration();
return configuration.ContainerName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.ContainerName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName);
}
}
}

2
framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs

@ -82,7 +82,7 @@ namespace Volo.Abp.BlobStoring.Aws
public string ContainerName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(AwsBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AwsBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(AwsBlobProviderConfigurationNames.ContainerName, value);
}
/// <summary>

14
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs

@ -9,10 +9,14 @@ namespace Volo.Abp.BlobStoring.Azure
public class AzureBlobProvider : BlobProviderBase, ITransientDependency
{
protected IAzureBlobNameCalculator AzureBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public AzureBlobProvider(IAzureBlobNameCalculator azureBlobNameCalculator)
public AzureBlobProvider(
IAzureBlobNameCalculator azureBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
AzureBlobNameCalculator = azureBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
@ -87,22 +91,22 @@ namespace Volo.Abp.BlobStoring.Azure
await blobContainerClient.CreateIfNotExistsAsync();
}
private async Task<bool> BlobExistsAsync(BlobProviderArgs args, string blobName)
protected virtual async Task<bool> BlobExistsAsync(BlobProviderArgs args, string blobName)
{
// Make sure Blob Container exists.
return await ContainerExistsAsync(GetBlobContainerClient(args)) &&
(await GetBlobClient(args, blobName).ExistsAsync()).Value;
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetAzureConfiguration();
return configuration.ContainerName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.ContainerName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName);
}
private static async Task<bool> ContainerExistsAsync(BlobContainerClient blobContainerClient)
protected virtual async Task<bool> ContainerExistsAsync(BlobContainerClient blobContainerClient)
{
return (await blobContainerClient.ExistsAsync()).Value;
}

2
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs

@ -17,7 +17,7 @@
public string ContainerName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(AzureBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, value);
}
/// <summary>

1
framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobContainerConfigurationExtensions.cs

@ -15,6 +15,7 @@ namespace Volo.Abp.BlobStoring.Minio
Action<MinioBlobProviderConfiguration> minioConfigureAction)
{
containerConfiguration.ProviderType = typeof(MinioBlobProvider);
containerConfiguration.NamingNormalizers.TryAdd<MinioBlobNamingNormalizer>();
minioConfigureAction(new MinioBlobProviderConfiguration(containerConfiguration));

12
framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs

@ -10,10 +10,14 @@ namespace Volo.Abp.BlobStoring.Minio
public class MinioBlobProvider : BlobProviderBase, ITransientDependency
{
protected IMinioBlobNameCalculator MinioBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public MinioBlobProvider(IMinioBlobNameCalculator minioBlobNameCalculator)
public MinioBlobProvider(
IMinioBlobNameCalculator minioBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
MinioBlobNameCalculator = minioBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
@ -108,7 +112,7 @@ namespace Volo.Abp.BlobStoring.Minio
}
}
private async Task<bool> BlobExistsAsync(MinioClient client, string containerName , string blobName)
protected virtual async Task<bool> BlobExistsAsync(MinioClient client, string containerName , string blobName)
{
// Make sure Blob Container exists.
if (await client.BucketExistsAsync(containerName))
@ -133,13 +137,13 @@ namespace Volo.Abp.BlobStoring.Minio
return false;
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetMinioConfiguration();
return configuration.BucketName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.BucketName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.BucketName);
}
}
}

2
framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs

@ -5,7 +5,7 @@
public string BucketName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(MinioBlobProviderConfigurationNames.BucketName);
set => _containerConfiguration.SetConfiguration(MinioBlobProviderConfigurationNames.BucketName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(MinioBlobProviderConfigurationNames.BucketName, value);
}
/// <summary>

59
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs

@ -1,9 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
@ -88,12 +86,15 @@ namespace Volo.Abp.BlobStoring
protected IServiceProvider ServiceProvider { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public BlobContainer(
string containerName,
BlobContainerConfiguration configuration,
IBlobProvider provider,
ICurrentTenant currentTenant,
ICancellationTokenProvider cancellationTokenProvider,
IBlobNormalizeNamingService blobNormalizeNamingService,
IServiceProvider serviceProvider)
{
ContainerName = containerName;
@ -101,6 +102,7 @@ namespace Volo.Abp.BlobStoring
Provider = provider;
CurrentTenant = currentTenant;
CancellationTokenProvider = cancellationTokenProvider;
BlobNormalizeNamingService = blobNormalizeNamingService;
ServiceProvider = serviceProvider;
}
@ -112,13 +114,13 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) = NormalizeNaming(ContainerName, name);
var blobNormalizeNaming = BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
await Provider.SaveAsync(
new BlobProviderSaveArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
stream,
overrideExisting,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
@ -133,14 +135,14 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) =
NormalizeNaming(ContainerName, name);
var blobNormalizeNaming =
BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
return await Provider.DeleteAsync(
new BlobProviderDeleteArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
@ -153,14 +155,14 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) =
NormalizeNaming(ContainerName, name);
var blobNormalizeNaming =
BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
return await Provider.ExistsAsync(
new BlobProviderExistsArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
@ -189,14 +191,14 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) =
NormalizeNaming(ContainerName, name);
var blobNormalizeNaming =
BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
return await Provider.GetOrNullAsync(
new BlobProviderGetArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
@ -212,28 +214,5 @@ namespace Volo.Abp.BlobStoring
return CurrentTenant.Id;
}
protected virtual (string, string) NormalizeNaming(string containerName, string blobName)
{
if (!Configuration.NamingNormalizers.Any())
{
return (containerName, blobName);
}
using (var scope = ServiceProvider.CreateScope())
{
foreach (var normalizerType in Configuration.NamingNormalizers)
{
var normalizer = scope.ServiceProvider
.GetRequiredService(normalizerType)
.As<IBlobNamingNormalizer>();
containerName = normalizer.NormalizeContainerName(containerName);
blobName = normalizer.NormalizeBlobName(blobName);
}
return (containerName, blobName);
}
}
}
}

7
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactory.cs

@ -17,18 +17,22 @@ namespace Volo.Abp.BlobStoring
protected IServiceProvider ServiceProvider { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public BlobContainerFactory(
IBlobContainerConfigurationProvider configurationProvider,
ICurrentTenant currentTenant,
ICancellationTokenProvider cancellationTokenProvider,
IBlobProviderSelector providerSelector,
IServiceProvider serviceProvider)
IServiceProvider serviceProvider,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
ConfigurationProvider = configurationProvider;
CurrentTenant = currentTenant;
CancellationTokenProvider = cancellationTokenProvider;
ProviderSelector = providerSelector;
ServiceProvider = serviceProvider;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public virtual IBlobContainer Create(string name)
@ -41,6 +45,7 @@ namespace Volo.Abp.BlobStoring
ProviderSelector.Get(name),
CurrentTenant,
CancellationTokenProvider,
BlobNormalizeNamingService,
ServiceProvider
);
}

15
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNaming.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.BlobStoring
{
public class BlobNormalizeNaming
{
public string ContainerName { get; }
public string BlobName { get; }
public BlobNormalizeNaming(string containerName, string blobName)
{
ContainerName = containerName;
BlobName = blobName;
}
}
}

64
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs

@ -0,0 +1,64 @@
using System;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BlobStoring
{
public class BlobNormalizeNamingService : IBlobNormalizeNamingService, ITransientDependency
{
protected IServiceProvider ServiceProvider { get; }
public BlobNormalizeNamingService(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public BlobNormalizeNaming NormalizeNaming(
BlobContainerConfiguration configuration,
string containerName,
string blobName)
{
if (!configuration.NamingNormalizers.Any())
{
return new BlobNormalizeNaming(containerName, blobName);
}
using (var scope = ServiceProvider.CreateScope())
{
foreach (var normalizerType in configuration.NamingNormalizers)
{
var normalizer = scope.ServiceProvider
.GetRequiredService(normalizerType)
.As<IBlobNamingNormalizer>();
containerName = containerName.IsNullOrWhiteSpace()? containerName: normalizer.NormalizeContainerName(containerName);
blobName = blobName.IsNullOrWhiteSpace()? blobName: normalizer.NormalizeBlobName(blobName);
}
return new BlobNormalizeNaming(containerName, blobName);
}
}
public string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName)
{
if (!configuration.NamingNormalizers.Any())
{
return containerName;
}
return NormalizeNaming(configuration, containerName, null).ContainerName;
}
public string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName)
{
if (!configuration.NamingNormalizers.Any())
{
return blobName;
}
return NormalizeNaming(configuration, null, blobName).BlobName;
}
}
}

2
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderBase.cs

@ -13,4 +13,4 @@ namespace Volo.Abp.BlobStoring
public abstract Task<Stream> GetOrNullAsync(BlobProviderGetArgs args);
}
}
}

11
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobNormalizeNamingService.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.BlobStoring
{
public interface IBlobNormalizeNamingService
{
BlobNormalizeNaming NormalizeNaming(BlobContainerConfiguration configuration, string containerName, string blobName);
string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName);
string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName);
}
}

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -34,6 +34,7 @@ namespace Volo.Abp.Cli
options.Commands["update"] = typeof(UpdateCommand);
options.Commands["add-package"] = typeof(AddPackageCommand);
options.Commands["add-module"] = typeof(AddModuleCommand);
options.Commands["list-modules"] = typeof(ListModulesCommand);
options.Commands["login"] = typeof(LoginCommand);
options.Commands["logout"] = typeof(LogoutCommand);
options.Commands[GenerateProxyCommand.Name] = typeof(GenerateProxyCommand);
@ -45,7 +46,7 @@ namespace Volo.Abp.Cli
options.Commands["translate"] = typeof(TranslateCommand);
options.Commands["build"] = typeof(BuildCommand);
options.Commands["bundle"] = typeof(BundleCommand);
options.Commands["create-migration-and-run-migrator"] = typeof(CreateMigrationAndRunMigrator);
options.Commands["create-migration-and-run-migrator"] = typeof(CreateMigrationAndRunMigratorCommand);
});
}
}

65
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigrator.cs

@ -1,65 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class CreateMigrationAndRunMigrator : IConsoleCommand, ITransientDependency
{
public virtual async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Target.IsNullOrEmpty())
{
throw new CliUsageException(
"DbMigrations folder path is missing!"
);
}
var dbMigratorProjectPath = GetDbMigratorProjectPath(commandLineArgs.Target);
if (dbMigratorProjectPath == null)
{
throw new Exception("DbMigrator is not found!");
}
var output = CmdHelper.RunCmdAndGetOutput($"cd \"{commandLineArgs.Target}\" && dotnet ef migrations add Initial -s \"{dbMigratorProjectPath}\"");
if (output.Contains("Done.") && output.Contains("To undo this action") && output.Contains("ef migrations remove")) // Migration added successfully
{
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run");
}
else
{
throw new Exception("Migrations failed: " + output);
}
}
private string GetDbMigratorProjectPath(string dbMigrationsFolderPath)
{
var srcFolder = Directory.GetParent(dbMigrationsFolderPath);
var dbMigratorFolderPath = Directory.GetDirectories(srcFolder.FullName).FirstOrDefault(d => d.EndsWith(".DbMigrator"));
if (dbMigratorFolderPath == null)
{
return null;
}
return Directory.GetFiles(dbMigratorFolderPath).FirstOrDefault(f => f.EndsWith(".csproj"));
}
public string GetUsageInfo()
{
return string.Empty;
}
public string GetShortDescription()
{
return string.Empty;
}
}
}

98
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs

@ -0,0 +1,98 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientDependency
{
public ILogger<CreateMigrationAndRunMigratorCommand> Logger { get; set; }
public CreateMigrationAndRunMigratorCommand()
{
Logger = NullLogger<CreateMigrationAndRunMigratorCommand>.Instance;
}
public virtual async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Target.IsNullOrEmpty())
{
throw new CliUsageException("DbMigrations folder path is missing!");
}
var dbMigratorProjectPath = GetDbMigratorProjectPath(commandLineArgs.Target);
if (dbMigratorProjectPath == null)
{
throw new Exception("DbMigrator is not found!");
}
if (!IsDotNetEfToolInstalled())
{
InstallDotnetEfTool();
}
var addMigrationCmd = $"cd \"{commandLineArgs.Target}\" && " +
$"dotnet ef migrations add Initial -s \"{dbMigratorProjectPath}\"";
var output = CmdHelper.RunCmdAndGetOutput(addMigrationCmd);
if (output.Contains("Done.") &&
output.Contains("To undo this action") &&
output.Contains("ef migrations remove"))
{
// Migration added successfully
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run");
await Task.CompletedTask;
}
else
{
var exceptionMsg = "Migrations failed! The following command didn't run successfully:" +
Environment.NewLine +
addMigrationCmd +
Environment.NewLine + output;
Logger.LogError(exceptionMsg);
throw new Exception(exceptionMsg);
}
}
private static bool IsDotNetEfToolInstalled()
{
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g");
return output.Contains("dotnet-ef");
}
private void InstallDotnetEfTool()
{
Logger.LogInformation("Installing dotnet-ef tool...");
CmdHelper.RunCmd("dotnet tool install --global dotnet-ef");
Logger.LogInformation("dotnet-ef tool is installed.");
}
private static string GetDbMigratorProjectPath(string dbMigrationsFolderPath)
{
var srcFolder = Directory.GetParent(dbMigrationsFolderPath);
var dbMigratorDirectory = Directory.GetDirectories(srcFolder.FullName)
.FirstOrDefault(d => d.EndsWith(".DbMigrator"));
return dbMigratorDirectory == null
? null
: Directory.GetFiles(dbMigratorDirectory).FirstOrDefault(f => f.EndsWith(".csproj"));
}
public string GetUsageInfo()
{
return string.Empty;
}
public string GetShortDescription()
{
return string.Empty;
}
}
}

79
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs

@ -0,0 +1,79 @@
using System;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System.Threading.Tasks;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class ListModulesCommand : IConsoleCommand, ITransientDependency
{
public ModuleInfoProvider ModuleInfoProvider { get; }
public ILogger<ListModulesCommand> Logger { get; set; }
public ListModulesCommand(ModuleInfoProvider moduleInfoProvider)
{
ModuleInfoProvider = moduleInfoProvider;
Logger = NullLogger<ListModulesCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
var modules = await ModuleInfoProvider.GetModuleListAsync();
var freeModules = modules.Where(m => !m.IsPro).ToList();
var proModules = modules.Where(m => m.IsPro).ToList();
var output = new StringBuilder(Environment.NewLine);
output.AppendLine("Open Source Application Modules");
output.AppendLine();
foreach (var module in freeModules)
{
output.AppendLine($"> {module.DisplayName.PadRight(50)} ({module.Name})");
}
if (commandLineArgs.Options.ContainsKey("include-pro-modules"))
{
output.AppendLine();
output.AppendLine("Commercial (Pro) Application Modules");
output.AppendLine();
foreach (var module in proModules)
{
output.AppendLine($"> {module.DisplayName.PadRight(50)} ({module.Name})");
}
}
Logger.LogInformation(output.ToString());
}
public string GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("'list-modules' command is used for listing open source application modules.");
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine(" abp list-modules");
sb.AppendLine(" abp list-modules --include-pro-modules");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine(" --include-pro-modules Includes commercial (pro) modules in the output.");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
return sb.ToString();
}
public string GetShortDescription()
{
return "List open source application modules";
}
}
}

62
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -147,19 +147,34 @@ namespace Volo.Abp.Cli.Commands
}
var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs);
if (!createSolutionFolder)
{
Logger.LogInformation("Create Solution Folder: no");
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
var outputFolderRoot =
outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory();
outputFolder = createSolutionFolder ?
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
outputFolderRoot;
SolutionName solutionName;
if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(template))
{
var microserviceSolutionName = FindMicroserviceSolutionName(outputFolderRoot);
if (microserviceSolutionName == null)
{
throw new CliUsageException("This command should be run inside a folder that contains a microservice solution!");
}
solutionName = SolutionName.Parse(microserviceSolutionName, projectName);
outputFolder = MicroserviceServiceTemplateBase.CalculateTargetFolder(outputFolderRoot, projectName);
uiFramework = uiFramework == UiFramework.NotSpecified ? FindMicroserviceSolutionUiFramework(outputFolderRoot) : uiFramework;
}
else
{
solutionName = SolutionName.Parse(projectName);
outputFolder = createSolutionFolder ?
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
outputFolderRoot;
}
Volo.Abp.IO.DirectoryHelper.CreateIfNotExists(outputFolder);
@ -176,7 +191,7 @@ namespace Volo.Abp.Cli.Commands
var result = await TemplateProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(projectName),
solutionName,
template,
version,
databaseProvider,
@ -245,6 +260,32 @@ namespace Volo.Abp.Cli.Commands
}
}
private string FindMicroserviceSolutionName(string outputFolderRoot)
{
var slnFile = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
if (slnFile == null)
{
return null;
}
return Path.GetFileName(slnFile).RemovePostFix(".sln");
}
private UiFramework FindMicroserviceSolutionUiFramework(string outputFolderRoot)
{
if (Directory.Exists(Path.Combine(outputFolderRoot, "applications", "blazor")))
{
return UiFramework.Blazor;
}
if (Directory.Exists(Path.Combine(outputFolderRoot, "applications", "web")))
{
return UiFramework.Mvc;
}
return UiFramework.None;
}
private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial)
{
uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework;
@ -383,6 +424,11 @@ namespace Volo.Abp.Cli.Commands
protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Options.ContainsKey("no-ui"))
{
return UiFramework.None;
}
var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long);
switch (optionValue)
{

30
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs

@ -5,6 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
@ -25,7 +26,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var localVoloRepoPath = context.BuildArgs.VoloGitHubLocalRepositoryPath;
new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer(
context.Files,
context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
localAbpRepoPath,
localVoloRepoPath
@ -41,7 +42,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
}
new ProjectReferenceReplacer.NugetReferenceReplacer(
context.Files,
context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
nugetPackageVersion
).Run();
@ -70,13 +71,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private abstract class ProjectReferenceReplacer
{
private readonly List<FileEntry> _entries;
private readonly bool _isMicroserviceServiceTemplate;
private readonly string _projectName;
protected ProjectReferenceReplacer(
List<FileEntry> entries,
ProjectBuildContext context,
string projectName)
{
_entries = entries;
_entries = context.Files;
_isMicroserviceServiceTemplate = MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.Template?.Name);
_projectName = projectName;
}
@ -113,14 +116,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var oldNodeIncludeValue = oldNode.Attributes["Include"].Value;
// ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method
if (oldNodeIncludeValue.Contains(_projectName) && _entries.Any(e=>e.Name.EndsWith(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue))))
if (oldNodeIncludeValue.Contains(_projectName))
{
continue;
if (_isMicroserviceServiceTemplate || _entries.Any(e=>e.Name.EndsWith(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue))))
{
continue;
}
}
XmlNode newNode = null;
newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
XmlNode newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
oldNode.ParentNode.ReplaceChild(newNode, oldNode);
}
@ -145,8 +149,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
private readonly string _nugetPackageVersion;
public NugetReferenceReplacer(List<FileEntry> entries, string projectName, string nugetPackageVersion)
: base(entries, projectName)
public NugetReferenceReplacer(ProjectBuildContext context, string projectName, string nugetPackageVersion)
: base(context, projectName)
{
_nugetPackageVersion = nugetPackageVersion;
}
@ -183,8 +187,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private readonly string _gitHubAbpLocalRepositoryPath;
private readonly string _gitHubVoloLocalRepositoryPath;
public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(entries, projectName)
public LocalProjectPathReferenceReplacer(ProjectBuildContext context, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(context, projectName)
{
_gitHubAbpLocalRepositoryPath = gitHubAbpLocalRepositoryPath;
_gitHubVoloLocalRepositoryPath = gitHubVoloLocalRepositoryPath;

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -85,11 +85,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void SetSolutionAndProjectPathsIfNull(ProjectBuildContext context)
{
if (_solutionFilePath == null)
{
_solutionFilePath = context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.sln")?.Name ??
context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name;
context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name ??
context.FindFile("/MyCompanyName.MyProjectName.MicroserviceName.sln")?.Name;
}
if (_projectFolderPath == null)
{

28
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
@ -8,13 +9,26 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public override void Execute(ProjectBuildContext context)
{
new SolutionRenamer(
context.Files,
"MyCompanyName",
"MyProjectName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.BuildArgs.TemplateName))
{
new SolutionRenamer(
context.Files,
"MyCompanyName.MyProjectName",
"MicroserviceName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
}
else
{
new SolutionRenamer(
context.Files,
"MyCompanyName",
"MyProjectName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
}
}
private class SolutionRenamer

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs

@ -33,7 +33,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
}
if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor)
&& context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName)
&& context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName
&& context.Template.Name != MicroserviceServiceProTemplate.TemplateName)
{
pipeline.Steps.Add(new RemoveRootFolderStep());
}

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs

@ -17,6 +17,11 @@ namespace Volo.Abp.Cli.ProjectBuilding
ProjectName = projectName;
}
public static SolutionName Parse(string fullName, string microserviceName)
{
return new SolutionName(fullName + "." + microserviceName, fullName, microserviceName);
}
public static SolutionName Parse(string fullName)
{
if (fullName.Length < 1)
@ -47,4 +52,4 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new SolutionName(fullName, companyName, projectName);
}
}
}
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs

@ -28,7 +28,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
public TemplateInfoProvider(ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
AuthService authService,
AuthService authService,
CliHttpClientFactory cliHttpClientFactory)
{
CancellationTokenProvider = cancellationTokenProvider;
@ -56,6 +56,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new AppProTemplate();
case MicroserviceProTemplate.TemplateName:
return new MicroserviceProTemplate();
case MicroserviceServiceProTemplate.TemplateName:
return new MicroserviceServiceProTemplate();
case ModuleTemplate.TemplateName:
return new ModuleTemplate();
case ModuleProTemplate.TemplateName:

16
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceProTemplate.cs

@ -0,0 +1,16 @@
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
{
public class MicroserviceServiceProTemplate : MicroserviceServiceTemplateBase
{
/// <summary>
/// "microservice-service-pro".
/// </summary>
public const string TemplateName = "microservice-service-pro";
public MicroserviceServiceProTemplate()
: base(TemplateName)
{
DocumentUrl = null; // todo: set this
}
}
}

62
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
{
public abstract class MicroserviceServiceTemplateBase : TemplateInfo
{
protected MicroserviceServiceTemplateBase([NotNull] string name)
: base(name)
{
}
public static bool IsMicroserviceServiceTemplate(string templateName)
{
return templateName == MicroserviceServiceProTemplate.TemplateName;
}
public static string CalculateTargetFolder(string mainSolutionFolder, string serviceName)
{
serviceName = serviceName.ToCamelCase().RemovePostFix("Service");
return Path.Combine(mainSolutionFolder, "microservices", serviceName);
}
public override IEnumerable<ProjectBuildPipelineStep> GetCustomSteps(ProjectBuildContext context)
{
var steps = new List<ProjectBuildPipelineStep>();
DeleteUnrelatedUiProject(context, steps);
RandomizeStringEncryption(context, steps);
return steps;
}
private static void DeleteUnrelatedUiProject(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
switch (context.BuildArgs.UiFramework)
{
case UiFramework.Blazor:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Web"));
break;
case UiFramework.Mvc:
case UiFramework.NotSpecified:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Blazor"));
break;
default:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Web"));
break;
}
}
private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
steps.Add(new RandomizeStringEncryptionStep());
}
}
}

26
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs

@ -33,27 +33,41 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
switch (context.BuildArgs.UiFramework)
{
case UiFramework.None:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
steps.Add(new RemoveFolderStep("/angular"));
break;
case UiFramework.Angular:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
break;
case UiFramework.Blazor:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveFolderStep("/angular"));
break;
case UiFramework.Mvc:
case UiFramework.NotSpecified:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
steps.Add(new RemoveFolderStep("/angular"));
break;
}
steps.Add(new RemoveFolderStep("/microservices/template"));
}
private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)

63
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs

@ -34,7 +34,8 @@ namespace Volo.Abp.Cli.ProjectModification
}
await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects);
await CreateTsConfigProdJsonAsync(angularPath);
await AddScriptsToPackageJsonAsync(angularPath);
await AddProjectToAngularJsonAsync(angularPath, projects);
}
catch (Exception e)
@ -93,6 +94,61 @@ namespace Volo.Abp.Cli.ProjectModification
File.WriteAllText(angularJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task AddScriptsToPackageJsonAsync(string angularPath)
{
var packageJsonFilePath = Path.Combine(angularPath, "package.json");
var fileContent = File.ReadAllText(packageJsonFilePath);
var json = JObject.Parse(fileContent);
var scriptsJobject = (JObject) json["scripts"];
if (scriptsJobject == null || scriptsJobject["postinstall"] != null || scriptsJobject["compile:ivy"] != null)
{
return;
}
scriptsJobject["postinstall"] = "npm run compile:ivy";
scriptsJobject["compile:ivy"] = "yarn ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points --tsconfig './tsconfig.prod.json' --source node_modules";
File.WriteAllText(packageJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task CreateTsConfigProdJsonAsync(string angularPath)
{
var tsConfigProdJsonFilePath = Path.Combine(angularPath, "tsconfig.prod.json");
if (File.Exists(tsConfigProdJsonFilePath))
{
return;
}
var json = new JObject(
new JProperty("compileOnSave", false),
new JProperty("compilerOptions", new JObject(
new JProperty("baseUrl", "./"),
new JProperty("outDir", "./dist/out-tsc"),
new JProperty("sourceMap", true),
new JProperty("declaration", false),
new JProperty("downlevelIteration", true),
new JProperty("experimentalDecorators", true),
new JProperty("module", "esnext"),
new JProperty("moduleResolution", "node"),
new JProperty("importHelpers", true),
new JProperty("target", "es2015"),
new JProperty("typeRoots", new JArray(new JValue("node_modules/@types"))),
new JProperty("lib", new JArray(new JValue("es2018"), new JValue("dom"))),
new JProperty("types", new JArray(new JValue("jest")))
)),
new JProperty("angularCompilerOptions", new JObject(
new JProperty("fullTemplateTypeCheck", true),
new JProperty("strictInjectionParameters", true)
))
);
File.WriteAllText(tsConfigProdJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task AddPathsToTsConfigAsync(string angularPath, string angularProjectsPath,
List<string> projects)
{
@ -105,7 +161,8 @@ namespace Volo.Abp.Cli.ProjectModification
{
var projectPackageName = await GetProjectPackageNameAsync(angularProjectsPath, project);
var publicApis = Directory.GetFiles(Path.Combine(angularProjectsPath, project), "*public-api.ts", SearchOption.AllDirectories)
var publicApis = Directory.GetFiles(Path.Combine(angularProjectsPath, project), "*public-api.ts",
SearchOption.AllDirectories)
.Where(p => !p.Contains("\\node_modules\\"))
.Select(p => p.RemovePreFix(angularPath).Replace("\\", "/").RemovePreFix("/"));
@ -171,8 +228,10 @@ namespace Volo.Abp.Cli.ProjectModification
{
continue;
}
Directory.Move(folderUnderProject, Path.Combine(folder, Path.GetFileName(folderUnderProject)));
}
projectsInFolder = Directory.GetDirectories(folder);
}

19
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs

@ -29,6 +29,8 @@ namespace Volo.Abp.DependencyInjection
public Dictionary<Type, Type> CustomRepositories { get; }
public List<Type> SpecifiedDefaultRepositories { get; }
public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithoutKey != null;
protected AbpCommonDbContextRegistrationOptions(Type originalDbContextType, IServiceCollection services)
@ -38,6 +40,7 @@ namespace Volo.Abp.DependencyInjection
DefaultRepositoryDbContextType = originalDbContextType;
CustomRepositories = new Dictionary<Type, Type>();
ReplacedDbContextTypes = new List<Type>();
SpecifiedDefaultRepositories = new List<Type>();
}
public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext<TOtherDbContext>()
@ -82,6 +85,20 @@ namespace Volo.Abp.DependencyInjection
return AddDefaultRepositories(typeof(TDefaultRepositoryDbContext), includeAllEntities);
}
public IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository<TEntity>()
{
return AddDefaultRepository(typeof(TEntity));
}
public IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository(Type entityType)
{
EntityHelper.CheckEntity(entityType);
SpecifiedDefaultRepositories.AddIfNotContains(entityType);
return this;
}
public IAbpCommonDbContextRegistrationOptionsBuilder AddRepository<TEntity, TRepository>()
{
AddCustomRepository(typeof(TEntity), typeof(TRepository));
@ -118,4 +135,4 @@ namespace Volo.Abp.DependencyInjection
CustomRepositories[entityType] = repositoryType;
}
}
}
}

14
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs

@ -39,6 +39,20 @@ namespace Volo.Abp.DependencyInjection
/// </param>
IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepositories(Type defaultRepositoryDbContextType, bool includeAllEntities = false);
/// <summary>
/// Registers custom repository for a specific entity.
/// </summary>
/// <typeparam name="TEntity">Entity type</typeparam>
IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository<TEntity>();
/// <summary>
/// Registers default repository for a specific entity.
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository(Type entityType);
/// <summary>
/// Registers custom repository for a specific entity.
/// Custom repositories overrides default repositories.

10
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs

@ -118,9 +118,19 @@ namespace Volo.Abp.Domain.Entities
public static bool IsEntity([NotNull] Type type)
{
Check.NotNull(type, nameof(type));
return typeof(IEntity).IsAssignableFrom(type);
}
public static void CheckEntity([NotNull] Type type)
{
Check.NotNull(type, nameof(type));
if (!IsEntity(type))
{
throw new AbpException($"Given {nameof(type)} is not an entity: {type.AssemblyQualifiedName}. It must implement {typeof(IEntity).AssemblyQualifiedName}.");
}
}
public static bool IsEntityWithId([NotNull] Type type)
{
foreach (var interfaceType in type.GetInterfaces())

30
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs

@ -17,20 +17,27 @@ namespace Volo.Abp.Domain.Repositories
}
public virtual void AddRepositories()
{
RegisterCustomRepositories();
RegisterDefaultRepositories();
RegisterSpecifiedDefaultRepositories();
}
protected virtual void RegisterCustomRepositories()
{
foreach (var customRepository in Options.CustomRepositories)
{
Options.Services.AddDefaultRepository(customRepository.Key, customRepository.Value, replaceExisting: true);
}
if (Options.RegisterDefaultRepositories)
{
RegisterDefaultRepositories();
}
}
protected virtual void RegisterDefaultRepositories()
{
if (!Options.RegisterDefaultRepositories)
{
return;
}
foreach (var entityType in GetEntityTypes(Options.OriginalDbContextType))
{
if (!ShouldRegisterDefaultRepositoryFor(entityType))
@ -42,6 +49,17 @@ namespace Volo.Abp.Domain.Repositories
}
}
protected virtual void RegisterSpecifiedDefaultRepositories()
{
foreach (var entityType in Options.SpecifiedDefaultRepositories)
{
if (!Options.CustomRepositories.ContainsKey(entityType))
{
RegisterDefaultRepository(entityType);
}
}
}
protected virtual void RegisterDefaultRepository(Type entityType)
{
Options.Services.AddDefaultRepository(
@ -92,4 +110,4 @@ namespace Volo.Abp.Domain.Repositories
protected abstract Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType);
}
}
}

2
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs

@ -43,7 +43,7 @@ namespace Volo.Abp.Http.Modeling
public ApplicationApiDescriptionModel CreateSubModel(string[] modules = null, string[] controllers = null, string[] actions = null)
{
var subModel = new ApplicationApiDescriptionModel();
var subModel = ApplicationApiDescriptionModel.Create();;
foreach (var module in Modules.Values)
{

10
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs

@ -41,17 +41,17 @@ namespace Volo.Abp.Http.Modeling
public ControllerApiDescriptionModel AddController(ControllerApiDescriptionModel controller)
{
if (Controllers.ContainsKey(controller.ControllerName))
if (Controllers.ContainsKey(controller.Type))
{
throw new AbpException($"There is already a controller with name: {controller.ControllerName} in module: {RootPath}");
throw new AbpException($"There is already a controller with type: {controller.Type} in module: {RootPath}");
}
return Controllers[controller.ControllerName] = controller;
return Controllers[controller.Type] = controller;
}
public ControllerApiDescriptionModel GetOrAddController(string uniqueName, string name, Type type, [CanBeNull] HashSet<Type> ignoredInterfaces = null)
public ControllerApiDescriptionModel GetOrAddController(string name, Type type, [CanBeNull] HashSet<Type> ignoredInterfaces = null)
{
return Controllers.GetOrAdd(uniqueName, () => ControllerApiDescriptionModel.Create(name, type, ignoredInterfaces));
return Controllers.GetOrAdd(type.FullName, () => ControllerApiDescriptionModel.Create(name, type, ignoredInterfaces));
}
public ModuleApiDescriptionModel CreateSubModel(string[] controllers, string[] actions)

5
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs

@ -10,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
public string Name { get; set; }
public string JsonName { get; set; }
public string Type { get; set; }
public string TypeSimple { get; set; }
@ -29,11 +31,12 @@ namespace Volo.Abp.Http.Modeling
}
public static ParameterApiDescriptionModel Create(string name, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null, string descriptorName = null)
public static ParameterApiDescriptionModel Create(string name, string jsonName, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null, string descriptorName = null)
{
return new ParameterApiDescriptionModel
{
Name = name,
JsonName = jsonName,
NameOnMethod = nameOnMethod,
Type = type != null ? TypeHelper.GetFullNameHandlingNullableAndGenerics(type) : null,
TypeSimple = type != null ? ApiTypeNameHelper.GetSimpleTypeName(type) : null,

4
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs

@ -1,6 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using Volo.Abp.Http.ProxyScripting.Configuration;
namespace Volo.Abp.Http.Modeling
{
@ -9,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
{
public string Name { get; set; }
public string JsonName { get; set; }
public string Type { get; set; }
public string TypeSimple { get; set; }
@ -21,6 +24,7 @@ namespace Volo.Abp.Http.Modeling
return new PropertyApiDescriptionModel
{
Name = propertyInfo.Name,
JsonName = AbpApiProxyScriptingOptions.PropertyNameGenerator.Invoke(propertyInfo),
Type = ApiTypeNameHelper.GetTypeName(propertyInfo.PropertyType),
TypeSimple = ApiTypeNameHelper.GetSimpleTypeName(propertyInfo.PropertyType),
IsRequired = propertyInfo.IsDefined(typeof(RequiredAttribute), true)

22
framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingOptions.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.Http.ProxyScripting.Configuration
{
@ -7,9 +8,30 @@ namespace Volo.Abp.Http.ProxyScripting.Configuration
{
public IDictionary<string, Type> Generators { get; }
public static Func<PropertyInfo, string> PropertyNameGenerator { get; set; }
public AbpApiProxyScriptingOptions()
{
Generators = new Dictionary<string, Type>();
PropertyNameGenerator = propertyInfo =>
{
var jsonPropertyNameAttribute = propertyInfo.GetSingleAttributeOrNull<System.Text.Json.Serialization.JsonPropertyNameAttribute>(true);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = propertyInfo.GetSingleAttributeOrNull<Newtonsoft.Json.JsonPropertyAttribute>(true);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
return null;
};
}
}
}

2
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs

@ -43,7 +43,7 @@ namespace Volo.Abp.Settings
return value;
}
public async Task<List<SettingValue>> GetAllAsync(string[] names)
public virtual async Task<List<SettingValue>> GetAllAsync(string[] names)
{
var result = new Dictionary<string, SettingValue>();
var settingDefinitions = SettingDefinitionManager.GetAll().Where(x => names.Contains(x.Name)).ToList();

3
framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false"/>
</Weavers>

30
framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

24
framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props"/>
<Import Project="..\..\..\common.props"/>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Sms.Aliyun</AssemblyName>
<PackageId>Volo.Abp.Sms.Aliyun</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace/>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Sms\Volo.Abp.Sms.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="1.0.2"/>
</ItemGroup>
</Project>

11
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.Sms.Aliyun
{
public class AbpAliyunSmsOptions
{
public string AccessKeySecret { get; set; }
public string AccessKeyId { get; set; }
public string EndPoint { get; set; }
}
}

16
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpSmsAliyunModule.cs

@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Sms.Aliyun
{
[DependsOn(typeof(AbpSmsModule))]
public class AbpSmsAliyunModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAliyunSmsOptions>(configuration.GetSection("AbpAliyunSms"));
}
}
}

43
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AliyunSmsSender.cs

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using AliyunClient = AlibabaCloud.SDK.Dysmsapi20170525.Client;
using AliyunConfig = AlibabaCloud.OpenApiClient.Models.Config;
using AliyunSendSmsRequest = AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest;
namespace Volo.Abp.Sms.Aliyun
{
public class AliyunSmsSender : ISmsSender, ITransientDependency
{
protected AbpAliyunSmsOptions Options { get; }
public AliyunSmsSender(IOptionsSnapshot<AbpAliyunSmsOptions> options)
{
Options = options.Value;
}
public async Task SendAsync(SmsMessage smsMessage)
{
var client = CreateClient();
await client.SendSmsAsync(new AliyunSendSmsRequest
{
PhoneNumbers = smsMessage.PhoneNumber,
SignName = smsMessage.Properties.GetOrDefault("SignName") as string,
TemplateCode = smsMessage.Properties.GetOrDefault("TemplateCode") as string,
TemplateParam = smsMessage.Text
});
}
protected virtual AliyunClient CreateClient()
{
return new(new AliyunConfig
{
AccessKeyId = Options.AccessKeyId,
AccessKeySecret = Options.AccessKeySecret,
Endpoint = Options.EndPoint
});
}
}
}

1
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs

@ -110,6 +110,7 @@ namespace Volo.Abp.AspNetCore.Mvc
app.UseCorrelationId();
app.UseVirtualFiles();
app.UseAbpRequestLocalization();
app.UseAbpSecurityHeaders();
app.UseRouting();
app.UseMiddleware<FakeAuthenticationMiddleware>();
app.UseAbpClaimsMap();

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs

@ -2,21 +2,11 @@
using System.Security.Claims;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Autofac;
using Volo.Abp.MemoryDb;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Authorization
{
[DependsOn(
typeof(AbpAspNetCoreTestBaseModule),
typeof(AbpMemoryDbTestModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAutofacModule)
)]
public class AuthTestController_Tests : AspNetCoreMvcTestBase
{
private readonly FakeUserClaims _fakeRequiredService;

143
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention_Tests.cs

@ -0,0 +1,143 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using System;
using System.Reflection;
using Volo.Abp.DependencyInjection;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Conventions
{
public class AbpServiceConvention_Tests : AspNetCoreMvcTestBase
{
private readonly IConventionalRouteBuilder _conventionalRouteBuilder;
private readonly IOptions<AbpAspNetCoreMvcOptions> _options;
public AbpServiceConvention_Tests()
{
_conventionalRouteBuilder = GetRequiredService<IConventionalRouteBuilder>();
_options = GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>();
}
[Fact]
public void Should_Not_Remove_Derived_Controller_If_Not_Expose_Service()
{
// Arrange
var applicationModel = new ApplicationModel();
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(baseControllerModel);
var derivedControllerModel = new ControllerModel(typeof(DerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldContain(baseControllerModel);
applicationModel.Controllers.ShouldContain(derivedControllerModel);
}
[Fact]
public void Should_Remove_Exposed_Controller_If_Expose_Self()
{
// Arrange
var applicationModel = new ApplicationModel();
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(baseControllerModel);
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceIncludeSelfDerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldNotContain(baseControllerModel);
applicationModel.Controllers.ShouldContain(derivedControllerModel);
}
[Fact]
public void Should_Not_Remove_Derived_Controller_If_No_Base_Controller_Model()
{
// Arrange
var applicationModel = new ApplicationModel();
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceDerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldContain(derivedControllerModel);
}
[Fact]
public void Should_Remove_Derived_Controller_If_Expose_Service()
{
// Arrange
var applicationModel = new ApplicationModel();
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(baseControllerModel);
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceDerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldContain(baseControllerModel);
applicationModel.Controllers.ShouldNotContain(derivedControllerModel);
}
}
public class BaseController : Controller
{
}
public class DerivedController : BaseController
{
}
[ExposeServices(typeof(BaseController))]
public class ExposeServiceDerivedController : BaseController
{
}
[ExposeServices(typeof(BaseController), IncludeSelf = true)]
public class ExposeServiceIncludeSelfDerivedController : BaseController
{
}
}

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs

@ -2,20 +2,10 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.AspNetCore.Mvc.Authorization;
using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Autofac;
using Volo.Abp.MemoryDb;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Security.Claims
{
[DependsOn(
typeof(AbpAspNetCoreTestBaseModule),
typeof(AbpMemoryDbTestModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAutofacModule)
)]
public class ClaimsMapTestController_Tests : AspNetCoreMvcTestBase
{
private readonly FakeUserClaims _fakeRequiredService;

12
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController.cs

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace Volo.Abp.AspNetCore.Mvc.Security.Headers
{
public class SecurityHeadersTestController : AbpController
{
public ActionResult Get()
{
return Content("OK");
}
}
}

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController_Tests.cs

@ -0,0 +1,19 @@
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Security.Headers
{
public class SecurityHeadersTestController_Tests : AspNetCoreMvcTestBase
{
[Fact]
public async Task SecurityHeaders_Should_Be_Added()
{
var responseMessage = await GetResponseAsync("/SecurityHeadersTest/Get");
responseMessage.Headers.ShouldContain(x => x.Key == "X-Content-Type-Options" & x.Value.First().ToString() == "nosniff");
responseMessage.Headers.ShouldContain(x => x.Key == "X-XSS-Protection" & x.Value.First().ToString() == "1; mode=block");
responseMessage.Headers.ShouldContain(x => x.Key == "X-Frame-Options" & x.Value.First().ToString() == "SAMEORIGIN");
}
}
}

54
framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs

@ -189,6 +189,60 @@ namespace Volo.Abp.Domain.Repositories
services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestCustomBaseRepository<MyTestEntityWithInt32Pk, int>));
}
[Fact]
public void Should_Register_Default_Repository()
{
//Arrange
var services = new ServiceCollection();
var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext), services);
options.AddDefaultRepository<MyTestAggregateRootWithGuidPk>();
//Act
new MyTestRepositoryRegistrar(options).AddRepositories();
//MyTestAggregateRootWithoutPk
services.ShouldNotContainService(typeof(IReadOnlyRepository<MyTestAggregateRootWithoutPk>));
services.ShouldNotContainService(typeof(IBasicRepository<MyTestAggregateRootWithoutPk>));
services.ShouldNotContainService(typeof(IRepository<MyTestAggregateRootWithoutPk>));
//MyTestAggregateRootWithGuidPk
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
}
[Fact]
public void Should_Not_Register_Default_Repository_If_Registered_Custom_Repository()
{
//Arrange
var services = new ServiceCollection();
var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext), services);
options
.AddDefaultRepository<MyTestAggregateRootWithGuidPk>()
.AddRepository<MyTestAggregateRootWithGuidPk, MyTestAggregateRootWithDefaultPkCustomRepository>();;
//Act
new MyTestRepositoryRegistrar(options).AddRepositories();
//MyTestAggregateRootWithGuidPk
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IReadOnlyBasicRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
}
public class MyTestRepositoryRegistrar : RepositoryRegistrarBase<AbpCommonDbContextRegistrationOptions>
{
public MyTestRepositoryRegistrar(AbpCommonDbContextRegistrationOptions options)

26
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
<UserSecretsId>9f0d2c00-80c1-435b-bfab-2c39c8249091</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
</ItemGroup>
<ItemGroup>
<None Remove="appsettings.json" />
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

12
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestBase.cs

@ -0,0 +1,12 @@
using Volo.Abp.Testing;
namespace Volo.Abp.Sms.Aliyun
{
public class AbpSmsAliyunTestBase : AbpIntegratedTest<AbpSmsAliyunTestsModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

18
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestsModule.cs

@ -0,0 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Sms.Aliyun
{
[DependsOn(typeof(AbpSmsAliyunModule))]
public class AbpSmsAliyunTestsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAliyunSmsOptions>(
configuration.GetSection("AbpAliyunSms")
);
}
}
}

37
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AliyunSmsSender_Tests.cs

@ -0,0 +1,37 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Xunit;
namespace Volo.Abp.Sms.Aliyun
{
public class AliyunSmsSender_Tests : AbpSmsAliyunTestBase
{
private readonly ISmsSender _smsSender;
private readonly IConfiguration _configuration;
public AliyunSmsSender_Tests()
{
_configuration = GetRequiredService<IConfiguration>();
_smsSender = GetRequiredService<ISmsSender>();
}
[Fact]
public async Task SendSms_Test()
{
var config = _configuration.GetSection("AbpAliyunSms");
// Please fill in the real parameters in the appsettings.json file.
if (config["AccessKeyId"] == "<Enter your AccessKeyId from Aliyun>")
{
return;
}
var msg = new SmsMessage(config["TargetPhoneNumber"],
config["TemplateParam"]);
msg.Properties.Add("SignName", config["SignName"]);
msg.Properties.Add("TemplateCode", config["TemplateCode"]);
await _smsSender.SendAsync(msg);
}
}
}

11
framework/test/Volo.Abp.Sms.Aliyun.Tests/appsettings.json

@ -0,0 +1,11 @@
{
"AbpAliyunSms": {
"AccessKeySecret": "<Enter your AccessKeySecret from Aliyun>",
"AccessKeyId": "<Enter your AccessKeyId from Aliyun>",
"EndPoint": "<Enter your EndPoint from Aliyun>",
"TargetPhoneNumber": "<Enter the target phone number to receive the SMS>",
"SignName": "<Enter the SignName from Aliyun>",
"TemplateCode": "<Enter the TemplateCode you need to send>",
"TemplateParam": "<Enter the template parameters>"
}
}

2
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs

@ -7,6 +7,6 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
[ConnectionStringName(AbpAuditLoggingDbProperties.ConnectionStringName)]
public interface IAuditLoggingDbContext : IEfCoreDbContext
{
DbSet<AuditLog> AuditLogs { get; set; }
DbSet<AuditLog> AuditLogs { get; }
}
}

10
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs

@ -16,14 +16,14 @@ namespace Volo.Blogging.EntityFrameworkCore
{
DbSet<BlogUser> Users { get; }
DbSet<Blog> Blogs { get; set; }
DbSet<Blog> Blogs { get; }
DbSet<Post> Posts { get; set; }
DbSet<Post> Posts { get; }
DbSet<Comment> Comments { get; set; }
DbSet<Comment> Comments { get; }
DbSet<PostTag> PostTags { get; set; }
DbSet<PostTag> PostTags { get; }
DbSet<Tag> Tags { get; set; }
DbSet<Tag> Tags { get; }
}
}

1576
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201224140744_Initial.Designer.cs

File diff suppressed because it is too large

1647
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201225120048_Added_Page.Designer.cs

File diff suppressed because it is too large

46
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201225120048_Added_Page.cs

@ -1,46 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Added_Page : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CmsPages",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(515)", maxLength: 515, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsPages", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_CmsPages_TenantId_Url",
table: "CmsPages",
columns: new[] { "TenantId", "Url" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsPages");
}
}
}

1643
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201228083120_Updated_Tag_Removed_HexColor.Designer.cs

File diff suppressed because it is too large

1725
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201231111657_Added_Blob_Storing.Designer.cs

File diff suppressed because it is too large

95
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201231111657_Added_Blob_Storing.cs

@ -1,95 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Added_Blob_Storing : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Description",
table: "CmsPages",
type: "nvarchar(512)",
maxLength: 512,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(515)",
oldMaxLength: 515,
oldNullable: true);
migrationBuilder.CreateTable(
name: "AbpBlobContainers",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBlobContainers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AbpBlobs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ContainerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Content = table.Column<byte[]>(type: "varbinary(max)", maxLength: 2147483647, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBlobs", x => x.Id);
table.ForeignKey(
name: "FK_AbpBlobs_AbpBlobContainers_ContainerId",
column: x => x.ContainerId,
principalTable: "AbpBlobContainers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AbpBlobContainers_TenantId_Name",
table: "AbpBlobContainers",
columns: new[] { "TenantId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_AbpBlobs_ContainerId",
table: "AbpBlobs",
column: "ContainerId");
migrationBuilder.CreateIndex(
name: "IX_AbpBlobs_TenantId_ContainerId_Name",
table: "AbpBlobs",
columns: new[] { "TenantId", "ContainerId", "Name" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AbpBlobs");
migrationBuilder.DropTable(
name: "AbpBlobContainers");
migrationBuilder.AlterColumn<string>(
name: "Description",
table: "CmsPages",
type: "nvarchar(515)",
maxLength: 515,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(512)",
oldMaxLength: 512,
oldNullable: true);
}
}
}

106
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210209082122_UrlSlugToSlug.cs

@ -1,106 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class UrlSlugToSlug : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CmsBlogPosts",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Title = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
ShortDescription = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogPosts", x => x.Id);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_CreatorId",
column: x => x.CreatorId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_DeleterId",
column: x => x.DeleterId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId",
column: x => x.LastModifierId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "CmsBlogs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Slug = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogs", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_CreatorId",
table: "CmsBlogPosts",
column: "CreatorId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_DeleterId",
table: "CmsBlogPosts",
column: "DeleterId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_LastModifierId",
table: "CmsBlogPosts",
column: "LastModifierId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_Slug_BlogId",
table: "CmsBlogPosts",
columns: new[] { "Slug", "BlogId" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsBlogPosts");
migrationBuilder.DropTable(
name: "CmsBlogs");
}
}
}

73
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210210105857_Added_Media.cs

@ -1,73 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Added_Media : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsPages");
migrationBuilder.CreateTable(
name: "CmsMediaDescriptors",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false),
MimeType = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Size = table.Column<long>(type: "bigint", maxLength: 2147483647, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsMediaDescriptors", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsMediaDescriptors");
migrationBuilder.CreateTable(
name: "CmsPages",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsPages", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_CmsPages_TenantId_Url",
table: "CmsPages",
columns: new[] { "TenantId", "Url" });
}
}
}

46
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219084931_PageSlugChange.cs

@ -1,46 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class PageSlugChange : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CmsPages",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsPages", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_CmsPages_TenantId_Slug",
table: "CmsPages",
columns: new[] { "TenantId", "Slug" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsPages");
}
}
}

66
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219084931_PageSlugChange.Designer.cs → modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219113255_Initial.Designer.cs

@ -11,8 +11,8 @@ using Volo.CmsKit.EntityFrameworkCore;
namespace Volo.CmsKit.Migrations
{
[DbContext(typeof(UnifiedDbContext))]
[Migration("20210219084931_PageSlugChange")]
partial class PageSlugChange
[Migration("20210219113255_Initial")]
partial class Initial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
@ -1191,6 +1191,68 @@ namespace Volo.CmsKit.Migrations
b.ToTable("CmsBlogs");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogFeature", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("FeatureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.HasKey("Id");
b.ToTable("CmsBlogFeatures");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.Property<Guid>("Id")

241
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20201224140744_Initial.cs → modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219113255_Initial.cs

@ -39,6 +39,21 @@ namespace Volo.CmsKit.Migrations
table.PrimaryKey("PK_AbpAuditLogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AbpBlobContainers",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBlobContainers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AbpClaimTypes",
columns: table => new
@ -251,6 +266,52 @@ namespace Volo.CmsKit.Migrations
table.PrimaryKey("PK_AbpUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsBlogFeatures",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
FeatureName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Enabled = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogFeatures", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsBlogs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Slug = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsComments",
columns: table => new
@ -306,6 +367,54 @@ namespace Volo.CmsKit.Migrations
table.PrimaryKey("PK_CmsEntityTags", x => new { x.EntityId, x.TagId });
});
migrationBuilder.CreateTable(
name: "CmsMediaDescriptors",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false),
MimeType = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Size = table.Column<long>(type: "bigint", maxLength: 2147483647, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsMediaDescriptors", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsPages",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsPages", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsRatings",
columns: table => new
@ -328,10 +437,9 @@ namespace Volo.CmsKit.Migrations
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Name = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
HexColor = table.Column<string>(type: "nvarchar(6)", maxLength: 6, nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
@ -435,6 +543,29 @@ namespace Volo.CmsKit.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AbpBlobs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ContainerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Content = table.Column<byte[]>(type: "varbinary(max)", maxLength: 2147483647, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBlobs", x => x.Id);
table.ForeignKey(
name: "FK_AbpBlobs_AbpBlobContainers_ContainerId",
column: x => x.ContainerId,
principalTable: "AbpBlobContainers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AbpOrganizationUnitRoles",
columns: table => new
@ -617,6 +748,49 @@ namespace Volo.CmsKit.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "CmsBlogPosts",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Title = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
ShortDescription = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsBlogPosts", x => x.Id);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_CreatorId",
column: x => x.CreatorId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_DeleterId",
column: x => x.DeleterId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId",
column: x => x.LastModifierId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "AbpEntityPropertyChanges",
columns: table => new
@ -660,6 +834,21 @@ namespace Volo.CmsKit.Migrations
table: "AbpAuditLogs",
columns: new[] { "TenantId", "UserId", "ExecutionTime" });
migrationBuilder.CreateIndex(
name: "IX_AbpBlobContainers_TenantId_Name",
table: "AbpBlobContainers",
columns: new[] { "TenantId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_AbpBlobs_ContainerId",
table: "AbpBlobs",
column: "ContainerId");
migrationBuilder.CreateIndex(
name: "IX_AbpBlobs_TenantId_ContainerId_Name",
table: "AbpBlobs",
columns: new[] { "TenantId", "ContainerId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_AbpEntityChanges_AuditLogId",
table: "AbpEntityChanges",
@ -787,6 +976,26 @@ namespace Volo.CmsKit.Migrations
table: "AbpUsers",
column: "UserName");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_CreatorId",
table: "CmsBlogPosts",
column: "CreatorId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_DeleterId",
table: "CmsBlogPosts",
column: "DeleterId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_LastModifierId",
table: "CmsBlogPosts",
column: "LastModifierId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_Slug_BlogId",
table: "CmsBlogPosts",
columns: new[] { "Slug", "BlogId" });
migrationBuilder.CreateIndex(
name: "IX_CmsComments_TenantId_EntityType_EntityId",
table: "CmsComments",
@ -807,6 +1016,11 @@ namespace Volo.CmsKit.Migrations
table: "CmsEntityTags",
columns: new[] { "TenantId", "EntityId", "TagId" });
migrationBuilder.CreateIndex(
name: "IX_CmsPages_TenantId_Slug",
table: "CmsPages",
columns: new[] { "TenantId", "Slug" });
migrationBuilder.CreateIndex(
name: "IX_CmsRatings_TenantId_EntityType_EntityId_CreatorId",
table: "CmsRatings",
@ -843,6 +1057,9 @@ namespace Volo.CmsKit.Migrations
migrationBuilder.DropTable(
name: "AbpAuditLogActions");
migrationBuilder.DropTable(
name: "AbpBlobs");
migrationBuilder.DropTable(
name: "AbpClaimTypes");
@ -888,6 +1105,15 @@ namespace Volo.CmsKit.Migrations
migrationBuilder.DropTable(
name: "AbpUserTokens");
migrationBuilder.DropTable(
name: "CmsBlogFeatures");
migrationBuilder.DropTable(
name: "CmsBlogPosts");
migrationBuilder.DropTable(
name: "CmsBlogs");
migrationBuilder.DropTable(
name: "CmsComments");
@ -897,6 +1123,12 @@ namespace Volo.CmsKit.Migrations
migrationBuilder.DropTable(
name: "CmsEntityTags");
migrationBuilder.DropTable(
name: "CmsMediaDescriptors");
migrationBuilder.DropTable(
name: "CmsPages");
migrationBuilder.DropTable(
name: "CmsRatings");
@ -907,7 +1139,7 @@ namespace Volo.CmsKit.Migrations
name: "CmsUserReactions");
migrationBuilder.DropTable(
name: "CmsUsers");
name: "AbpBlobContainers");
migrationBuilder.DropTable(
name: "AbpEntityChanges");
@ -924,6 +1156,9 @@ namespace Volo.CmsKit.Migrations
migrationBuilder.DropTable(
name: "AbpUsers");
migrationBuilder.DropTable(
name: "CmsUsers");
migrationBuilder.DropTable(
name: "AbpAuditLogs");
}

151
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210209082122_UrlSlugToSlug.Designer.cs → modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219144454_BlogFeatureEnabledColumnRename.Designer.cs

@ -11,17 +11,17 @@ using Volo.CmsKit.EntityFrameworkCore;
namespace Volo.CmsKit.Migrations
{
[DbContext(typeof(UnifiedDbContext))]
[Migration("20210209082122_UrlSlugToSlug")]
partial class UrlSlugToSlug
[Migration("20210219144454_BlogFeatureEnabledColumnRename")]
partial class BlogFeatureEnabledColumnRename
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.UseIdentityColumns()
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.2");
.HasAnnotation("ProductVersion", "5.0.3")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
{
@ -1191,6 +1191,68 @@ namespace Volo.CmsKit.Migrations
b.ToTable("CmsBlogs");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogFeature", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("FeatureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsEnabled")
.HasColumnType("bit");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.HasKey("Id");
b.ToTable("CmsBlogFeatures");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.Property<Guid>("Id")
@ -1388,6 +1450,75 @@ namespace Volo.CmsKit.Migrations
b.ToTable("CmsContents");
});
modelBuilder.Entity("Volo.CmsKit.MediaDescriptors.MediaDescriptor", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("MimeType")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("nvarchar(255)");
b.Property<long>("Size")
.HasMaxLength(2147483647)
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("CmsMediaDescriptors");
});
modelBuilder.Entity("Volo.CmsKit.Pages.Page", b =>
{
b.Property<Guid>("Id")
@ -1438,6 +1569,11 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
@ -1447,14 +1583,9 @@ namespace Volo.CmsKit.Migrations
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Url")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("TenantId", "Url");
b.HasIndex("TenantId", "Slug");
b.ToTable("CmsPages");
});

23
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210219144454_BlogFeatureEnabledColumnRename.cs

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class BlogFeatureEnabledColumnRename : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Enabled",
table: "CmsBlogFeatures",
newName: "IsEnabled");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "IsEnabled",
table: "CmsBlogFeatures",
newName: "Enabled");
}
}
}

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

Loading…
Cancel
Save