Browse Source

Merge branch 'dev' into maliming/ChallengeAccountController

pull/8002/head
maliming 6 years ago
parent
commit
0e122f289d
  1. 2
      docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md
  2. 37
      npm/ng-packs/angular.json
  3. 4
      npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts
  4. 2
      npm/ng-packs/apps/dev-app/src/app/app.module.ts
  5. 2
      npm/ng-packs/apps/dev-app/src/app/home/home.component.ts
  6. 5
      npm/ng-packs/apps/dev-app/src/environments/environment.ts
  7. 3
      npm/ng-packs/packages/account/README.md
  8. 7
      npm/ng-packs/packages/account/config/ng-package.json
  9. 12
      npm/ng-packs/packages/account/config/src/account-config.module.ts
  10. 1
      npm/ng-packs/packages/account/config/src/enums/index.ts
  11. 6
      npm/ng-packs/packages/account/config/src/enums/route-names.ts
  12. 1
      npm/ng-packs/packages/account/config/src/providers/index.ts
  13. 39
      npm/ng-packs/packages/account/config/src/providers/route.provider.ts
  14. 3
      npm/ng-packs/packages/account/config/src/public-api.ts
  15. 6
      npm/ng-packs/packages/account/jest.config.js
  16. 8
      npm/ng-packs/packages/account/ng-package.json
  17. 6
      npm/ng-packs/packages/account/ngcc.config.js
  18. 16
      npm/ng-packs/packages/account/package.json
  19. 93
      npm/ng-packs/packages/account/src/lib/account-routing.module.ts
  20. 63
      npm/ng-packs/packages/account/src/lib/account.module.ts
  21. 25
      npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html
  22. 28
      npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts
  23. 48
      npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html
  24. 99
      npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts
  25. 40
      npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.html
  26. 35
      npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts
  27. 8
      npm/ng-packs/packages/account/src/lib/components/index.ts
  28. 60
      npm/ng-packs/packages/account/src/lib/components/login/login.component.html
  29. 80
      npm/ng-packs/packages/account/src/lib/components/login/login.component.ts
  30. 62
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html
  31. 45
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
  32. 46
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.html
  33. 58
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts
  34. 51
      npm/ng-packs/packages/account/src/lib/components/register/register.component.html
  35. 102
      npm/ng-packs/packages/account/src/lib/components/register/register.component.ts
  36. 49
      npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.html
  37. 70
      npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts
  38. 63
      npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html
  39. 73
      npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts
  40. 11
      npm/ng-packs/packages/account/src/lib/enums/components.ts
  41. 1
      npm/ng-packs/packages/account/src/lib/enums/index.ts
  42. 15
      npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts
  43. 1
      npm/ng-packs/packages/account/src/lib/guards/index.ts
  44. 12
      npm/ng-packs/packages/account/src/lib/models/account.ts
  45. 3
      npm/ng-packs/packages/account/src/lib/models/config-options.ts
  46. 2
      npm/ng-packs/packages/account/src/lib/models/index.ts
  47. 17
      npm/ng-packs/packages/account/src/lib/proxy/README.md
  48. 37
      npm/ng-packs/packages/account/src/lib/proxy/account/account.service.ts
  49. 2
      npm/ng-packs/packages/account/src/lib/proxy/account/index.ts
  50. 20
      npm/ng-packs/packages/account/src/lib/proxy/account/models.ts
  51. 4745
      npm/ng-packs/packages/account/src/lib/proxy/generate-proxy.json
  52. 1
      npm/ng-packs/packages/account/src/lib/proxy/identity/index.ts
  53. 15
      npm/ng-packs/packages/account/src/lib/proxy/identity/models.ts
  54. 3
      npm/ng-packs/packages/account/src/lib/proxy/index.ts
  55. 1
      npm/ng-packs/packages/account/src/lib/services/index.ts
  56. 28
      npm/ng-packs/packages/account/src/lib/services/manage-profile.state.service.ts
  57. 6
      npm/ng-packs/packages/account/src/lib/tokens/config-options.token.ts
  58. 1
      npm/ng-packs/packages/account/src/lib/tokens/index.ts
  59. 9
      npm/ng-packs/packages/account/src/lib/utils/auth-utils.ts
  60. 8
      npm/ng-packs/packages/account/src/lib/utils/factory-utils.ts
  61. 2
      npm/ng-packs/packages/account/src/lib/utils/index.ts
  62. 9
      npm/ng-packs/packages/account/src/public-api.ts
  63. 19
      npm/ng-packs/packages/account/tsconfig.lib.json
  64. 6
      npm/ng-packs/packages/account/tsconfig.lib.prod.json
  65. 11
      npm/ng-packs/packages/account/tsconfig.spec.json
  66. 17
      npm/ng-packs/packages/account/tslint.json
  67. 4
      npm/ng-packs/packages/core/src/lib/core.module.ts
  68. 2
      npm/ng-packs/packages/core/src/lib/guards/auth.guard.ts
  69. 8
      npm/ng-packs/packages/core/src/lib/models/session.ts
  70. 60
      npm/ng-packs/packages/core/src/lib/services/auth.service.ts
  71. 6
      npm/ng-packs/packages/core/src/lib/services/session-state.service.ts
  72. 148
      npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts
  73. 1
      npm/ng-packs/packages/core/src/lib/strategies/index.ts
  74. 6
      npm/ng-packs/packages/core/src/lib/tests/auth.guard.spec.ts
  75. 2
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  76. 7
      npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html
  77. 2
      npm/ng-packs/packages/setting-management/config/src/providers/setting-tab.provider.ts
  78. 26
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
  79. 4
      npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts
  80. 2
      npm/ng-packs/tsconfig.json
  81. 2366
      npm/ng-packs/yarn.lock
  82. 2
      templates/app/angular/src/app/home/home.component.ts
  83. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application.Contracts/MyCompanyName.MyProjectName.Application.Contracts.csproj
  84. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application.Contracts/MyProjectNameApplicationContractsModule.cs
  85. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application/MyCompanyName.MyProjectName.Application.csproj
  86. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application/MyProjectNameApplicationModule.cs
  87. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj
  88. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyProjectNameDomainSharedModule.cs
  89. 10
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyProjectNameGlobalFeatureConfigurator.cs
  90. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj
  91. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyProjectNameDomainModule.cs
  92. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/MyProjectNameMigrationsDbContext.cs
  93. 2954
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20210308123703_CmsKit.Designer.cs
  94. 345
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20210308123703_CmsKit.cs
  95. 651
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/MyProjectNameMigrationsDbContextModelSnapshot.cs
  96. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameEntityFrameworkCoreModule.cs
  97. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj
  98. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj
  99. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyProjectNameHttpApiClientModule.cs
  100. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs

2
docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md

@ -781,7 +781,7 @@ namespace IssueTracking.Issues
- 创建时间大于30天
- 最近30天没有评论
这个业务逻辑就被实现再了仓储内部,当我们需要重用这个业务规则时就会出现问题.
这个业务逻辑就被实现在了仓储内部,当我们需要重用这个业务规则时就会出现问题.
例如:我们需要再实体`Issue`上添加一个方法来判断是否非活动`bool IsInActive()`,以方便我们在`Issue`实例上获取.

37
npm/ng-packs/angular.json

@ -184,6 +184,43 @@
}
}
},
"account": {
"projectType": "library",
"root": "packages/account",
"sourceRoot": "packages/account/src",
"prefix": "abp",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "packages/account/tsconfig.lib.json",
"project": "packages/account/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "packages/account/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-builders/jest:run",
"options": {
"coverage": true,
"passWithNoTests": true
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"packages/account/tsconfig.lib.json",
"packages/account/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**"]
}
}
}
},
"identity": {
"projectType": "library",
"root": "packages/identity",

4
npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts

@ -7,6 +7,10 @@ const routes: Routes = [
pathMatch: 'full',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule),
},
{
path: 'account',
loadChildren: () => import('@abp/ng.account').then(m => m.AccountModule.forLazy()),
},
{
path: 'identity',
loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()),

2
npm/ng-packs/apps/dev-app/src/app/app.module.ts

@ -11,6 +11,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { InspectorModule } from '@ngneat/inspector';
import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';
import { NgxsModule } from '@ngxs/store';
import { AccountConfigModule } from '@abp/ng.account/config';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@ -33,6 +34,7 @@ const INSPECTION_TOOLS = [
skipGetAppConfiguration: false,
}),
ThemeSharedModule.forRoot(),
AccountConfigModule.forRoot(),
IdentityConfigModule.forRoot(),
TenantManagementConfigModule.forRoot(),
SettingManagementConfigModule.forRoot(),

2
npm/ng-packs/apps/dev-app/src/app/home/home.component.ts

@ -14,6 +14,6 @@ export class HomeComponent {
constructor(private oAuthService: OAuthService, private authService: AuthService) {}
login() {
this.authService.initLogin();
this.authService.navigateToLogin();
}
}

5
npm/ng-packs/apps/dev-app/src/environments/environment.ts

