mirror of https://github.com/abpframework/abp.git
338 changed files with 10854 additions and 8153 deletions
@ -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. |
|||
|
|||
 |
|||
|
|||
 |
|||
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 59 KiB |
@ -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)); |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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"; |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -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
|
|||
} |
|||
} |
|||
} |
|||
@ -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()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false"/> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -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> |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -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")); |
|||
} |
|||
} |
|||
} |
|||
@ -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 |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -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 |
|||
{ |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
@ -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") |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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>" |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -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"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
} |
|||
@ -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" }); |
|||
} |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
} |
|||
@ -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…
Reference in new issue