@ -12,10 +12,11 @@ export const environment = {
},
oAuthConfig: {
issuer: 'https://localhost:44305',
redirectUri: baseUrl,
clientId: 'MyProjectName_App',
responseType: 'code',
dummyClientSecret: '1q2w3e*',
scope: 'offline_access MyProjectName',
// responseType: 'code',
// redirectUri: baseUrl
},
apis: {
default: {

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

@ -0,0 +1,3 @@
<h1> @abp/ng.account </h1>
[docs.abp.io](https://docs.abp.io)

7
npm/ng-packs/packages/account/config/ng-package.json

@ -0,0 +1,7 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/account/config",
"lib": {
"entryFile": "src/public-api.ts"
}
}

12
npm/ng-packs/packages/account/config/src/account-config.module.ts

@ -0,0 +1,12 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { ACCOUNT_ROUTE_PROVIDERS } from './providers/route.provider';
@NgModule()
export class AccountConfigModule {
static forRoot(): ModuleWithProviders<AccountConfigModule> {
return {
ngModule: AccountConfigModule,
providers: [ACCOUNT_ROUTE_PROVIDERS],
};
}
}

1
npm/ng-packs/packages/account/config/src/enums/index.ts

@ -0,0 +1 @@
export * from './route-names';

6
npm/ng-packs/packages/account/config/src/enums/route-names.ts

@ -0,0 +1,6 @@
export const enum eAccountRouteNames {
Account = 'AbpAccount::Menu:Account',
Login = 'AbpAccount::Login',
Register = 'AbpAccount::Register',
ManageProfile = 'AbpAccount::ManageYourProfile',
}

1
npm/ng-packs/packages/account/config/src/providers/index.ts

@ -0,0 +1 @@
export * from './route.provider';

39
npm/ng-packs/packages/account/config/src/providers/route.provider.ts

@ -0,0 +1,39 @@
import { eLayoutType, RoutesService } from '@abp/ng.core';
import { APP_INITIALIZER } from '@angular/core';
import { eAccountRouteNames } from '../enums/route-names';
export const ACCOUNT_ROUTE_PROVIDERS = [
{ provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true },
];
export function configureRoutes(routes: RoutesService) {
return () => {
routes.add([
{
path: '/account',
name: eAccountRouteNames.Account,
invisible: true,
layout: eLayoutType.application,
order: 1,
},
{
path: '/account/login',
name: eAccountRouteNames.Login,
parentName: eAccountRouteNames.Account,
order: 1,
},
{
path: '/account/register',
name: eAccountRouteNames.Register,
parentName: eAccountRouteNames.Account,
order: 2,
},
{
path: '/account/manage-profile',
name: eAccountRouteNames.ManageProfile,
parentName: eAccountRouteNames.Account,
order: 3,
},
]);
};
}

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

@ -0,0 +1,3 @@
export * from './account-config.module';
export * from './enums';
export * from './providers';

6
npm/ng-packs/packages/account/jest.config.js

@ -0,0 +1,6 @@
const jestConfig = require('../../jest.config');
module.exports = {
...jestConfig,
name: 'account',
};

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

@ -0,0 +1,8 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/account",
"lib": {
"entryFile": "src/public-api.ts"
},
"whitelistedNonPeerDependencies": ["@abp/ng.theme.shared"]
}

6
npm/ng-packs/packages/account/ngcc.config.js

@ -0,0 +1,6 @@
module.exports = {
entryPoints: {
'.': {},
'./config': {}
},
};

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

@ -0,0 +1,16 @@
{
"name": "@abp/ng.account",
"version": "4.3.0",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.theme.shared": "~3.3.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
}

93
npm/ng-packs/packages/account/src/lib/account-routing.module.ts

@ -0,0 +1,93 @@
import {
AuthGuard,
DynamicLayoutComponent,
ReplaceableComponents,
ReplaceableRouteContainerComponent,
} from '@abp/ng.core';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthWrapperComponent } from './components/auth-wrapper/auth-wrapper.component';
import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component';
import { LoginComponent } from './components/login/login.component';
import { ManageProfileComponent } from './components/manage-profile/manage-profile.component';
import { RegisterComponent } from './components/register/register.component';
import { ResetPasswordComponent } from './components/reset-password/reset-password.component';
import { eAccountComponents } from './enums/components';
import { AuthenticationFlowGuard } from './guards/authentication-flow.guard';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'login' },
{
path: '',
component: DynamicLayoutComponent,
children: [
{
path: '',
component: AuthWrapperComponent,
children: [
{
path: 'login',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.Login,
defaultComponent: LoginComponent,
} as ReplaceableComponents.RouteData<LoginComponent>,
},
},
{
path: 'register',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.Register,
defaultComponent: RegisterComponent,
} as ReplaceableComponents.RouteData<RegisterComponent>,
},
},
{
path: 'forgot-password',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.ForgotPassword,
defaultComponent: ForgotPasswordComponent,
} as ReplaceableComponents.RouteData<ForgotPasswordComponent>,
},
},
{
path: 'reset-password',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.ResetPassword,
defaultComponent: ResetPasswordComponent,
} as ReplaceableComponents.RouteData<ResetPasswordComponent>,
},
},
],
},
{
path: 'manage-profile',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthGuard],
data: {
replaceableComponent: {
key: eAccountComponents.ManageProfile,
defaultComponent: ManageProfileComponent,
} as ReplaceableComponents.RouteData<ManageProfileComponent>,
},
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class AccountRoutingModule {}

63
npm/ng-packs/packages/account/src/lib/account.module.ts

@ -0,0 +1,63 @@
import { CoreModule, LazyModuleFactory } from '@abp/ng.core';
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { ModuleWithProviders, NgModule, NgModuleFactory } from '@angular/core';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { NgxValidateCoreModule } from '@ngx-validate/core';
import { AccountRoutingModule } from './account-routing.module';
import { AuthWrapperComponent } from './components/auth-wrapper/auth-wrapper.component';
import { ChangePasswordComponent } from './components/change-password/change-password.component';
import { LoginComponent } from './components/login/login.component';
import { ManageProfileComponent } from './components/manage-profile/manage-profile.component';
import { PersonalSettingsComponent } from './components/personal-settings/personal-settings.component';
import { RegisterComponent } from './components/register/register.component';
import { TenantBoxComponent } from './components/tenant-box/tenant-box.component';
import { AccountConfigOptions } from './models/config-options';
import { ACCOUNT_CONFIG_OPTIONS } from './tokens/config-options.token';
import { accountConfigOptionsFactory } from './utils/factory-utils';
import { AuthenticationFlowGuard } from './guards/authentication-flow.guard';
import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './components/reset-password/reset-password.component';
const declarations = [
AuthWrapperComponent,
LoginComponent,
RegisterComponent,
TenantBoxComponent,
ChangePasswordComponent,
ManageProfileComponent,
PersonalSettingsComponent,
ForgotPasswordComponent,
ResetPasswordComponent,
];
@NgModule({
declarations: [...declarations],
imports: [
CoreModule,
AccountRoutingModule,
ThemeSharedModule,
NgbDropdownModule,
NgxValidateCoreModule,
],
exports: [...declarations],
})
export class AccountModule {
static forChild(options = {} as AccountConfigOptions): ModuleWithProviders<AccountModule> {
return {
ngModule: AccountModule,
providers: [
AuthenticationFlowGuard,
{ provide: ACCOUNT_CONFIG_OPTIONS, useValue: options },
{
provide: 'ACCOUNT_OPTIONS',
useFactory: accountConfigOptionsFactory,
deps: [ACCOUNT_CONFIG_OPTIONS],
},
],
};
}
static forLazy(options = {} as AccountConfigOptions): NgModuleFactory<AccountModule> {
return new LazyModuleFactory(AccountModule.forChild(options));
}
}

25
npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html

@ -0,0 +1,25 @@
<div class="row">
<div class="mx-auto col col-md-5">
<ng-container *ngIf="(isMultiTenancyEnabled$ | async) && multiTenancy.isTenantBoxVisible">
<abp-tenant-box *abpReplaceableTemplate="{ componentKey: tenantBoxKey }"></abp-tenant-box>
</ng-container>
<div class="abp-account-container">
<div
*ngIf="enableLocalLogin$ | async; else disableLocalLoginTemplate"
class="card mt-3 shadow-sm rounded"
>
<div class="card-body p-5">
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
</div>
<ng-template #disableLocalLoginTemplate>
<div class="alert alert-warning">
<strong>{{ 'AbpAccount::InvalidLoginRequest' | abpLocalization }}</strong>
{{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | abpLocalization }}
</div>
</ng-template>

28
npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts

@ -0,0 +1,28 @@
import { ConfigStateService, MultiTenancyService, SubscriptionService } from '@abp/ng.core';
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { eAccountComponents } from '../../enums/components';
@Component({
selector: 'abp-auth-wrapper',
templateUrl: './auth-wrapper.component.html',
exportAs: 'abpAuthWrapper',
providers: [SubscriptionService],
})
export class AuthWrapperComponent {
isMultiTenancyEnabled$ = this.configState.getDeep$('multiTenancy.isEnabled');
get enableLocalLogin$(): Observable<boolean> {
return this.configState
.getSetting$('Abp.Account.EnableLocalLogin')
.pipe(map(value => value?.toLowerCase() !== 'false'));
}
tenantBoxKey = eAccountComponents.TenantBox;
constructor(
public readonly multiTenancy: MultiTenancyService,
private configState: ConfigStateService,
) {}
}

48
npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html

@ -0,0 +1,48 @@
<form [formGroup]="form" (ngSubmit)="onSubmit()" [mapErrorsFn]="mapErrorsFn" validateOnSubmit>
<div *ngIf="!hideCurrentPassword" class="form-group">
<label for="current-password">{{
'AbpIdentity::DisplayName:CurrentPassword' | abpLocalization
}}</label
><span> * </span
><input
type="password"
id="current-password"
class="form-control"
formControlName="password"
autofocus
autocomplete="current-password"
/>
</div>
<div class="form-group">
<label for="new-password">{{ 'AbpIdentity::DisplayName:NewPassword' | abpLocalization }}</label
><span> * </span
><input
type="password"
id="new-password"
class="form-control"
formControlName="newPassword"
autocomplete="new-password"
/>
</div>
<div class="form-group">
<label for="confirm-new-password">{{
'AbpIdentity::DisplayName:NewPasswordConfirm' | abpLocalization
}}</label
><span> * </span
><input
type="password"
id="confirm-new-password"
class="form-control"
formControlName="repeatNewPassword"
autocomplete="new-password"
/>
</div>
<abp-button
iconClass="fa fa-check"
buttonClass="btn btn-primary color-white"
buttonType="submit"
[loading]="inProgress"
[disabled]="form?.invalid"
>{{ 'AbpIdentity::Save' | abpLocalization }}</abp-button
>
</form>

99
npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts

@ -0,0 +1,99 @@
import { Profile, ProfileService } from '@abp/ng.core';
import { getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
import { Component, Injector, Input, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { comparePasswords, Validation } from '@ngx-validate/core';
import { finalize } from 'rxjs/operators';
import snq from 'snq';
import { Account } from '../../models/account';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
const { required } = Validators;
const PASSWORD_FIELDS = ['newPassword', 'repeatNewPassword'];
@Component({
selector: 'abp-change-password-form',
templateUrl: './change-password.component.html',
exportAs: 'abpChangePasswordForm',
})
export class ChangePasswordComponent
implements OnInit, Account.ChangePasswordComponentInputs, Account.ChangePasswordComponentOutputs {
form: FormGroup;
inProgress: boolean;
hideCurrentPassword: boolean;
mapErrorsFn: Validation.MapErrorsFn = (errors, groupErrors, control) => {
if (PASSWORD_FIELDS.indexOf(String(control.name)) < 0) return errors;
return errors.concat(groupErrors.filter(({ key }) => key === 'passwordMismatch'));
};
constructor(
private fb: FormBuilder,
private injector: Injector,
private toasterService: ToasterService,
private profileService: ProfileService,
private manageProfileState: ManageProfileStateService,
) {}
ngOnInit(): void {
this.hideCurrentPassword = !this.manageProfileState.getProfile()?.hasPassword;
const passwordValidations = getPasswordValidators(this.injector);
this.form = this.fb.group(
{
password: ['', required],
newPassword: [
'',
{
validators: [required, ...passwordValidations],
},
],
repeatNewPassword: [
'',
{
validators: [required, ...passwordValidations],
},
],
},
{
validators: [comparePasswords(PASSWORD_FIELDS)],
},
);
if (this.hideCurrentPassword) this.form.removeControl('password');
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
this.profileService
.changePassword({
...(!this.hideCurrentPassword && { currentPassword: this.form.get('password').value }),
newPassword: this.form.get('newPassword').value,
})
.pipe(finalize(() => (this.inProgress = false)))
.subscribe({
next: () => {
this.form.reset();
this.toasterService.success('AbpAccount::PasswordChangedMessage', '', {
life: 5000,
});
if (this.hideCurrentPassword) {
this.hideCurrentPassword = false;
this.form.addControl('password', new FormControl('', [required]));
}
},
error: err => {
this.toasterService.error(
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
);
},
});
}
}

40
npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.html

@ -0,0 +1,40 @@
<h4>{{ 'AbpAccount::ForgotPassword' | abpLocalization }}</h4>
<form
*ngIf="!isEmailSent; else emailSentTemplate"
[formGroup]="form"
(ngSubmit)="onSubmit()"
validateOnSubmit
>
<p>{{ 'AbpAccount::SendPasswordResetLink_Information' | abpLocalization }}</p>
<div class="form-group">
<label for="input-email-address">{{ 'AbpAccount::EmailAddress' | abpLocalization }}</label
><span> * </span>
<input type="email" id="input-email-address" class="form-control" formControlName="email" />
</div>
<abp-button
class="d-block"
buttonClass="mt-2 mb-3 btn btn-primary btn-block"
[loading]="inProgress"
buttonType="submit"
[disabled]="form?.invalid"
>
{{ 'AbpAccount::Submit' | abpLocalization }}
</abp-button>
<a routerLink="/account/login"
><i class="fa fa-long-arrow-left mr-1"></i>{{ 'AbpAccount::Login' | abpLocalization }}</a
>
</form>
<ng-template #emailSentTemplate>
<p>
{{ 'AbpAccount::PasswordResetMailSentMessage' | abpLocalization }}
</p>
<a routerLink="/account/login">
<button class="d-block mt-2 mb-3 btn btn-primary btn-block">
<i class="fa fa-long-arrow-left mr-1"></i>
{{ 'AbpAccount::BackToLogin' | abpLocalization }}
</button>
</a>
</ng-template>

35
npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts

@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { AccountService } from '../../proxy/account/account.service';
@Component({
selector: 'abp-forgot-password',
templateUrl: 'forgot-password.component.html',
})
export class ForgotPasswordComponent {
form: FormGroup;
inProgress: boolean;
isEmailSent = false;
constructor(private fb: FormBuilder, private accountService: AccountService) {
this.form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
});
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
this.accountService
.sendPasswordResetCode({ email: this.form.get('email').value, appName: 'Angular' })
.pipe(finalize(() => (this.inProgress = false)))
.subscribe(() => {
this.isEmailSent = true;
});
}
}

8
npm/ng-packs/packages/account/src/lib/components/index.ts

@ -0,0 +1,8 @@
export * from './change-password/change-password.component';
export * from './forgot-password/forgot-password.component';
export * from './login/login.component';
export * from './manage-profile/manage-profile.component';
export * from './register/register.component';
export * from './personal-settings/personal-settings.component';
export * from './reset-password/reset-password.component';
export * from './tenant-box/tenant-box.component';

60
npm/ng-packs/packages/account/src/lib/components/login/login.component.html

@ -0,0 +1,60 @@
<h4>{{ 'AbpAccount::Login' | abpLocalization }}</h4>
<strong *ngIf="isSelfRegistrationEnabled">
{{ 'AbpAccount::AreYouANewUser' | abpLocalization }}
<a class="text-decoration-none" routerLink="/account/register" queryParamsHandling="preserve">{{
'AbpAccount::Register' | abpLocalization
}}</a>
</strong>
<form [formGroup]="form" (ngSubmit)="onSubmit()" validateOnSubmit class="mt-4">
<div class="form-group">
<label for="login-input-user-name-or-email-address">{{
'AbpAccount::UserNameOrEmailAddress' | abpLocalization
}}</label>
<input
class="form-control"
type="text"
id="login-input-user-name-or-email-address"
formControlName="username"
autocomplete="username"
autofocus
/>
</div>
<div class="form-group">
<label for="login-input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label>
<input
class="form-control"
type="password"
id="login-input-password"
formControlName="password"
autocomplete="current-password"
/>
</div>
<div class="row">
<div class="col">
<label class="custom-checkbox custom-control mb-2" for="login-input-remember-me">
<input
class="form-check-input"
type="checkbox"
id="login-input-remember-me"
formControlName="rememberMe"
/>
{{ 'AbpAccount::RememberMe' | abpLocalization }}
</label>
</div>
<div class="text-right col">
<a routerLink="/account/forgot-password">{{
'AbpAccount::ForgotPassword' | abpLocalization
}}</a>
</div>
</div>
<abp-button
[loading]="inProgress"
buttonType="submit"
name="Action"
buttonClass="btn-block btn-lg mt-3 btn btn-primary"
>
{{ 'AbpAccount::Login' | abpLocalization }}
</abp-button>
</form>

80
npm/ng-packs/packages/account/src/lib/components/login/login.component.ts

@ -0,0 +1,80 @@
import { ConfigStateService, AuthService } from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngxs/store';
import { throwError } from 'rxjs';
import { catchError, finalize } from 'rxjs/operators';
import snq from 'snq';
import { eAccountComponents } from '../../enums/components';
import { getRedirectUrl } from '../../utils/auth-utils';
const { maxLength, required } = Validators;
@Component({
selector: 'abp-login',
templateUrl: './login.component.html',
})
export class LoginComponent implements OnInit {
form: FormGroup;
inProgress: boolean;
isSelfRegistrationEnabled = true;
authWrapperKey = eAccountComponents.AuthWrapper;
constructor(
protected injector: Injector,
protected fb: FormBuilder,
protected toasterService: ToasterService,
protected authService: AuthService,
protected configState: ConfigStateService,
) {}
ngOnInit() {
this.init();
this.buildForm();
}
protected init() {
this.isSelfRegistrationEnabled =
(
(this.configState.getSetting('Abp.Account.IsSelfRegistrationEnabled') as string) || ''
).toLowerCase() !== 'false';
}
protected buildForm() {
this.form = this.fb.group({
username: ['', [required, maxLength(255)]],
password: ['', [required, maxLength(128)]],
rememberMe: [false],
});
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
const { username, password, rememberMe } = this.form.value;
const redirectUrl = getRedirectUrl(this.injector);
this.authService
.login({ username, password, rememberMe, redirectUrl })
.pipe(
catchError(err => {
this.toasterService.error(
snq(() => err.error.error_description) ||
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{ life: 7000 },
);
return throwError(err);
}),
finalize(() => (this.inProgress = false)),
)
.subscribe();
}
}

62
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html

@ -0,0 +1,62 @@
<div id="AbpContentToolbar"></div>
<div class="card border-0 shadow-sm min-h-400" [abpLoading]="!(profile$ | async)">
<div class="card-body">
<div class="row">
<div class="col-12 col-md-3">
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist">
<li
*ngIf="!hideChangePasswordTab && (profile$ | async)"
class="nav-item"
(click)="selectedTab = 0"
>
<a
class="nav-link"
[ngClass]="{ active: selectedTab === 0 }"
role="tab"
href="javascript:void(0)"
>{{ 'AbpUi::ChangePassword' | abpLocalization }}</a
>
</li>
<li class="nav-item mb-2" (click)="selectedTab = 1">
<a
class="nav-link"
[ngClass]="{ active: selectedTab === 1 }"
role="tab"
href="javascript:void(0)"
>{{ 'AbpAccount::PersonalSettings' | abpLocalization }}</a
>
</li>
</ul>
</div>
<div *ngIf="profile$ | async" class="col-12 col-md-9">
<div class="tab-content" *ngIf="selectedTab === 0" [@fadeIn]>
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::ChangePassword' | abpLocalization }}
<hr />
</h4>
<abp-change-password-form
*abpReplaceableTemplate="{
componentKey: changePasswordKey
}"
></abp-change-password-form>
</div>
</div>
<div class="tab-content" *ngIf="selectedTab === 1" [@fadeIn]>
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::PersonalSettings' | abpLocalization }}
<hr />
</h4>
<abp-personal-settings-form
*abpReplaceableTemplate="{
componentKey: personalSettingsKey
}"
></abp-personal-settings-form>
</div>
</div>
</div>
</div>
</div>
</div>

45
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts

@ -0,0 +1,45 @@
import { Profile, ProfileService } from '@abp/ng.core';
import { fadeIn } from '@abp/ng.theme.shared';
import { transition, trigger, useAnimation } from '@angular/animations';
import { Component, OnInit } from '@angular/core';
import { eAccountComponents } from '../../enums/components';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
@Component({
selector: 'abp-manage-profile',
templateUrl: './manage-profile.component.html',
animations: [trigger('fadeIn', [transition(':enter', useAnimation(fadeIn))])],
styles: [
`
.min-h-400 {
min-height: 400px;
}
`,
],
})
export class ManageProfileComponent implements OnInit {
selectedTab = 0;
changePasswordKey = eAccountComponents.ChangePassword;
personalSettingsKey = eAccountComponents.PersonalSettings;
profile$ = this.manageProfileState.getProfile$();
hideChangePasswordTab: boolean;
constructor(
protected profileService: ProfileService,
protected manageProfileState: ManageProfileStateService,
) {}
ngOnInit() {
this.profileService.get().subscribe(profile => {
this.manageProfileState.setProfile(profile);
if (profile.isExternal) {
this.hideChangePasswordTab = true;
this.selectedTab = 1;
}
});
}
}

46
npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.html

@ -0,0 +1,46 @@
<form validateOnSubmit *ngIf="form" [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group">
<label for="username">{{ 'AbpIdentity::DisplayName:UserName' | abpLocalization }}</label
><span> * </span
><input
type="text"
id="username"
class="form-control"
formControlName="userName"
autofocus
(keydown.space)="$event.preventDefault()"
/>
</div>
<div class="row">
<div class="col col-md-6">
<div class="form-group">
<label for="name">{{ 'AbpIdentity::DisplayName:Name' | abpLocalization }}</label
><input type="text" id="name" class="form-control" formControlName="name" />
</div>
</div>
<div class="col col-md-6">
<div class="form-group">
<label for="surname">{{ 'AbpIdentity::DisplayName:Surname' | abpLocalization }}</label
><input type="text" id="surname" class="form-control" formControlName="surname" />
</div>
</div>
</div>
<div class="form-group">
<label for="email-address">{{ 'AbpIdentity::DisplayName:Email' | abpLocalization }}</label
><span> * </span
><input type="text" id="email-address" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label for="phone-number">{{ 'AbpIdentity::DisplayName:PhoneNumber' | abpLocalization }}</label
><input type="text" id="phone-number" class="form-control" formControlName="phoneNumber" />
</div>
<abp-button
buttonType="submit"
iconClass="fa fa-check"
buttonClass="btn btn-primary color-white"
[loading]="inProgress"
[disabled]="form?.invalid"
>
{{ 'AbpIdentity::Save' | abpLocalization }}</abp-button
>
</form>

58
npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts

@ -0,0 +1,58 @@
import { ProfileService } from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { Account } from '../../models/account';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
const { maxLength, required, email } = Validators;
@Component({
selector: 'abp-personal-settings-form',
templateUrl: './personal-settings.component.html',
exportAs: 'abpPersonalSettingsForm',
})
export class PersonalSettingsComponent
implements
OnInit,
Account.PersonalSettingsComponentInputs,
Account.PersonalSettingsComponentOutputs {
form: FormGroup;
inProgress: boolean;
constructor(
private fb: FormBuilder,
private toasterService: ToasterService,
private profileService: ProfileService,
private manageProfileState: ManageProfileStateService,
) {}
ngOnInit() {
this.buildForm();
}
buildForm() {
const profile = this.manageProfileState.getProfile();
this.form = this.fb.group({
userName: [profile.userName, [required, maxLength(256)]],
email: [profile.email, [required, email, maxLength(256)]],
name: [profile.name || '', [maxLength(64)]],
surname: [profile.surname || '', [maxLength(64)]],
phoneNumber: [profile.phoneNumber || '', [maxLength(16)]],
});
}
submit() {
if (this.form.invalid) return;
this.inProgress = true;
this.profileService
.update(this.form.value)
.pipe(finalize(() => (this.inProgress = false)))
.subscribe(profile => {
this.manageProfileState.setProfile(profile);
this.toasterService.success('AbpAccount::PersonalSettingsSaved', 'Success', { life: 5000 });
});
}
}

51
npm/ng-packs/packages/account/src/lib/components/register/register.component.html

@ -0,0 +1,51 @@
<h4>{{ 'AbpAccount::Register' | abpLocalization }}</h4>
<strong>
{{ 'AbpAccount::AlreadyRegistered' | abpLocalization }}
<a class="text-decoration-none" routerLink="/account/login">{{
'AbpAccount::Login' | abpLocalization
}}</a>
</strong>
<form
*ngIf="isSelfRegistrationEnabled"
[formGroup]="form"
(ngSubmit)="onSubmit()"
validateOnSubmit
class="mt-4"
>
<div class="form-group">
<label for="input-user-name">{{ 'AbpAccount::UserName' | abpLocalization }}</label
><span> * </span
><input
autofocus
type="text"
id="input-user-name"
class="form-control"
formControlName="username"
autocomplete="username"
/>
</div>
<div class="form-group">
<label for="input-email-address">{{ 'AbpAccount::EmailAddress' | abpLocalization }}</label
><span> * </span
><input type="email" id="input-email-address" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label for="input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label
><span> * </span
><input
type="password"
id="input-password"
class="form-control"
formControlName="password"
autocomplete="current-password"
/>
</div>
<abp-button
[loading]="inProgress"
buttonType="submit"
name="Action"
buttonClass="btn-block btn-lg mt-3 btn btn-primary"
>
{{ 'AbpAccount::Register' | abpLocalization }}
</abp-button>
</form>

102
npm/ng-packs/packages/account/src/lib/components/register/register.component.ts

@ -0,0 +1,102 @@
import { AuthService, ConfigStateService } from '@abp/ng.core';
import { getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
import { Component, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { throwError } from 'rxjs';
import { catchError, finalize, switchMap } from 'rxjs/operators';
import snq from 'snq';
import { eAccountComponents } from '../../enums/components';
import { AccountService } from '../../proxy/account/account.service';
import { RegisterDto } from '../../proxy/account/models';
import { getRedirectUrl } from '../../utils/auth-utils';
const { maxLength, required, email } = Validators;
@Component({
selector: 'abp-register',
templateUrl: './register.component.html',
})
export class RegisterComponent implements OnInit {
form: FormGroup;
inProgress: boolean;
isSelfRegistrationEnabled = true;
authWrapperKey = eAccountComponents.AuthWrapper;
constructor(
protected fb: FormBuilder,
protected accountService: AccountService,
protected configState: ConfigStateService,
protected toasterService: ToasterService,
protected authService: AuthService,
protected injector: Injector,
) {}
ngOnInit() {
this.init();
this.buildForm();
}
protected init() {
this.isSelfRegistrationEnabled =
(this.configState.getSetting('Abp.Account.IsSelfRegistrationEnabled') || '').toLowerCase() !==
'false';
if (!this.isSelfRegistrationEnabled) {
this.toasterService.warn(
{
key: 'AbpAccount::SelfRegistrationDisabledMessage',
defaultValue: 'Self registration is disabled.',
},
null,
{ life: 10000 },
);
return;
}
}
protected buildForm() {
this.form = this.fb.group({
username: ['', [required, maxLength(255)]],
password: ['', [required, ...getPasswordValidators(this.injector)]],
email: ['', [required, email]],
});
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
const newUser = {
userName: this.form.get('username').value,
password: this.form.get('password').value,
emailAddress: this.form.get('email').value,
appName: 'Angular',
} as RegisterDto;
this.accountService
.register(newUser)
.pipe(
switchMap(() =>
this.authService.login({
username: newUser.userName,
password: newUser.password,
redirectUrl: getRedirectUrl(this.injector),
}),
),
catchError(err => {
this.toasterService.error(
snq(() => err.error.error_description) ||
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{ life: 7000 },
);
return throwError(err);
}),
finalize(() => (this.inProgress = false)),
)
.subscribe();
}
}

49
npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.html

@ -0,0 +1,49 @@
<h4>{{ 'AbpAccount::ResetPassword' | abpLocalization }}</h4>
<form
*ngIf="!isPasswordReset; else passwordResetTemplate"
[formGroup]="form"
[mapErrorsFn]="mapErrorsFn"
(ngSubmit)="onSubmit()"
validateOnSubmit
>
<p>{{ 'AbpAccount::ResetPassword_Information' | abpLocalization }}</p>
<div class="form-group">
<label for="input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label
><span> * </span>
<input type="password" id="input-password" class="form-control" formControlName="password" />
</div>
<div class="form-group">
<label for="input-confirm-password">{{ 'AbpAccount::ConfirmPassword' | abpLocalization }}</label
><span> * </span>
<input
type="password"
id="input-confirm-password"
class="form-control"
formControlName="confirmPassword"
/>
</div>
<button class="mr-2 btn btn-secondary" type="button" routerLink="/account/login">
{{ 'AbpAccount::Cancel' | abpLocalization }}
</button>
<abp-button
buttonType="submit"
buttonClass="mr-2 btn btn-primary"
[loading]="inProgress"
(click)="onSubmit()"
>
{{ 'AbpAccount::Submit' | abpLocalization }}
</abp-button>
</form>
<ng-template #passwordResetTemplate>
<p>
{{ 'AbpAccount::YourPasswordIsSuccessfullyReset' | abpLocalization }}
</p>
<a routerLink="/account/login">
<button class="d-block mt-2 mb-3 btn btn-primary">
{{ 'AbpAccount::BackToLogin' | abpLocalization }}
</button>
</a>
</ng-template>

70
npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts

@ -0,0 +1,70 @@
import { getPasswordValidators } from '@abp/ng.theme.shared';
import { Component, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { comparePasswords, Validation } from '@ngx-validate/core';
import { finalize } from 'rxjs/operators';
import { AccountService } from '../../proxy/account/account.service';
const PASSWORD_FIELDS = ['password', 'confirmPassword'];
@Component({
selector: 'abp-reset-password',
templateUrl: './reset-password.component.html',
})
export class ResetPasswordComponent implements OnInit {
form: FormGroup;
inProgress = false;
isPasswordReset = false;
mapErrorsFn: Validation.MapErrorsFn = (errors, groupErrors, control) => {
if (PASSWORD_FIELDS.indexOf(String(control.name)) < 0) return errors;
return errors.concat(groupErrors.filter(({ key }) => key === 'passwordMismatch'));
};
constructor(
private fb: FormBuilder,
private accountService: AccountService,
private route: ActivatedRoute,
private router: Router,
private injector: Injector,
) {}
ngOnInit(): void {
this.route.queryParams.subscribe(({ userId, resetToken }) => {
if (!userId || !resetToken) this.router.navigateByUrl('/account/login');
this.form = this.fb.group(
{
userId: [userId, [Validators.required]],
resetToken: [resetToken, [Validators.required]],
password: ['', [Validators.required, ...getPasswordValidators(this.injector)]],
confirmPassword: ['', [Validators.required, ...getPasswordValidators(this.injector)]],
},
{
validators: [comparePasswords(PASSWORD_FIELDS)],
},
);
});
}
onSubmit() {
if (this.form.invalid || this.inProgress) return;
this.inProgress = true;
this.accountService
.resetPassword({
userId: this.form.get('userId').value,
resetToken: this.form.get('resetToken').value,
password: this.form.get('password').value,
})
.pipe(finalize(() => (this.inProgress = false)))
.subscribe(() => {
this.isPasswordReset = true;
});
}
}

63
npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html

@ -0,0 +1,63 @@
<ng-container *ngIf="(currentTenant$ | async) || {} as currentTenant">
<div class="card shadow-sm rounded mb-3">
<div class="card-body px-5">
<div class="row">
<div class="col">
<span style="font-size: 0.8em;" class="text-uppercase text-muted">{{
'AbpUiMultiTenancy::Tenant' | abpLocalization
}}</span
><br />
<h6 class="m-0 d-inline-block">
<i>{{ currentTenant.name || ('AbpUiMultiTenancy::NotSelected' | abpLocalization) }}</i>
</h6>
</div>
<div class="col-auto">
<a
id="AbpTenantSwitchLink"
href="javascript:void(0);"
class="btn btn-sm mt-3 btn-outline-primary"
(click)="onSwitch()"
>{{ 'AbpUiMultiTenancy::Switch' | abpLocalization }}</a
>
</div>
</div>
</div>
</div>
<abp-modal size="md" [(visible)]="isModalVisible" [busy]="modalBusy">
<ng-template #abpHeader>
<h5>Switch Tenant</h5>
</ng-template>
<ng-template #abpBody>
<form (ngSubmit)="save()">
<div class="mt-2">
<div class="form-group">
<label for="name">{{ 'AbpUiMultiTenancy::Name' | abpLocalization }}</label>
<input
[(ngModel)]="name"
type="text"
id="name"
name="tenant"
class="form-control"
autofocus
/>
</div>
<p>{{ 'AbpUiMultiTenancy::SwitchTenantHint' | abpLocalization }}</p>
</div>
</form>
</ng-template>
<ng-template #abpFooter>
<button #abpClose type="button" class="btn btn-secondary">
{{ 'AbpTenantManagement::Cancel' | abpLocalization }}
</button>
<abp-button
type="abp-button"
iconClass="fa fa-check"
(click)="save()"
[disabled]="currentTenant?.name === name"
>
<span>{{ 'AbpTenantManagement::Save' | abpLocalization }}</span>
</abp-button>
</ng-template>
</abp-modal>
</ng-container>

73
npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts

@ -0,0 +1,73 @@
import {
AbpApplicationConfigurationService,
AbpTenantService,
ConfigStateService,
CurrentTenantDto,
SessionStateService,
} from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component } from '@angular/core';
import { finalize } from 'rxjs/operators';
import { Account } from '../../models/account';
@Component({
selector: 'abp-tenant-box',
templateUrl: './tenant-box.component.html',
})
export class TenantBoxComponent
implements Account.TenantBoxComponentInputs, Account.TenantBoxComponentOutputs {
currentTenant$ = this.sessionState.getTenant$();
name: string;
isModalVisible: boolean;
modalBusy: boolean;
constructor(
private toasterService: ToasterService,
private tenantService: AbpTenantService,
private sessionState: SessionStateService,
private configState: ConfigStateService,
private appConfigService: AbpApplicationConfigurationService,
) {}
onSwitch() {
const tenant = this.sessionState.getTenant();
this.name = tenant?.name;
this.isModalVisible = true;
}
save() {
if (!this.name) {
this.setTenant(null);
this.isModalVisible = false;
return;
}
this.modalBusy = true;
this.tenantService
.findTenantByName(this.name, {})
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(({ success, tenantId: id, ...tenant }) => {
if (!success) {
this.showError();
return;
}
this.setTenant({ ...tenant, id, isAvailable: true });
this.isModalVisible = false;
});
}
private setTenant(tenant: CurrentTenantDto) {
this.sessionState.setTenant(tenant);
this.appConfigService.get().subscribe(res => this.configState.setState(res));
}
private showError() {
this.toasterService.error('AbpUiMultiTenancy::GivenTenantIsNotAvailable', 'AbpUi::Error', {
messageLocalizationParams: [this.name],
});
}
}

11
npm/ng-packs/packages/account/src/lib/enums/components.ts

@ -0,0 +1,11 @@
export const enum eAccountComponents {
Login = 'Account.LoginComponent',
Register = 'Account.RegisterComponent',
ForgotPassword = 'Account.ForgotPasswordComponent',
ResetPassword = 'Account.ResetPasswordComponent',
ManageProfile = 'Account.ManageProfileComponent',
TenantBox = 'Account.TenantBoxComponent',
AuthWrapper = 'Account.AuthWrapperComponent',
ChangePassword = 'Account.ChangePasswordComponent',
PersonalSettings = 'Account.PersonalSettingsComponent',
}

1
npm/ng-packs/packages/account/src/lib/enums/index.ts

@ -0,0 +1 @@
export * from './components';

15
npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts

@ -0,0 +1,15 @@
import { AuthService } from '@abp/ng.core';
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
@Injectable()
export class AuthenticationFlowGuard implements CanActivate {
constructor(private authService: AuthService) {}
canActivate() {
if (this.authService.isInternalAuth) return true;
this.authService.navigateToLogin();
return false;
}
}

1
npm/ng-packs/packages/account/src/lib/guards/index.ts

@ -0,0 +1 @@
export * from './authentication-flow.guard';

12
npm/ng-packs/packages/account/src/lib/models/account.ts

@ -0,0 +1,12 @@
import { TemplateRef } from '@angular/core';
export namespace Account {
//tslint:disable
export interface TenantBoxComponentInputs {}
export interface TenantBoxComponentOutputs {}
export interface PersonalSettingsComponentInputs {}
export interface PersonalSettingsComponentOutputs {}
export interface ChangePasswordComponentInputs {}
export interface ChangePasswordComponentOutputs {}
// tslint:enable
}

3
npm/ng-packs/packages/account/src/lib/models/config-options.ts

@ -0,0 +1,3 @@
export interface AccountConfigOptions {
redirectUrl?: string;
}

2
npm/ng-packs/packages/account/src/lib/models/index.ts

@ -0,0 +1,2 @@
export * from './account';
export * from './config-options';

17
npm/ng-packs/packages/account/src/lib/proxy/README.md

@ -0,0 +1,17 @@
# Proxy Generation Output
This directory includes the output of the latest proxy generation.
The files and folders in it will be overwritten when proxy generation is run again.
Therefore, please do not place your own content in this folder.
In addition, `generate-proxy.json` works like a lock file.
It includes information used by the proxy generator, so please do not delete or modify it.
Finally, the name of the files and folders should not be changed for two reasons:
- Proxy generator will keep creating them at those paths and you will have multiple copies of the same content.
- ABP Suite generates files which include imports from this folder.
> **Important Notice:** If you are building a module and are planning to publish to npm,
> some of the generated proxies are likely to be exported from public-api.ts file. In such a case,
> please make sure you export files directly and not from barrel exports. In other words,
> do not include index.ts exports in your public-api.ts exports.

37
npm/ng-packs/packages/account/src/lib/proxy/account/account.service.ts

@ -0,0 +1,37 @@
import type { RegisterDto, ResetPasswordDto, SendPasswordResetCodeDto } from './models';
import { RestService } from '@abp/ng.core';
import { Injectable } from '@angular/core';
import type { IdentityUserDto } from '../identity/models';
@Injectable({
providedIn: 'root',
})
export class AccountService {
apiName = 'AbpAccount';
register = (input: RegisterDto) =>
this.restService.request<any, IdentityUserDto>({
method: 'POST',
url: '/api/account/register',
body: input,
},
{ apiName: this.apiName });
resetPassword = (input: ResetPasswordDto) =>
this.restService.request<any, void>({
method: 'POST',
url: '/api/account/reset-password',
body: input,
},
{ apiName: this.apiName });
sendPasswordResetCode = (input: SendPasswordResetCodeDto) =>
this.restService.request<any, void>({
method: 'POST',
url: '/api/account/send-password-reset-code',
body: input,
},
{ apiName: this.apiName });
constructor(private restService: RestService) {}
}

2
npm/ng-packs/packages/account/src/lib/proxy/account/index.ts

@ -0,0 +1,2 @@
export * from './account.service';
export * from './models';

20
npm/ng-packs/packages/account/src/lib/proxy/account/models.ts

@ -0,0 +1,20 @@
export interface RegisterDto {
userName: string;
emailAddress: string;
password: string;
appName: string;
}
export interface ResetPasswordDto {
userId?: string;
resetToken: string;
password: string;
}
export interface SendPasswordResetCodeDto {
email: string;
appName: string;
returnUrl?: string;
returnUrlHash?: string;
}

4745
npm/ng-packs/packages/account/src/lib/proxy/generate-proxy.json

File diff suppressed because it is too large

1
npm/ng-packs/packages/account/src/lib/proxy/identity/index.ts

@ -0,0 +1 @@
export * from './models';

15
npm/ng-packs/packages/account/src/lib/proxy/identity/models.ts

@ -0,0 +1,15 @@
import type { ExtensibleFullAuditedEntityDto } from '@abp/ng.core';
export interface IdentityUserDto extends ExtensibleFullAuditedEntityDto<string> {
tenantId?: string;
userName?: string;
name?: string;
surname?: string;
email?: string;
emailConfirmed: boolean;
phoneNumber?: string;
phoneNumberConfirmed: boolean;
lockoutEnabled: boolean;
lockoutEnd?: string;
concurrencyStamp?: string;
}

3
npm/ng-packs/packages/account/src/lib/proxy/index.ts

@ -0,0 +1,3 @@
import * as Account from './account';
import * as Identity from './identity';
export { Account, Identity };

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

@ -0,0 +1 @@
export * from './manage-profile.state.service';

28
npm/ng-packs/packages/account/src/lib/services/manage-profile.state.service.ts

@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
import { InternalStore, Profile } from '@abp/ng.core';
import { Observable } from 'rxjs';
export interface ManageProfileState {
profile: Profile.Response;
}
@Injectable({ providedIn: 'root' })
export class ManageProfileStateService {
private readonly store = new InternalStore({} as ManageProfileState);
get createOnUpdateStream() {
return this.store.sliceUpdate;
}
getProfile$(): Observable<Profile.Response> {
return this.store.sliceState(state => state.profile);
}
getProfile(): Profile.Response {
return this.store.state.profile;
}
setProfile(profile: Profile.Response) {
this.store.patch({ profile });
}
}

6
npm/ng-packs/packages/account/src/lib/tokens/config-options.token.ts

@ -0,0 +1,6 @@
import { InjectionToken } from '@angular/core';
import { AccountConfigOptions } from '../models/config-options';
export const ACCOUNT_CONFIG_OPTIONS = new InjectionToken<AccountConfigOptions>(
'ACCOUNT_CONFIG_OPTIONS',
);

1
npm/ng-packs/packages/account/src/lib/tokens/index.ts

@ -0,0 +1 @@
export * from './config-options.token';

9
npm/ng-packs/packages/account/src/lib/utils/auth-utils.ts

@ -0,0 +1,9 @@
import { Injector } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ACCOUNT_CONFIG_OPTIONS } from '../tokens';
export function getRedirectUrl(injector: Injector) {
const route = injector.get(ActivatedRoute);
const options = injector.get(ACCOUNT_CONFIG_OPTIONS);
return route.snapshot.queryParams.returnUrl || options.redirectUrl || '/';
}

8
npm/ng-packs/packages/account/src/lib/utils/factory-utils.ts

@ -0,0 +1,8 @@
import { AccountConfigOptions } from '../models/config-options';
export function accountConfigOptionsFactory(options: AccountConfigOptions) {
return {
redirectUrl: '/',
...options,
};
}

2
npm/ng-packs/packages/account/src/lib/utils/index.ts

@ -0,0 +1,2 @@
export * from './auth-utils';
export * from './factory-utils';

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

@ -0,0 +1,9 @@
export * from './lib/account.module';
export * from './lib/components';
export * from './lib/enums';
export * from './lib/guards';
export * from './lib/models';
export * from './lib/services';
export * from './lib/tokens';
export * from './lib/proxy/account';
export * from './lib/proxy/identity';

19
npm/ng-packs/packages/account/tsconfig.lib.json

@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.prod.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"inlineSources": true,
"types": [],
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"enableResourceInlining": true
},
"exclude": ["src/test.ts", "**/*.spec.ts"]
}

6
npm/ng-packs/packages/account/tsconfig.lib.prod.json

@ -0,0 +1,6 @@
{
"extends": "./tsconfig.lib.json",
"angularCompilerOptions": {
"enableIvy": false
}
}

11
npm/ng-packs/packages/account/tsconfig.spec.json

@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.prod.json",
"compilerOptions": {
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["**/*.spec.ts", "**/*.d.ts"]
}

17
npm/ng-packs/packages/account/tslint.json

@ -0,0 +1,17 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"abp",
"camelCase"
],
"component-selector": [
true,
"element",
"abp",
"kebab-case"
]
}
}

4
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS, HttpClientModule, HttpClientXsrfModule } from '@angular/common/http';
import { HttpClientModule, HttpClientXsrfModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
@ -29,7 +29,7 @@ import { LocaleProvider } from './providers/locale.provider';
import { LocalizationService } from './services/localization.service';
import { ProfileState } from './states/profile.state';
import { oAuthStorage } from './strategies/auth-flow.strategy';
import { CORE_OPTIONS, coreOptionsFactory } from './tokens/options.token';
import { coreOptionsFactory, CORE_OPTIONS } from './tokens/options.token';
import { noop } from './utils/common-utils';
import './utils/date-extensions';
import { getInitialData, localeInitializer } from './utils/initial-utils';

2
npm/ng-packs/packages/core/src/lib/guards/auth.guard.ts

@ -16,7 +16,7 @@ export class AuthGuard implements CanActivate {
return true;
}
this.authService.initLogin();
this.authService.navigateToLogin();
return false;
}
}

8
npm/ng-packs/packages/core/src/lib/models/session.ts

@ -4,9 +4,17 @@ export namespace Session {
export interface State {
language: string;
tenant: CurrentTenantDto;
/**
*
* @deprecated To be deleted in v5.0
*/
sessionDetail: SessionDetail;
}
/**
*
* @deprecated To be deleted in v5.0
*/
export interface SessionDetail {
openedTabCount: number;
lastExitTime: number;

60
npm/ng-packs/packages/core/src/lib/services/auth.service.ts

@ -1,47 +1,61 @@
import { Injectable, Injector } from '@angular/core';
import { Observable } from 'rxjs';
import { AuthFlowStrategy, AUTH_FLOW_STRATEGY } from '../strategies/auth-flow.strategy';
import { from, Observable } from 'rxjs';
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
import {
AuthFlowStrategy,
AUTH_FLOW_STRATEGY,
LoginParams,
} from '../strategies/auth-flow.strategy';
import { EnvironmentService } from './environment.service';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private flow: string;
private strategy: AuthFlowStrategy;
get isInternalAuth() {
return this.strategy.isInternalAuth;
}
constructor(private environment: EnvironmentService, private injector: Injector) {
this.setStrategy();
this.listenToSetEnvironment();
}
private setStrategy = () => {
const flow = this.environment.getEnvironment().oAuthConfig.responseType || 'password';
if (this.flow === flow) return;
if (this.strategy) this.strategy.destroy();
this.flow = flow;
this.strategy = AUTH_FLOW_STRATEGY.Code(this.injector);
};
private listenToSetEnvironment() {
this.environment.createOnUpdateStream(state => state.oAuthConfig).subscribe(this.setStrategy);
}
constructor(protected injector: Injector) {}
async init() {
return await this.strategy.init();
const environmentService = this.injector.get(EnvironmentService);
return environmentService
.getEnvironment$()
.pipe(
map(env => env?.oAuthConfig),
filter(oAuthConfig => !!oAuthConfig),
tap(oAuthConfig => {
this.strategy =
oAuthConfig.responseType === 'code'
? AUTH_FLOW_STRATEGY.Code(this.injector)
: AUTH_FLOW_STRATEGY.Password(this.injector);
}),
switchMap(() => from(this.strategy.init())),
take(1),
)
.toPromise();
}
logout(): Observable<any> {
return this.strategy.logout();
}
/**
* @deprecated Use navigateToLogin method instead. To be deleted in v5.0
*/
initLogin() {
this.strategy.login();
this.strategy.navigateToLogin();
}
navigateToLogin() {
this.strategy.navigateToLogin();
}
login(params: LoginParams) {
return this.strategy.login(params);
}
}

6
npm/ng-packs/packages/core/src/lib/services/session-state.service.ts

@ -6,12 +6,6 @@ import { CurrentTenantDto } from '../proxy/volo/abp/asp-net-core/mvc/multi-tenan
import { InternalStore } from '../utils/internal-store-utils';
import { ConfigStateService } from './config-state.service';
export interface SessionDetail {
openedTabCount: number;
lastExitTime: number;
remember: boolean;
}
@Injectable({
providedIn: 'root',
})

148
npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts

@ -1,11 +1,23 @@
import { HttpHeaders } from '@angular/common/http';
import { Injector } from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngxs/store';
import { AuthConfig, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
import { Observable, of } from 'rxjs';
import { AuthConfig, OAuthInfoEvent, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
import { from, Observable, of } from 'rxjs';
import { filter, switchMap, tap } from 'rxjs/operators';
import { RestOccurError } from '../actions/rest.actions';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { SessionStateService } from '../services/session-state.service';
import { ConfigStateService } from '../services/config-state.service';
import { EnvironmentService } from '../services/environment.service';
export interface LoginParams {
username: string;
password: string;
rememberMe?: boolean;
redirectUrl?: string;
}
export const oAuthStorage = localStorage;
export abstract class AuthFlowStrategy {
@ -17,9 +29,9 @@ export abstract class AuthFlowStrategy {
protected oAuthService: OAuthService;
protected oAuthConfig: AuthConfig;
abstract checkIfInternalAuth(): boolean;
abstract login(): void;
abstract navigateToLogin(): void;
abstract logout(): Observable<any>;
abstract destroy(): void;
abstract login(params?: LoginParams): Observable<any>;
private catchError = err => this.store.dispatch(new RestOccurError(err));
@ -39,7 +51,16 @@ export abstract class AuthFlowStrategy {
if (shouldClear) clearOAuthStorage(oAuthStorage);
this.oAuthService.configure(this.oAuthConfig);
return this.oAuthService.loadDiscoveryDocument().catch(this.catchError);
return this.oAuthService
.loadDiscoveryDocument()
.then(() => {
if (this.oAuthService.hasValidAccessToken() || !this.oAuthService.getRefreshToken()) {
return Promise.resolve();
}
return this.oAuthService.refreshToken() as Promise<any>;
})
.catch(this.catchError);
}
}
@ -50,17 +71,10 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy {
return super
.init()
.then(() => this.oAuthService.tryLogin())
.then(() => {
if (this.oAuthService.hasValidAccessToken() || !this.oAuthService.getRefreshToken()) {
return Promise.resolve();
}
return this.oAuthService.refreshToken() as Promise<any>;
})
.then(() => this.oAuthService.setupAutomaticSilentRefresh({}, 'access_token'));
}
login() {
navigateToLogin() {
this.oAuthService.initCodeFlow();
}
@ -70,18 +84,115 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy {
}
logout() {
this.oAuthService.revokeTokenAndLogout();
// TODO: no need to return of(null). It may be removed in v5.0.
return from(this.oAuthService.revokeTokenAndLogout());
}
login() {
this.oAuthService.initCodeFlow();
return of(null);
}
}
destroy() {}
export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
readonly isInternalAuth = true;
private cookieKey = 'rememberMe';
private storageKey = 'passwordFlow';
private appConfigService = this.injector.get(AbpApplicationConfigurationService);
private listenToTokenExpiration() {
this.oAuthService.events
.pipe(
filter(
event =>
event instanceof OAuthInfoEvent &&
event.type === 'token_expires' &&
event.info === 'access_token',
),
)
.subscribe(() => {
if (this.oAuthService.getRefreshToken()) {
this.oAuthService.refreshToken();
} else {
this.oAuthService.logOut();
this.appConfigService.get().subscribe(res => {
this.configState.setState(res);
});
}
});
}
private setRememberMe(remember: boolean) {
this.removeRememberMe();
localStorage.setItem(this.storageKey, 'true');
document.cookie = `${this.cookieKey}=true${
remember ? ';expires=Fri, 31 Dec 9999 23:59:59 GMT' : ''
}`;
}
private removeRememberMe() {
localStorage.removeItem(this.storageKey);
document.cookie = this.cookieKey + '= ; expires = Thu, 01 Jan 1970 00:00:00 GMT';
}
async init() {
if (!getCookieValueByName('rememberMe') && localStorage.getItem(this.storageKey)) {
this.oAuthService.logOut();
}
return super.init().then(() => this.listenToTokenExpiration());
}
navigateToLogin() {
const router = this.injector.get(Router);
router.navigateByUrl('/account/login');
}
checkIfInternalAuth() {
return true;
}
login(params: LoginParams): Observable<any> {
const sessionState = this.injector.get(SessionStateService);
const router = this.injector.get(Router);
const tenant = sessionState.getTenant();
return from(
this.oAuthService.fetchTokenUsingPasswordFlow(
params.username,
params.password,
new HttpHeaders({ ...(tenant && tenant.id && { __tenant: tenant.id }) }),
),
).pipe(
switchMap(() => this.appConfigService.get()),
tap(res => {
this.configState.setState(res);
this.setRememberMe(params.rememberMe);
router.navigate([params.redirectUrl || '/']);
}),
);
}
logout() {
const router = this.injector.get(Router);
return from(this.oAuthService.revokeTokenAndLogout()).pipe(
switchMap(() => this.appConfigService.get()),
tap(res => {
this.configState.setState(res);
router.navigateByUrl('/');
this.removeRememberMe();
}),
);
}
}
export const AUTH_FLOW_STRATEGY = {
Code(injector: Injector) {
return new AuthCodeFlowStrategy(injector);
},
Password(injector: Injector) {
return new AuthPasswordFlowStrategy(injector);
},
};
export function clearOAuthStorage(storage: OAuthStorage = oAuthStorage) {
@ -114,3 +225,8 @@ function shouldStorageClear(clientId: string, storage: OAuthStorage): boolean {
if (shouldClear) storage.setItem(key, clientId);
return shouldClear;
}
function getCookieValueByName(name: string) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? match[2] : '';
}

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

@ -1,4 +1,3 @@
export * from './auth-flow.strategy';
export * from './container.strategy';
export * from './content-security.strategy';
export * from './content.strategy';

6
npm/ng-packs/packages/core/src/lib/tests/auth.guard.spec.ts

@ -21,12 +21,12 @@ describe('AuthGuard', () => {
expect(guard.canActivate()).toBe(true);
});
it('should execute the initLogin method of the authService', () => {
it('should execute the navigateToLogin method of the authService', () => {
const authService = spectator.inject(AuthService);
spectator.inject(OAuthService).hasValidAccessToken.andReturn(false);
const initLoginSpy = jest.spyOn(authService, 'initLogin');
const navigateToLoginSpy = jest.spyOn(authService, 'navigateToLogin');
expect(guard.canActivate()).toBe(false);
expect(initLoginSpy).toHaveBeenCalled();
expect(navigateToLoginSpy).toHaveBeenCalled();
});
});

2
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -1,9 +1,7 @@
import { registerLocaleData } from '@angular/common';
import { Injector } from '@angular/core';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { tap } from 'rxjs/operators';
import { ApplicationConfiguration } from '../models/application-configuration';
import { ABP } from '../models/common';
import { Environment } from '../models/environment';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';

7
npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html

@ -43,7 +43,12 @@
}}</label>
</div>
<div [@collapse]="form.get('smtpUseDefaultCredentials').value ? 'collapsed' : 'expanded'">
<div
[@collapse]="{
value: form.get('smtpUseDefaultCredentials').value ? 'collapsed' : 'expanded',
params: { time: '200ms', easing: 'linear' }
}"
>
<div class="form-group">
<label>{{ 'AbpSettingManagement::SmtpDomain' | abpLocalization }}</label>
<input type="text" class="form-control" formControlName="smtpDomain" />

2
npm/ng-packs/packages/setting-management/config/src/providers/setting-tab.provider.ts

@ -17,7 +17,7 @@ export function configureSettingTabs(settingTabs: SettingTabsService) {
settingTabs.add([
{
name: eSettingManamagementSettingTabNames.EmailSettingGroup,
order: 1,
order: 100,
requiredPolicy: 'SettingManagement.Emailing',
component: EmailSettingGroupComponent,
},

26
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts

@ -1,6 +1,5 @@
import { AuthService, ConfigStateService, CurrentUserDto, EnvironmentService } from '@abp/ng.core';
import { AuthService, ConfigStateService, CurrentUserDto } from '@abp/ng.core';
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
@Component({
@ -8,7 +7,7 @@ import { Observable } from 'rxjs';
// tslint:disable-next-line: component-max-inline-declarations
template: `
<ng-template #loginBtn>
<a role="button" class="nav-link pointer" (click)="initLogin()">{{
<a role="button" class="nav-link pointer" (click)="navigateToLogin()">{{
'AbpAccount::Login' | abpLocalization
}}</a>
</ng-template>
@ -36,7 +35,7 @@ import { Observable } from 'rxjs';
aria-labelledby="dropdownMenuLink"
[class.d-block]="smallScreen && currentUserDropdown.isOpen()"
>
<a class="dropdown-item" [href]="manageProfileUrl"
<a class="dropdown-item" routerLink="/account/manage-profile"
><i class="fa fa-cog mr-1"></i>{{ 'AbpAccount::ManageYourProfile' | abpLocalization }}</a
>
<a class="dropdown-item" href="javascript:void(0)" (click)="logout()"
@ -53,24 +52,13 @@ export class CurrentUserComponent {
return window.innerWidth < 992;
}
get manageProfileUrl() {
return `${this.environment.getEnvironment().oAuthConfig.issuer}/Account/Manage?returnUrl=${
window.location.href
}`;
}
constructor(
private authService: AuthService,
private router: Router,
private configState: ConfigStateService,
private environment: EnvironmentService,
) {}
constructor(private authService: AuthService, private configState: ConfigStateService) {}
initLogin() {
this.authService.initLogin();
navigateToLogin() {
this.authService.navigateToLogin();
}
logout() {
logout() {
this.authService.logout().subscribe();
}
}

4
npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts

@ -275,8 +275,8 @@ export class ErrorHandler {
});
}
protected navigateToLogin() {
this.injector.get(AuthService).initLogin();
private navigateToLogin() {
this.injector.get(AuthService).navigateToLogin();
}
createErrorComponent(instance: Partial<HttpErrorWrapperComponent>) {

2
npm/ng-packs/tsconfig.json

@ -22,6 +22,8 @@
"@abp/ng.theme.shared/extensions": ["packages/theme-shared/extensions/src/public-api.ts"],
"@abp/ng.components/tree": ["packages/components/tree/src/public-api.ts"],
"@abp/ng.theme.basic": ["packages/theme-basic/src/public-api.ts"],
"@abp/ng.account": ["packages/account/src/public-api.ts"],
"@abp/ng.account/config": ["packages/account/config/src/public-api.ts"],
"@abp/ng.identity": ["packages/identity/src/public-api.ts"],
"@abp/ng.identity/config": ["packages/identity/config/src/public-api.ts"],
"@abp/ng.tenant-management": ["packages/tenant-management/src/public-api.ts"],

2366
npm/ng-packs/yarn.lock

File diff suppressed because it is too large

2
templates/app/angular/src/app/home/home.component.ts

@ -14,6 +14,6 @@ export class HomeComponent {
constructor(private oAuthService: OAuthService, private authService: AuthService) {}
login() {
this.authService.initLogin();
this.authService.navigateToLogin();
}
}

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application.Contracts/MyCompanyName.MyProjectName.Application.Contracts.csproj

@ -19,6 +19,9 @@
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Application.Contracts\Volo.Abp.TenantManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Application.Contracts\Volo.Abp.FeatureManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Application.Contracts\Volo.Abp.SettingManagement.Application.Contracts.csproj" />
<!--<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>-->
<ProjectReference Include="..\..\..\..\..\modules\cms-kit\src\Volo.CmsKit.Application.Contracts\Volo.CmsKit.Application.Contracts.csproj" />
<!--</TEMPLATE-REMOVE>-->
</ItemGroup>
</Project>

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application.Contracts/MyProjectNameApplicationContractsModule.cs

@ -6,6 +6,9 @@ using Volo.Abp.ObjectExtending;
using Volo.Abp.PermissionManagement;
using Volo.Abp.SettingManagement;
using Volo.Abp.TenantManagement;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit.Admin;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName
{
@ -17,6 +20,9 @@ namespace MyCompanyName.MyProjectName
typeof(AbpPermissionManagementApplicationContractsModule),
typeof(AbpSettingManagementApplicationContractsModule),
typeof(AbpTenantManagementApplicationContractsModule),
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
typeof(CmsKitAdminApplicationContractsModule),
//</TEMPLATE-REMOVE>
typeof(AbpObjectExtendingModule)
)]
public class MyProjectNameApplicationContractsModule : AbpModule

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application/MyCompanyName.MyProjectName.Application.csproj

@ -19,6 +19,9 @@
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Application\Volo.Abp.TenantManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Application\Volo.Abp.FeatureManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Application\Volo.Abp.SettingManagement.Application.csproj" />
<!--<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>-->
<ProjectReference Include="..\..\..\..\..\modules\cms-kit\src\Volo.CmsKit.Application\Volo.CmsKit.Application.csproj" />
<!--</TEMPLATE-REMOVE>-->
</ItemGroup>
</Project>

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Application/MyProjectNameApplicationModule.cs

@ -6,6 +6,9 @@ using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.SettingManagement;
using Volo.Abp.TenantManagement;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName
{
@ -17,6 +20,9 @@ namespace MyCompanyName.MyProjectName
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpTenantManagementApplicationModule),
typeof(AbpFeatureManagementApplicationModule),
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
typeof(CmsKitApplicationModule),
//</TEMPLATE-REMOVE>
typeof(AbpSettingManagementApplicationModule)
)]
public class MyProjectNameApplicationModule : AbpModule

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj

@ -17,6 +17,9 @@
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Domain.Shared\Volo.Abp.FeatureManagement.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Domain.Shared\Volo.Abp.PermissionManagement.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Domain.Shared\Volo.Abp.SettingManagement.Domain.Shared.csproj" />
<!--<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>-->
<ProjectReference Include="..\..\..\..\..\modules\cms-kit\src\Volo.CmsKit.Domain.Shared\Volo.CmsKit.Domain.Shared.csproj" />
<!--</TEMPLATE-REMOVE>-->
</ItemGroup>
<ItemGroup>

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyProjectNameDomainSharedModule.cs

@ -12,6 +12,9 @@ using Volo.Abp.SettingManagement;
using Volo.Abp.TenantManagement;
using Volo.Abp.Validation.Localization;
using Volo.Abp.VirtualFileSystem;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName
{
@ -23,6 +26,9 @@ namespace MyCompanyName.MyProjectName
typeof(AbpIdentityServerDomainSharedModule),
typeof(AbpPermissionManagementDomainSharedModule),
typeof(AbpSettingManagementDomainSharedModule),
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
typeof(CmsKitDomainSharedModule),
//</TEMPLATE-REMOVE>
typeof(AbpTenantManagementDomainSharedModule)
)]
public class MyProjectNameDomainSharedModule : AbpModule

10
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyProjectNameGlobalFeatureConfigurator.cs

@ -1,4 +1,5 @@
using Volo.Abp.Threading;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Threading;
namespace MyCompanyName.MyProjectName
{
@ -10,6 +11,13 @@ namespace MyCompanyName.MyProjectName
{
OneTimeRunner.Run(() =>
{
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit =>
{
cmsKit.EnableAll();
});
//</TEMPLATE-REMOVE>
/* You can configure (enable/disable) global features of the used modules here.
*
* YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT!

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj

@ -22,6 +22,9 @@
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Domain\Volo.Abp.TenantManagement.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Domain\Volo.Abp.FeatureManagement.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Domain\Volo.Abp.SettingManagement.Domain.csproj" />
<!--<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>-->
<ProjectReference Include="..\..\..\..\..\modules\cms-kit\src\Volo.CmsKit.Domain\Volo.CmsKit.Domain.csproj" />
<!--</TEMPLATE-REMOVE>-->
</ItemGroup>
</Project>

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyProjectNameDomainModule.cs

@ -13,6 +13,9 @@ using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.PermissionManagement.IdentityServer;
using Volo.Abp.SettingManagement;
using Volo.Abp.TenantManagement;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName
{
@ -27,6 +30,9 @@ namespace MyCompanyName.MyProjectName
typeof(AbpPermissionManagementDomainIdentityServerModule),
typeof(AbpSettingManagementDomainModule),
typeof(AbpTenantManagementDomainModule),
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
typeof(CmsKitDomainModule),
//</TEMPLATE-REMOVE>
typeof(AbpEmailingModule)
)]
public class MyProjectNameDomainModule : AbpModule

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/MyProjectNameMigrationsDbContext.cs

@ -9,6 +9,9 @@ using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit.EntityFrameworkCore;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName.EntityFrameworkCore
{
@ -39,6 +42,9 @@ namespace MyCompanyName.MyProjectName.EntityFrameworkCore
builder.ConfigureIdentityServer();
builder.ConfigureFeatureManagement();
builder.ConfigureTenantManagement();
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
builder.ConfigureCmsKit();
//</TEMPLATE-REMOVE>
/* Configure your own tables/entities inside the ConfigureMyProjectName method */

2954
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20210308123703_CmsKit.Designer.cs

File diff suppressed because it is too large

345
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/20210308123703_CmsKit.cs

@ -0,0 +1,345 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace MyCompanyName.MyProjectName.Migrations
{
public partial class CmsKit : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
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),
IsEnabled = 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
{
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),
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Text = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: false),
RepliedCommentId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsComments", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsEntityTags",
columns: table => new
{
TagId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
EntityId = table.Column<string>(type: "nvarchar(450)", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
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),
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
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),
Content = table.Column<string>(type: "nvarchar(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),
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
{
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),
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
StarCount = table.Column<short>(type: "smallint", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsRatings", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsTags",
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),
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_CmsTags", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsUserReactions",
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),
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
ReactionName = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsUserReactions", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CmsUsers",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
Surname = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
PhoneNumber = table.Column<string>(type: "nvarchar(16)", maxLength: 16, nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false, defaultValue: 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_CmsUsers", x => x.Id);
});
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),
Content = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: true),
CoverImageMediaId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
AuthorId = table.Column<Guid>(type: "uniqueidentifier", 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_CmsBlogPosts", x => x.Id);
table.ForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_AuthorId",
column: x => x.AuthorId,
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_AuthorId",
table: "CmsBlogPosts",
column: "AuthorId");
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_Slug_BlogId",
table: "CmsBlogPosts",
columns: new[] { "Slug", "BlogId" });
migrationBuilder.CreateIndex(
name: "IX_CmsComments_TenantId_EntityType_EntityId",
table: "CmsComments",
columns: new[] { "TenantId", "EntityType", "EntityId" });
migrationBuilder.CreateIndex(
name: "IX_CmsComments_TenantId_RepliedCommentId",
table: "CmsComments",
columns: new[] { "TenantId", "RepliedCommentId" });
migrationBuilder.CreateIndex(
name: "IX_CmsEntityTags_TenantId_EntityId_TagId",
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",
columns: new[] { "TenantId", "EntityType", "EntityId", "CreatorId" });
migrationBuilder.CreateIndex(
name: "IX_CmsTags_TenantId_Name",
table: "CmsTags",
columns: new[] { "TenantId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_CmsUserReactions_TenantId_CreatorId_EntityType_EntityId_ReactionName",
table: "CmsUserReactions",
columns: new[] { "TenantId", "CreatorId", "EntityType", "EntityId", "ReactionName" });
migrationBuilder.CreateIndex(
name: "IX_CmsUserReactions_TenantId_EntityType_EntityId_ReactionName",
table: "CmsUserReactions",
columns: new[] { "TenantId", "EntityType", "EntityId", "ReactionName" });
migrationBuilder.CreateIndex(
name: "IX_CmsUsers_TenantId_Email",
table: "CmsUsers",
columns: new[] { "TenantId", "Email" });
migrationBuilder.CreateIndex(
name: "IX_CmsUsers_TenantId_UserName",
table: "CmsUsers",
columns: new[] { "TenantId", "UserName" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsBlogFeatures");
migrationBuilder.DropTable(
name: "CmsBlogPosts");
migrationBuilder.DropTable(
name: "CmsBlogs");
migrationBuilder.DropTable(
name: "CmsComments");
migrationBuilder.DropTable(
name: "CmsEntityTags");
migrationBuilder.DropTable(
name: "CmsMediaDescriptors");
migrationBuilder.DropTable(
name: "CmsPages");
migrationBuilder.DropTable(
name: "CmsRatings");
migrationBuilder.DropTable(
name: "CmsTags");
migrationBuilder.DropTable(
name: "CmsUserReactions");
migrationBuilder.DropTable(
name: "CmsUsers");
}
}
}

651
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations/MyProjectNameMigrationsDbContextModelSnapshot.cs

@ -16,10 +16,10 @@ namespace MyCompanyName.MyProjectName.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.UseIdentityColumns()
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.0-rc.2.20475.6");
.HasAnnotation("ProductVersion", "5.0.3")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
{
@ -1937,6 +1937,642 @@ namespace MyCompanyName.MyProjectName.Migrations
b.ToTable("AbpTenantConnectionStrings");
});
modelBuilder.Entity("Volo.CmsKit.Blogs.Blog", 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>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
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")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("CoverImageMediaId")
.HasColumnType("uniqueidentifier");
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>("ShortDescription")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("Slug", "BlogId");
b.ToTable("CmsBlogPosts");
});
modelBuilder.Entity("Volo.CmsKit.Comments.Comment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid?>("RepliedCommentId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Text")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.HasKey("Id");
b.HasIndex("TenantId", "RepliedCommentId");
b.HasIndex("TenantId", "EntityType", "EntityId");
b.ToTable("CmsComments");
});
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>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
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")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
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>("Slug")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("TenantId", "Slug");
b.ToTable("CmsPages");
});
modelBuilder.Entity("Volo.CmsKit.Ratings.Rating", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<short>("StarCount")
.HasColumnType("smallint");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("TenantId", "EntityType", "EntityId", "CreatorId");
b.ToTable("CmsRatings");
});
modelBuilder.Entity("Volo.CmsKit.Reactions.UserReaction", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ReactionName")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("TenantId", "EntityType", "EntityId", "ReactionName");
b.HasIndex("TenantId", "CreatorId", "EntityType", "EntityId", "ReactionName");
b.ToTable("CmsUserReactions");
});
modelBuilder.Entity("Volo.CmsKit.Tags.EntityTag", b =>
{
b.Property<string>("EntityId")
.HasColumnType("nvarchar(450)");
b.Property<Guid>("TagId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("EntityId", "TagId");
b.HasIndex("TenantId", "EntityId", "TagId");
b.ToTable("CmsEntityTags");
});
modelBuilder.Entity("Volo.CmsKit.Tags.Tag", 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>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
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>("Name")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("TenantId", "Name");
b.ToTable("CmsTags");
});
modelBuilder.Entity("Volo.CmsKit.Users.CmsUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("Email");
b.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("EmailConfirmed");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("Name")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Name");
b.Property<string>("PhoneNumber")
.HasMaxLength(16)
.HasColumnType("nvarchar(16)")
.HasColumnName("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("PhoneNumberConfirmed");
b.Property<string>("Surname")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Surname");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("UserName");
b.HasKey("Id");
b.HasIndex("TenantId", "Email");
b.HasIndex("TenantId", "UserName");
b.ToTable("CmsUsers");
});
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
{
b.HasOne("Volo.Abp.AuditLogging.AuditLog", null)
@ -2214,6 +2850,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.IsRequired();
});
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.HasOne("Volo.CmsKit.Users.CmsUser", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
{
b.Navigation("Actions");

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameEntityFrameworkCoreModule.cs

@ -10,6 +10,9 @@ using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit.EntityFrameworkCore;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName.EntityFrameworkCore
{
@ -23,6 +26,9 @@ namespace MyCompanyName.MyProjectName.EntityFrameworkCore
typeof(AbpBackgroundJobsEntityFrameworkCoreModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule),
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
typeof(CmsKitEntityFrameworkCoreModule),
//</TEMPLATE-REMOVE>
typeof(AbpFeatureManagementEntityFrameworkCoreModule)
)]
public class MyProjectNameEntityFrameworkCoreModule : AbpModule

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj

@ -18,6 +18,9 @@
<ProjectReference Include="..\..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.EntityFrameworkCore\Volo.Abp.AuditLogging.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.EntityFrameworkCore\Volo.Abp.TenantManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.EntityFrameworkCore\Volo.Abp.FeatureManagement.EntityFrameworkCore.csproj" />
<!--<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>-->
<ProjectReference Include="..\..\..\..\..\modules\cms-kit\src\Volo.CmsKit.EntityFrameworkCore\Volo.CmsKit.EntityFrameworkCore.csproj" />
<!--</TEMPLATE-REMOVE>-->
</ItemGroup>
</Project>

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj

@ -18,6 +18,9 @@
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi.Client\Volo.Abp.TenantManagement.HttpApi.Client.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi.Client\Volo.Abp.FeatureManagement.HttpApi.Client.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.HttpApi.Client\Volo.Abp.SettingManagement.HttpApi.Client.csproj" />
<!--<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>-->
<ProjectReference Include="..\..\..\..\..\modules\cms-kit\src\Volo.CmsKit.HttpApi.Client\Volo.CmsKit.HttpApi.Client.csproj" />
<!--</TEMPLATE-REMOVE>-->
</ItemGroup>
</Project>

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyProjectNameHttpApiClientModule.cs

@ -6,6 +6,9 @@ using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.TenantManagement;
using Volo.Abp.SettingManagement;
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
using Volo.CmsKit;
//</TEMPLATE-REMOVE>
namespace MyCompanyName.MyProjectName
{
@ -16,6 +19,9 @@ namespace MyCompanyName.MyProjectName
typeof(AbpPermissionManagementHttpApiClientModule),
typeof(AbpTenantManagementHttpApiClientModule),
typeof(AbpFeatureManagementHttpApiClientModule),
//<TEMPLATE-REMOVE IF-NOT='CMS-KIT'>
typeof(CmsKitHttpApiClientModule),
//</TEMPLATE-REMOVE>
typeof(AbpSettingManagementHttpApiClientModule)
)]
public class MyProjectNameHttpApiClientModule : AbpModule

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs

@ -13,6 +13,7 @@ using MyCompanyName.MyProjectName.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.MultiTenancy;
@ -78,6 +79,9 @@ namespace MyCompanyName.MyProjectName
{
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));
options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"];
options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password";
});
}

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

Loading…
Cancel
Save