mirror of https://github.com/abpframework/abp.git
62 changed files with 6292 additions and 1 deletions
@ -0,0 +1,36 @@ |
|||
{ |
|||
"extends": ["../../.eslintrc.json"], |
|||
"ignorePatterns": ["!**/*"], |
|||
"overrides": [ |
|||
{ |
|||
"files": ["*.ts"], |
|||
"extends": [ |
|||
"plugin:@nrwl/nx/angular", |
|||
"plugin:@angular-eslint/template/process-inline-templates" |
|||
], |
|||
"rules": { |
|||
"@angular-eslint/directive-selector": [ |
|||
"error", |
|||
{ |
|||
"type": "attribute", |
|||
"prefix": "abp", |
|||
"style": "camelCase" |
|||
} |
|||
], |
|||
"@angular-eslint/component-selector": [ |
|||
"error", |
|||
{ |
|||
"type": "element", |
|||
"prefix": "abp", |
|||
"style": "kebab-case" |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
{ |
|||
"files": ["*.html"], |
|||
"extends": ["plugin:@nrwl/nx/angular-template"], |
|||
"rules": {} |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<h1> @abp/ng.identity </h1> |
|||
|
|||
[docs.abp.io](https://docs.abp.io) |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", |
|||
"dest": "../../../dist/packages/identity/config", |
|||
"lib": { |
|||
"entryFile": "src/public-api.ts" |
|||
} |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
export * from './policy-names'; |
|||
export * from './route-names'; |
|||
@ -0,0 +1,5 @@ |
|||
export const enum eIdentityPolicyNames { |
|||
IdentityManagement = 'AbpIdentity.Roles || AbpIdentity.Users', |
|||
Roles = 'AbpIdentity.Roles', |
|||
Users = 'AbpIdentity.Users', |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
export const enum eIdentityRouteNames { |
|||
IdentityManagement = 'AbpIdentity::Menu:IdentityManagement', |
|||
Roles = 'AbpIdentity::Roles', |
|||
Users = 'AbpIdentity::Users', |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
import { ModuleWithProviders, NgModule } from '@angular/core'; |
|||
import { IDENTITY_ROUTE_PROVIDERS } from './providers/route.provider'; |
|||
|
|||
@NgModule() |
|||
export class IdentityConfigModule { |
|||
static forRoot(): ModuleWithProviders<IdentityConfigModule> { |
|||
return { |
|||
ngModule: IdentityConfigModule, |
|||
providers: [IDENTITY_ROUTE_PROVIDERS], |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './route.provider'; |
|||
@ -0,0 +1,39 @@ |
|||
import { eLayoutType, RoutesService } from '@abp/ng.core'; |
|||
import { eThemeSharedRouteNames } from '@abp/ng.theme.shared'; |
|||
import { APP_INITIALIZER } from '@angular/core'; |
|||
import { eIdentityPolicyNames } from '../enums/policy-names'; |
|||
import { eIdentityRouteNames } from '../enums/route-names'; |
|||
|
|||
export const IDENTITY_ROUTE_PROVIDERS = [ |
|||
{ provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, |
|||
]; |
|||
|
|||
export function configureRoutes(routesService: RoutesService) { |
|||
return () => { |
|||
routesService.add([ |
|||
{ |
|||
path: undefined, |
|||
name: eIdentityRouteNames.IdentityManagement, |
|||
parentName: eThemeSharedRouteNames.Administration, |
|||
requiredPolicy: eIdentityPolicyNames.IdentityManagement, |
|||
iconClass: 'fa fa-id-card-o', |
|||
layout: eLayoutType.application, |
|||
order: 1, |
|||
}, |
|||
{ |
|||
path: '/identity/roles', |
|||
name: eIdentityRouteNames.Roles, |
|||
parentName: eIdentityRouteNames.IdentityManagement, |
|||
requiredPolicy: eIdentityPolicyNames.Roles, |
|||
order: 1, |
|||
}, |
|||
{ |
|||
path: '/identity/users', |
|||
name: eIdentityRouteNames.Users, |
|||
parentName: eIdentityRouteNames.IdentityManagement, |
|||
requiredPolicy: eIdentityPolicyNames.Users, |
|||
order: 2, |
|||
}, |
|||
]); |
|||
}; |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
export * from './enums'; |
|||
export * from './identity-config.module'; |
|||
export * from './providers'; |
|||
@ -0,0 +1,20 @@ |
|||
module.exports = { |
|||
displayName: 'identity', |
|||
preset: '../../jest.preset.js', |
|||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], |
|||
globals: { |
|||
'ts-jest': { |
|||
tsconfig: '<rootDir>/tsconfig.spec.json', |
|||
stringifyContentPathRegex: '\\.(html|svg)$', |
|||
}, |
|||
}, |
|||
coverageDirectory: '../../coverage/packages/identity', |
|||
transform: { |
|||
'^.+\\.(ts|js|html)$': 'jest-preset-angular', |
|||
}, |
|||
snapshotSerializers: [ |
|||
'jest-preset-angular/build/serializers/no-ng-attributes', |
|||
'jest-preset-angular/build/serializers/ng-snapshot', |
|||
'jest-preset-angular/build/serializers/html-comment', |
|||
], |
|||
}; |
|||
@ -0,0 +1,11 @@ |
|||
{ |
|||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json", |
|||
"dest": "../../dist/packages/identity", |
|||
"lib": { |
|||
"entryFile": "src/public-api.ts" |
|||
}, |
|||
"allowedNonPeerDependencies": [ |
|||
"@abp/ng.theme.shared", |
|||
"@abp/ng.permission-management" |
|||
] |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
{ |
|||
"name": "@abp/ng.identity", |
|||
"version": "4.4.0", |
|||
"homepage": "https://abp.io", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "https://github.com/abpframework/abp.git" |
|||
}, |
|||
"dependencies": { |
|||
"@abp/ng.permission-management": "~4.4.0", |
|||
"@abp/ng.theme.shared": "~4.4.0", |
|||
"tslib": "^2.0.0" |
|||
}, |
|||
"publishConfig": { |
|||
"access": "public" |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
import { Identity } from '../models/identity'; |
|||
import { ABP, PagedAndSortedResultRequestDto } from '@abp/ng.core'; |
|||
import { |
|||
GetIdentityUsersInput, |
|||
IdentityRoleCreateDto, |
|||
IdentityRoleUpdateDto, |
|||
IdentityUserCreateDto, |
|||
IdentityUserUpdateDto, |
|||
} from '../proxy/identity/models'; |
|||
|
|||
export class GetRoles { |
|||
static readonly type = '[Identity] Get Roles'; |
|||
constructor(public payload?: PagedAndSortedResultRequestDto) {} |
|||
} |
|||
|
|||
export class GetRoleById { |
|||
static readonly type = '[Identity] Get Role By Id'; |
|||
constructor(public payload: string) {} |
|||
} |
|||
|
|||
export class DeleteRole { |
|||
static readonly type = '[Identity] Delete Role'; |
|||
constructor(public payload: string) {} |
|||
} |
|||
|
|||
export class CreateRole { |
|||
static readonly type = '[Identity] Create Role'; |
|||
constructor(public payload: IdentityRoleCreateDto) {} |
|||
} |
|||
|
|||
export class UpdateRole { |
|||
static readonly type = '[Identity] Update Role'; |
|||
constructor(public payload: IdentityRoleUpdateDto & { id: string }) {} |
|||
} |
|||
|
|||
export class GetUsers { |
|||
static readonly type = '[Identity] Get Users'; |
|||
constructor(public payload?: GetIdentityUsersInput) {} |
|||
} |
|||
|
|||
export class GetUserById { |
|||
static readonly type = '[Identity] Get User By Id'; |
|||
constructor(public payload: string) {} |
|||
} |
|||
|
|||
export class DeleteUser { |
|||
static readonly type = '[Identity] Delete User'; |
|||
constructor(public payload: string) {} |
|||
} |
|||
|
|||
export class CreateUser { |
|||
static readonly type = '[Identity] Create User'; |
|||
constructor(public payload: IdentityUserCreateDto) {} |
|||
} |
|||
|
|||
export class UpdateUser { |
|||
static readonly type = '[Identity] Update User'; |
|||
constructor(public payload: IdentityUserUpdateDto & { id: string }) {} |
|||
} |
|||
|
|||
export class GetUserRoles { |
|||
static readonly type = '[Identity] Get User Roles'; |
|||
constructor(public payload: string) {} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './identity.actions'; |
|||
@ -0,0 +1,2 @@ |
|||
export * from './roles/roles.component'; |
|||
export * from './users/users.component'; |
|||
@ -0,0 +1,60 @@ |
|||
<div id="identity-roles-wrapper" class="card"> |
|||
<div class="card-header"> |
|||
<div class="row"> |
|||
<div class="col col-md-6"> |
|||
<h5 class="card-title">{{ 'AbpIdentity::Roles' | abpLocalization }}</h5> |
|||
</div> |
|||
<div class="text-right col col-md-6"> |
|||
<abp-page-toolbar [record]="data$ | async"></abp-page-toolbar> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="card-body"> |
|||
<abp-extensible-table |
|||
[data]="data$ | async" |
|||
[recordsTotal]="totalCount$ | async" |
|||
[list]="list" |
|||
></abp-extensible-table> |
|||
</div> |
|||
</div> |
|||
|
|||
<abp-modal size="md" [(visible)]="isModalVisible" [busy]="modalBusy"> |
|||
<ng-template #abpHeader> |
|||
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}</h3> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpBody> |
|||
<form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit> |
|||
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpFooter> |
|||
<button type="button" class="btn btn-secondary" abpClose> |
|||
{{ 'AbpIdentity::Cancel' | abpLocalization }} |
|||
</button> |
|||
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{ |
|||
'AbpIdentity::Save' | abpLocalization |
|||
}}</abp-button> |
|||
</ng-template> |
|||
</abp-modal> |
|||
|
|||
<abp-permission-management |
|||
#abpPermissionManagement="abpPermissionManagement" |
|||
*abpReplaceableTemplate=" |
|||
{ |
|||
inputs: { |
|||
providerName: { value: 'R' }, |
|||
providerKey: { value: providerKey }, |
|||
visible: { value: visiblePermissions, twoWay: true }, |
|||
hideBadges: { value: true } |
|||
}, |
|||
outputs: { visibleChange: onVisiblePermissionChange }, |
|||
componentKey: permissionManagementKey |
|||
}; |
|||
let init = initTemplate |
|||
" |
|||
(abpInit)="init(abpPermissionManagement)" |
|||
> |
|||
</abp-permission-management> |
|||
@ -0,0 +1,142 @@ |
|||
import { ListService, PagedAndSortedResultRequestDto } from '@abp/ng.core'; |
|||
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; |
|||
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; |
|||
import { |
|||
EXTENSIONS_IDENTIFIER, |
|||
FormPropData, |
|||
generateFormFromProps, |
|||
} from '@abp/ng.theme.shared/extensions'; |
|||
import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core'; |
|||
import { FormGroup } from '@angular/forms'; |
|||
import { Select, Store } from '@ngxs/store'; |
|||
import { Observable } from 'rxjs'; |
|||
import { finalize, pluck } from 'rxjs/operators'; |
|||
import { |
|||
CreateRole, |
|||
DeleteRole, |
|||
GetRoleById, |
|||
GetRoles, |
|||
UpdateRole, |
|||
} from '../../actions/identity.actions'; |
|||
import { eIdentityComponents } from '../../enums/components'; |
|||
import { IdentityRoleDto } from '../../proxy/identity/models'; |
|||
import { IdentityState } from '../../states/identity.state'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-roles', |
|||
templateUrl: './roles.component.html', |
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eIdentityComponents.Roles, |
|||
}, |
|||
], |
|||
}) |
|||
export class RolesComponent implements OnInit { |
|||
@Select(IdentityState.getRoles) |
|||
data$: Observable<IdentityRoleDto[]>; |
|||
|
|||
@Select(IdentityState.getRolesTotalCount) |
|||
totalCount$: Observable<number>; |
|||
|
|||
form: FormGroup; |
|||
|
|||
selected: IdentityRoleDto; |
|||
|
|||
isModalVisible: boolean; |
|||
|
|||
visiblePermissions = false; |
|||
|
|||
providerKey: string; |
|||
|
|||
modalBusy = false; |
|||
|
|||
permissionManagementKey = ePermissionManagementComponents.PermissionManagement; |
|||
|
|||
onVisiblePermissionChange = event => { |
|||
this.visiblePermissions = event; |
|||
}; |
|||
|
|||
constructor( |
|||
public readonly list: ListService<PagedAndSortedResultRequestDto>, |
|||
protected confirmationService: ConfirmationService, |
|||
protected store: Store, |
|||
protected injector: Injector, |
|||
) {} |
|||
|
|||
ngOnInit() { |
|||
this.hookToQuery(); |
|||
} |
|||
|
|||
buildForm() { |
|||
const data = new FormPropData(this.injector, this.selected); |
|||
this.form = generateFormFromProps(data); |
|||
} |
|||
|
|||
openModal() { |
|||
this.buildForm(); |
|||
this.isModalVisible = true; |
|||
} |
|||
|
|||
add() { |
|||
this.selected = {} as IdentityRoleDto; |
|||
this.openModal(); |
|||
} |
|||
|
|||
edit(id: string) { |
|||
this.store |
|||
.dispatch(new GetRoleById(id)) |
|||
.pipe(pluck('IdentityState', 'selectedRole')) |
|||
.subscribe(selectedRole => { |
|||
this.selected = selectedRole; |
|||
this.openModal(); |
|||
}); |
|||
} |
|||
|
|||
save() { |
|||
if (!this.form.valid) return; |
|||
this.modalBusy = true; |
|||
|
|||
this.store |
|||
.dispatch( |
|||
this.selected.id |
|||
? new UpdateRole({ ...this.selected, ...this.form.value, id: this.selected.id }) |
|||
: new CreateRole(this.form.value), |
|||
) |
|||
.pipe(finalize(() => (this.modalBusy = false))) |
|||
.subscribe(() => { |
|||
this.isModalVisible = false; |
|||
this.list.get(); |
|||
}); |
|||
} |
|||
|
|||
delete(id: string, name: string) { |
|||
this.confirmationService |
|||
.warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', { |
|||
messageLocalizationParams: [name], |
|||
}) |
|||
.subscribe((status: Confirmation.Status) => { |
|||
if (status === Confirmation.Status.confirm) { |
|||
this.store.dispatch(new DeleteRole(id)).subscribe(() => this.list.get()); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private hookToQuery() { |
|||
this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe(); |
|||
} |
|||
|
|||
openPermissionsModal(providerKey: string) { |
|||
this.providerKey = providerKey; |
|||
setTimeout(() => { |
|||
this.visiblePermissions = true; |
|||
}, 0); |
|||
} |
|||
|
|||
sort(data) { |
|||
const { prop, dir } = data.sorts[0]; |
|||
this.list.sortKey = prop; |
|||
this.list.sortOrder = dir; |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
<div id="identity-roles-wrapper" class="card"> |
|||
<div class="card-header"> |
|||
<div class="row"> |
|||
<div class="col col-md-6"> |
|||
<h5 class="card-title">{{ 'AbpIdentity::Users' | abpLocalization }}</h5> |
|||
</div> |
|||
<div class="text-right col col-md-6"> |
|||
<abp-page-toolbar [record]="data$ | async"></abp-page-toolbar> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="card-body"> |
|||
<div id="data-tables-table-filter" class="data-tables-filter"> |
|||
<div class="input-group"> |
|||
<input |
|||
type="search" |
|||
class="form-control" |
|||
[placeholder]="'AbpUi::PagerSearch' | abpLocalization" |
|||
[(ngModel)]="list.filter" |
|||
/> |
|||
</div> |
|||
</div> |
|||
|
|||
<abp-extensible-table |
|||
[data]="data$ | async" |
|||
[recordsTotal]="totalCount$ | async" |
|||
[list]="list" |
|||
></abp-extensible-table> |
|||
</div> |
|||
</div> |
|||
|
|||
<abp-modal size="md" [(visible)]="isModalVisible" [busy]="modalBusy"> |
|||
<ng-template #abpHeader> |
|||
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewUser') | abpLocalization }}</h3> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpBody> |
|||
<ng-template #loaderRef |
|||
><div class="text-center"><i class="fa fa-pulse fa-spinner"></i></div |
|||
></ng-template> |
|||
|
|||
<form *ngIf="form; else loaderRef" [formGroup]="form" (ngSubmit)="save()"> |
|||
<ul ngbNav #nav="ngbNav" class="nav-tabs"> |
|||
<li ngbNavItem> |
|||
<a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a> |
|||
<ng-template ngbNavContent> |
|||
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> |
|||
</ng-template> |
|||
</li> |
|||
|
|||
<li ngbNavItem> |
|||
<a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a> |
|||
<ng-template ngbNavContent> |
|||
<div |
|||
*ngFor="let roleGroup of roleGroups; let i = index; trackBy: trackByFn" |
|||
class="custom-checkbox custom-control mb-2" |
|||
> |
|||
<input |
|||
type="checkbox" |
|||
class="custom-control-input" |
|||
[attr.id]="'roles-' + i" |
|||
[formControl]="roleGroup.controls[roles[i].name]" |
|||
/> |
|||
<label class="custom-control-label" [attr.for]="'roles-' + i">{{ |
|||
roles[i].name |
|||
}}</label> |
|||
</div> |
|||
</ng-template> |
|||
</li> |
|||
</ul> |
|||
|
|||
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpFooter> |
|||
<button type="button" class="btn btn-secondary" abpClose> |
|||
{{ 'AbpIdentity::Cancel' | abpLocalization }} |
|||
</button> |
|||
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{ |
|||
'AbpIdentity::Save' | abpLocalization |
|||
}}</abp-button> |
|||
</ng-template> |
|||
</abp-modal> |
|||
|
|||
<abp-permission-management |
|||
#abpPermissionManagement="abpPermissionManagement" |
|||
*abpReplaceableTemplate=" |
|||
{ |
|||
inputs: { |
|||
providerName: { value: 'U' }, |
|||
providerKey: { value: providerKey }, |
|||
visible: { value: visiblePermissions, twoWay: true } |
|||
}, |
|||
outputs: { visibleChange: onVisiblePermissionChange }, |
|||
componentKey: permissionManagementKey |
|||
}; |
|||
let init = initTemplate |
|||
" |
|||
(abpInit)="init(abpPermissionManagement)" |
|||
> |
|||
</abp-permission-management> |
|||
@ -0,0 +1,211 @@ |
|||
import { ListService } from '@abp/ng.core'; |
|||
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; |
|||
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; |
|||
import { |
|||
EXTENSIONS_IDENTIFIER, |
|||
FormPropData, |
|||
generateFormFromProps, |
|||
} from '@abp/ng.theme.shared/extensions'; |
|||
import { |
|||
Component, |
|||
Injector, |
|||
OnInit, |
|||
TemplateRef, |
|||
TrackByFunction, |
|||
ViewChild, |
|||
} from '@angular/core'; |
|||
import { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms'; |
|||
import { Select, Store } from '@ngxs/store'; |
|||
import { Observable } from 'rxjs'; |
|||
import { finalize, pluck, switchMap, take } from 'rxjs/operators'; |
|||
import snq from 'snq'; |
|||
import { |
|||
CreateUser, |
|||
DeleteUser, |
|||
GetUserById, |
|||
GetUserRoles, |
|||
GetUsers, |
|||
UpdateUser, |
|||
} from '../../actions/identity.actions'; |
|||
import { eIdentityComponents } from '../../enums/components'; |
|||
import { Identity } from '../../models/identity'; |
|||
import { IdentityUserService } from '../../proxy/identity/identity-user.service'; |
|||
import { |
|||
GetIdentityUsersInput, |
|||
IdentityRoleDto, |
|||
IdentityUserDto, |
|||
} from '../../proxy/identity/models'; |
|||
import { IdentityState } from '../../states/identity.state'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-users', |
|||
templateUrl: './users.component.html', |
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eIdentityComponents.Users, |
|||
}, |
|||
], |
|||
}) |
|||
export class UsersComponent implements OnInit { |
|||
@Select(IdentityState.getUsers) |
|||
data$: Observable<IdentityUserDto[]>; |
|||
|
|||
@Select(IdentityState.getUsersTotalCount) |
|||
totalCount$: Observable<number>; |
|||
|
|||
@ViewChild('modalContent', { static: false }) |
|||
modalContent: TemplateRef<any>; |
|||
|
|||
form: FormGroup; |
|||
|
|||
selected: IdentityUserDto; |
|||
|
|||
selectedUserRoles: IdentityRoleDto[]; |
|||
|
|||
roles: IdentityRoleDto[]; |
|||
|
|||
visiblePermissions = false; |
|||
|
|||
providerKey: string; |
|||
|
|||
isModalVisible: boolean; |
|||
|
|||
modalBusy = false; |
|||
|
|||
permissionManagementKey = ePermissionManagementComponents.PermissionManagement; |
|||
|
|||
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index; |
|||
|
|||
onVisiblePermissionChange = event => { |
|||
this.visiblePermissions = event; |
|||
}; |
|||
|
|||
get roleGroups(): FormGroup[] { |
|||
return snq(() => (this.form.get('roleNames') as FormArray).controls as FormGroup[], []); |
|||
} |
|||
|
|||
constructor( |
|||
public readonly list: ListService<GetIdentityUsersInput>, |
|||
protected confirmationService: ConfirmationService, |
|||
protected userService: IdentityUserService, |
|||
protected fb: FormBuilder, |
|||
protected store: Store, |
|||
protected injector: Injector, |
|||
) {} |
|||
|
|||
ngOnInit() { |
|||
this.hookToQuery(); |
|||
} |
|||
|
|||
buildForm() { |
|||
const data = new FormPropData(this.injector, this.selected); |
|||
this.form = generateFormFromProps(data); |
|||
|
|||
this.userService.getAssignableRoles().subscribe(({ items }) => { |
|||
this.roles = items; |
|||
this.form.addControl( |
|||
'roleNames', |
|||
this.fb.array( |
|||
this.roles.map(role => |
|||
this.fb.group({ |
|||
[role.name]: [ |
|||
this.selected.id |
|||
? !!snq(() => this.selectedUserRoles.find(userRole => userRole.id === role.id)) |
|||
: role.isDefault, |
|||
], |
|||
}), |
|||
), |
|||
), |
|||
); |
|||
}); |
|||
} |
|||
|
|||
openModal() { |
|||
this.buildForm(); |
|||
this.isModalVisible = true; |
|||
} |
|||
|
|||
add() { |
|||
this.selected = {} as IdentityUserDto; |
|||
this.selectedUserRoles = [] as IdentityRoleDto[]; |
|||
this.openModal(); |
|||
} |
|||
|
|||
edit(id: string) { |
|||
this.store |
|||
.dispatch(new GetUserById(id)) |
|||
.pipe( |
|||
switchMap(() => this.store.dispatch(new GetUserRoles(id))), |
|||
pluck('IdentityState'), |
|||
take(1), |
|||
) |
|||
.subscribe((state: Identity.State) => { |
|||
this.selected = state.selectedUser; |
|||
this.selectedUserRoles = state.selectedUserRoles || []; |
|||
this.openModal(); |
|||
}); |
|||
} |
|||
|
|||
save() { |
|||
if (!this.form.valid || this.modalBusy) return; |
|||
this.modalBusy = true; |
|||
|
|||
const { roleNames } = this.form.value; |
|||
const mappedRoleNames = snq( |
|||
() => |
|||
roleNames.filter(role => !!role[Object.keys(role)[0]]).map(role => Object.keys(role)[0]), |
|||
[], |
|||
); |
|||
|
|||
this.store |
|||
.dispatch( |
|||
this.selected.id |
|||
? new UpdateUser({ |
|||
...this.selected, |
|||
...this.form.value, |
|||
id: this.selected.id, |
|||
roleNames: mappedRoleNames, |
|||
}) |
|||
: new CreateUser({ |
|||
...this.form.value, |
|||
roleNames: mappedRoleNames, |
|||
}), |
|||
) |
|||
.pipe(finalize(() => (this.modalBusy = false))) |
|||
.subscribe(() => { |
|||
this.isModalVisible = false; |
|||
this.list.get(); |
|||
}); |
|||
} |
|||
|
|||
delete(id: string, userName: string) { |
|||
this.confirmationService |
|||
.warn('AbpIdentity::UserDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', { |
|||
messageLocalizationParams: [userName], |
|||
}) |
|||
.subscribe((status: Confirmation.Status) => { |
|||
if (status === Confirmation.Status.confirm) { |
|||
this.store.dispatch(new DeleteUser(id)).subscribe(() => this.list.get()); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
sort(data) { |
|||
const { prop, dir } = data.sorts[0]; |
|||
this.list.sortKey = prop; |
|||
this.list.sortOrder = dir; |
|||
} |
|||
|
|||
private hookToQuery() { |
|||
this.list.hookToQuery(query => this.store.dispatch(new GetUsers(query))).subscribe(); |
|||
} |
|||
|
|||
openPermissionsModal(providerKey: string) { |
|||
this.providerKey = providerKey; |
|||
setTimeout(() => { |
|||
this.visiblePermissions = true; |
|||
}, 0); |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
import { EntityAction } from '@abp/ng.theme.shared/extensions'; |
|||
import { RolesComponent } from '../components/roles/roles.component'; |
|||
import { IdentityRoleDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_ROLES_ENTITY_ACTIONS = EntityAction.createMany<IdentityRoleDto>([ |
|||
{ |
|||
text: 'AbpIdentity::Edit', |
|||
action: data => { |
|||
const component = data.getInjected(RolesComponent); |
|||
component.edit(data.record.id); |
|||
}, |
|||
permission: 'AbpIdentity.Roles.Update', |
|||
}, |
|||
{ |
|||
text: 'AbpIdentity::Permissions', |
|||
action: data => { |
|||
const component = data.getInjected(RolesComponent); |
|||
component.openPermissionsModal(data.record.name); |
|||
}, |
|||
permission: 'AbpIdentity.Roles.ManagePermissions', |
|||
}, |
|||
{ |
|||
text: 'AbpIdentity::Delete', |
|||
action: data => { |
|||
const component = data.getInjected(RolesComponent); |
|||
component.delete(data.record.id, data.record.name); |
|||
}, |
|||
permission: 'AbpIdentity.Roles.Delete', |
|||
visible: data => !data.record.isStatic, |
|||
}, |
|||
]); |
|||
@ -0,0 +1,32 @@ |
|||
import { LocalizationService } from '@abp/ng.core'; |
|||
import { EntityProp, ePropType } from '@abp/ng.theme.shared/extensions'; |
|||
import { of } from 'rxjs'; |
|||
import { IdentityRoleDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_ROLES_ENTITY_PROPS = EntityProp.createMany<IdentityRoleDto>([ |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'name', |
|||
displayName: 'AbpIdentity::RoleName', |
|||
sortable: true, |
|||
valueResolver: data => { |
|||
const l10n = data.getInjected(LocalizationService); |
|||
const t = l10n.instant.bind(l10n); |
|||
const { isDefault, isPublic, name } = data.record; |
|||
|
|||
return of( |
|||
name + |
|||
(isDefault |
|||
? `<span class="badge badge-pill badge-success ml-1">${t( |
|||
'AbpIdentity::DisplayName:IsDefault', |
|||
)}</span>` |
|||
: '') + |
|||
(isPublic |
|||
? `<span class="badge badge-pill badge-info ml-1">${t( |
|||
'AbpIdentity::DisplayName:IsPublic', |
|||
)}</span>` |
|||
: ''), |
|||
); |
|||
}, |
|||
}, |
|||
]); |
|||
@ -0,0 +1,30 @@ |
|||
import { ePropType, FormProp, PropData } from '@abp/ng.theme.shared/extensions'; |
|||
import { Validators } from '@angular/forms'; |
|||
import { IdentityRoleDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_ROLES_CREATE_FORM_PROPS = FormProp.createMany<IdentityRoleDto>([ |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'name', |
|||
displayName: 'AbpIdentity::RoleName', |
|||
id: 'role-name', |
|||
disabled: (data: PropData<IdentityRoleDto>) => data.record && data.record.isStatic, |
|||
validators: () => [Validators.required], |
|||
}, |
|||
{ |
|||
type: ePropType.Boolean, |
|||
name: 'isDefault', |
|||
displayName: 'AbpIdentity::DisplayName:IsDefault', |
|||
id: 'role-is-default', |
|||
defaultValue: false, |
|||
}, |
|||
{ |
|||
type: ePropType.Boolean, |
|||
name: 'isPublic', |
|||
displayName: 'AbpIdentity::DisplayName:IsPublic', |
|||
id: 'role-is-public', |
|||
defaultValue: false, |
|||
}, |
|||
]); |
|||
|
|||
export const DEFAULT_ROLES_EDIT_FORM_PROPS = DEFAULT_ROLES_CREATE_FORM_PROPS; |
|||
@ -0,0 +1,15 @@ |
|||
import { ToolbarAction } from '@abp/ng.theme.shared/extensions'; |
|||
import { RolesComponent } from '../components/roles/roles.component'; |
|||
import { IdentityRoleDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_ROLES_TOOLBAR_ACTIONS = ToolbarAction.createMany<IdentityRoleDto[]>([ |
|||
{ |
|||
text: 'AbpIdentity::NewRole', |
|||
action: data => { |
|||
const component = data.getInjected(RolesComponent); |
|||
component.add(); |
|||
}, |
|||
permission: 'AbpIdentity.Roles.Create', |
|||
icon: 'fa fa-plus', |
|||
}, |
|||
]); |
|||
@ -0,0 +1,30 @@ |
|||
import { EntityAction } from '@abp/ng.theme.shared/extensions'; |
|||
import { UsersComponent } from '../components/users/users.component'; |
|||
import { IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_USERS_ENTITY_ACTIONS = EntityAction.createMany<IdentityUserDto>([ |
|||
{ |
|||
text: 'AbpIdentity::Edit', |
|||
action: data => { |
|||
const component = data.getInjected(UsersComponent); |
|||
component.edit(data.record.id); |
|||
}, |
|||
permission: 'AbpIdentity.Users.Update', |
|||
}, |
|||
{ |
|||
text: 'AbpIdentity::Permissions', |
|||
action: data => { |
|||
const component = data.getInjected(UsersComponent); |
|||
component.openPermissionsModal(data.record.id); |
|||
}, |
|||
permission: 'AbpIdentity.Users.ManagePermissions', |
|||
}, |
|||
{ |
|||
text: 'AbpIdentity::Delete', |
|||
action: data => { |
|||
const component = data.getInjected(UsersComponent); |
|||
component.delete(data.record.id, data.record.name || data.record.userName); |
|||
}, |
|||
permission: 'AbpIdentity.Users.Delete', |
|||
}, |
|||
]); |
|||
@ -0,0 +1,26 @@ |
|||
import { EntityProp, ePropType } from '@abp/ng.theme.shared/extensions'; |
|||
import { IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_USERS_ENTITY_PROPS = EntityProp.createMany<IdentityUserDto>([ |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'userName', |
|||
displayName: 'AbpIdentity::UserName', |
|||
sortable: true, |
|||
columnWidth: 250, |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'email', |
|||
displayName: 'AbpIdentity::EmailAddress', |
|||
sortable: true, |
|||
columnWidth: 250, |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'phoneNumber', |
|||
displayName: 'AbpIdentity::PhoneNumber', |
|||
sortable: true, |
|||
columnWidth: 250, |
|||
}, |
|||
]); |
|||
@ -0,0 +1,61 @@ |
|||
import { getPasswordValidators } from '@abp/ng.theme.shared'; |
|||
import { ePropType, FormProp } from '@abp/ng.theme.shared/extensions'; |
|||
import { Validators } from '@angular/forms'; |
|||
import { IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_USERS_CREATE_FORM_PROPS = FormProp.createMany<IdentityUserDto>([ |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'userName', |
|||
displayName: 'AbpIdentity::UserName', |
|||
id: 'user-name', |
|||
validators: () => [Validators.required, Validators.maxLength(256)], |
|||
}, |
|||
{ |
|||
type: ePropType.Password, |
|||
name: 'password', |
|||
displayName: 'AbpIdentity::Password', |
|||
id: 'password', |
|||
autocomplete: 'new-password', |
|||
validators: data => [Validators.required, ...getPasswordValidators({ get: data.getInjected })], |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'name', |
|||
displayName: 'AbpIdentity::DisplayName:Name', |
|||
id: 'name', |
|||
validators: () => [Validators.maxLength(64)], |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'surname', |
|||
displayName: 'AbpIdentity::DisplayName:Surname', |
|||
id: 'surname', |
|||
validators: () => [Validators.maxLength(64)], |
|||
}, |
|||
{ |
|||
type: ePropType.Email, |
|||
name: 'email', |
|||
displayName: 'AbpIdentity::EmailAddress', |
|||
id: 'email', |
|||
validators: () => [Validators.required, Validators.maxLength(256), Validators.email], |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'phoneNumber', |
|||
displayName: 'AbpIdentity::PhoneNumber', |
|||
id: 'phone-number', |
|||
validators: () => [Validators.maxLength(16)], |
|||
}, |
|||
{ |
|||
type: ePropType.Boolean, |
|||
name: 'lockoutEnabled', |
|||
displayName: 'AbpIdentity::DisplayName:LockoutEnabled', |
|||
id: 'lockout-checkbox', |
|||
defaultValue: true, |
|||
}, |
|||
]); |
|||
|
|||
export const DEFAULT_USERS_EDIT_FORM_PROPS = DEFAULT_USERS_CREATE_FORM_PROPS.filter( |
|||
prop => prop.name !== 'password', |
|||
); |
|||
@ -0,0 +1,15 @@ |
|||
import { ToolbarAction } from '@abp/ng.theme.shared/extensions'; |
|||
import { UsersComponent } from '../components/users/users.component'; |
|||
import { IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_USERS_TOOLBAR_ACTIONS = ToolbarAction.createMany<IdentityUserDto[]>([ |
|||
{ |
|||
text: 'AbpIdentity::NewUser', |
|||
action: data => { |
|||
const component = data.getInjected(UsersComponent); |
|||
component.add(); |
|||
}, |
|||
permission: 'AbpIdentity.Users.Create', |
|||
icon: 'fa fa-plus', |
|||
}, |
|||
]); |
|||
@ -0,0 +1,4 @@ |
|||
export const enum eIdentityComponents { |
|||
Roles = 'Identity.RolesComponent', |
|||
Users = 'Identity.UsersComponent', |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './components'; |
|||
@ -0,0 +1,91 @@ |
|||
import { ConfigStateService } from '@abp/ng.core'; |
|||
import { |
|||
ExtensionsService, |
|||
getObjectExtensionEntitiesFromStore, |
|||
mapEntitiesToContributors, |
|||
mergeWithDefaultActions, |
|||
mergeWithDefaultProps, |
|||
} from '@abp/ng.theme.shared/extensions'; |
|||
import { Injectable, Injector } from '@angular/core'; |
|||
import { CanActivate } from '@angular/router'; |
|||
import { Observable } from 'rxjs'; |
|||
import { map, mapTo, tap } from 'rxjs/operators'; |
|||
import { eIdentityComponents } from '../enums/components'; |
|||
import { |
|||
IdentityCreateFormPropContributors, |
|||
IdentityEditFormPropContributors, |
|||
IdentityEntityActionContributors, |
|||
IdentityEntityPropContributors, |
|||
IdentityToolbarActionContributors, |
|||
} from '../models/config-options'; |
|||
import { |
|||
DEFAULT_IDENTITY_CREATE_FORM_PROPS, |
|||
DEFAULT_IDENTITY_EDIT_FORM_PROPS, |
|||
DEFAULT_IDENTITY_ENTITY_ACTIONS, |
|||
DEFAULT_IDENTITY_ENTITY_PROPS, |
|||
DEFAULT_IDENTITY_TOOLBAR_ACTIONS, |
|||
IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS, |
|||
IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS, |
|||
IDENTITY_ENTITY_ACTION_CONTRIBUTORS, |
|||
IDENTITY_ENTITY_PROP_CONTRIBUTORS, |
|||
IDENTITY_TOOLBAR_ACTION_CONTRIBUTORS, |
|||
} from '../tokens/extensions.token'; |
|||
|
|||
@Injectable() |
|||
export class IdentityExtensionsGuard implements CanActivate { |
|||
constructor(private injector: Injector) {} |
|||
|
|||
canActivate(): Observable<boolean> { |
|||
const extensions: ExtensionsService = this.injector.get(ExtensionsService); |
|||
const actionContributors: IdentityEntityActionContributors = |
|||
this.injector.get(IDENTITY_ENTITY_ACTION_CONTRIBUTORS, null) || {}; |
|||
const toolbarContributors: IdentityToolbarActionContributors = |
|||
this.injector.get(IDENTITY_TOOLBAR_ACTION_CONTRIBUTORS, null) || {}; |
|||
const propContributors: IdentityEntityPropContributors = |
|||
this.injector.get(IDENTITY_ENTITY_PROP_CONTRIBUTORS, null) || {}; |
|||
const createFormContributors: IdentityCreateFormPropContributors = |
|||
this.injector.get(IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS, null) || {}; |
|||
const editFormContributors: IdentityEditFormPropContributors = |
|||
this.injector.get(IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS, null) || {}; |
|||
|
|||
const configState = this.injector.get(ConfigStateService); |
|||
return getObjectExtensionEntitiesFromStore(configState, 'Identity').pipe( |
|||
map(entities => ({ |
|||
[eIdentityComponents.Roles]: entities.Role, |
|||
[eIdentityComponents.Users]: entities.User, |
|||
})), |
|||
mapEntitiesToContributors(configState, 'AbpIdentity'), |
|||
tap(objectExtensionContributors => { |
|||
mergeWithDefaultActions( |
|||
extensions.entityActions, |
|||
DEFAULT_IDENTITY_ENTITY_ACTIONS, |
|||
actionContributors, |
|||
); |
|||
mergeWithDefaultActions( |
|||
extensions.toolbarActions, |
|||
DEFAULT_IDENTITY_TOOLBAR_ACTIONS, |
|||
toolbarContributors, |
|||
); |
|||
mergeWithDefaultProps( |
|||
extensions.entityProps, |
|||
DEFAULT_IDENTITY_ENTITY_PROPS, |
|||
objectExtensionContributors.prop, |
|||
propContributors, |
|||
); |
|||
mergeWithDefaultProps( |
|||
extensions.createFormProps, |
|||
DEFAULT_IDENTITY_CREATE_FORM_PROPS, |
|||
objectExtensionContributors.createForm, |
|||
createFormContributors, |
|||
); |
|||
mergeWithDefaultProps( |
|||
extensions.editFormProps, |
|||
DEFAULT_IDENTITY_EDIT_FORM_PROPS, |
|||
objectExtensionContributors.editForm, |
|||
editFormContributors, |
|||
); |
|||
}), |
|||
mapTo(true), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './extensions.guard'; |
|||
@ -0,0 +1,52 @@ |
|||
import { |
|||
AuthGuard, |
|||
DynamicLayoutComponent, |
|||
PermissionGuard, |
|||
ReplaceableComponents, |
|||
ReplaceableRouteContainerComponent, |
|||
} from '@abp/ng.core'; |
|||
import { NgModule } from '@angular/core'; |
|||
import { RouterModule, Routes } from '@angular/router'; |
|||
import { RolesComponent } from './components/roles/roles.component'; |
|||
import { UsersComponent } from './components/users/users.component'; |
|||
import { eIdentityComponents } from './enums/components'; |
|||
import { IdentityExtensionsGuard } from './guards/extensions.guard'; |
|||
|
|||
const routes: Routes = [ |
|||
{ path: '', redirectTo: 'roles', pathMatch: 'full' }, |
|||
{ |
|||
path: '', |
|||
component: DynamicLayoutComponent, |
|||
canActivate: [AuthGuard, PermissionGuard, IdentityExtensionsGuard], |
|||
children: [ |
|||
{ |
|||
path: 'roles', |
|||
component: ReplaceableRouteContainerComponent, |
|||
data: { |
|||
requiredPolicy: 'AbpIdentity.Roles', |
|||
replaceableComponent: { |
|||
key: eIdentityComponents.Roles, |
|||
defaultComponent: RolesComponent, |
|||
} as ReplaceableComponents.RouteData<RolesComponent>, |
|||
}, |
|||
}, |
|||
{ |
|||
path: 'users', |
|||
component: ReplaceableRouteContainerComponent, |
|||
data: { |
|||
requiredPolicy: 'AbpIdentity.Users', |
|||
replaceableComponent: { |
|||
key: eIdentityComponents.Users, |
|||
defaultComponent: UsersComponent, |
|||
} as ReplaceableComponents.RouteData<UsersComponent>, |
|||
}, |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
|
|||
@NgModule({ |
|||
imports: [RouterModule.forChild(routes)], |
|||
exports: [RouterModule], |
|||
}) |
|||
export class IdentityRoutingModule {} |
|||
@ -0,0 +1,71 @@ |
|||
import { CoreModule, LazyModuleFactory } from '@abp/ng.core'; |
|||
import { PermissionManagementModule } from '@abp/ng.permission-management'; |
|||
import { ThemeSharedModule } from '@abp/ng.theme.shared'; |
|||
import { UiExtensionsModule } from '@abp/ng.theme.shared/extensions'; |
|||
import { ModuleWithProviders, NgModule, NgModuleFactory } from '@angular/core'; |
|||
import { NgbDropdownModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; |
|||
import { NgxValidateCoreModule } from '@ngx-validate/core'; |
|||
import { NgxsModule } from '@ngxs/store'; |
|||
import { RolesComponent } from './components/roles/roles.component'; |
|||
import { UsersComponent } from './components/users/users.component'; |
|||
import { IdentityExtensionsGuard } from './guards/extensions.guard'; |
|||
import { IdentityRoutingModule } from './identity-routing.module'; |
|||
import { IdentityConfigOptions } from './models/config-options'; |
|||
import { IdentityState } from './states/identity.state'; |
|||
import { |
|||
IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS, |
|||
IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS, |
|||
IDENTITY_ENTITY_ACTION_CONTRIBUTORS, |
|||
IDENTITY_ENTITY_PROP_CONTRIBUTORS, |
|||
IDENTITY_TOOLBAR_ACTION_CONTRIBUTORS, |
|||
} from './tokens/extensions.token'; |
|||
|
|||
@NgModule({ |
|||
declarations: [RolesComponent, UsersComponent], |
|||
exports: [RolesComponent, UsersComponent], |
|||
imports: [ |
|||
NgxsModule.forFeature([IdentityState]), |
|||
CoreModule, |
|||
IdentityRoutingModule, |
|||
NgbNavModule, |
|||
ThemeSharedModule, |
|||
UiExtensionsModule, |
|||
NgbDropdownModule, |
|||
PermissionManagementModule, |
|||
NgxValidateCoreModule, |
|||
], |
|||
}) |
|||
export class IdentityModule { |
|||
static forChild(options: IdentityConfigOptions = {}): ModuleWithProviders<IdentityModule> { |
|||
return { |
|||
ngModule: IdentityModule, |
|||
providers: [ |
|||
{ |
|||
provide: IDENTITY_ENTITY_ACTION_CONTRIBUTORS, |
|||
useValue: options.entityActionContributors, |
|||
}, |
|||
{ |
|||
provide: IDENTITY_TOOLBAR_ACTION_CONTRIBUTORS, |
|||
useValue: options.toolbarActionContributors, |
|||
}, |
|||
{ |
|||
provide: IDENTITY_ENTITY_PROP_CONTRIBUTORS, |
|||
useValue: options.entityPropContributors, |
|||
}, |
|||
{ |
|||
provide: IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS, |
|||
useValue: options.createFormPropContributors, |
|||
}, |
|||
{ |
|||
provide: IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS, |
|||
useValue: options.editFormPropContributors, |
|||
}, |
|||
IdentityExtensionsGuard, |
|||
], |
|||
}; |
|||
} |
|||
|
|||
static forLazy(options: IdentityConfigOptions = {}): NgModuleFactory<IdentityModule> { |
|||
return new LazyModuleFactory(IdentityModule.forChild(options)); |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
import { |
|||
CreateFormPropContributorCallback, |
|||
EditFormPropContributorCallback, |
|||
EntityActionContributorCallback, |
|||
EntityPropContributorCallback, |
|||
ToolbarActionContributorCallback, |
|||
} from '@abp/ng.theme.shared/extensions'; |
|||
import { eIdentityComponents } from '../enums/components'; |
|||
import { IdentityRoleDto, IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export type IdentityEntityActionContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: EntityActionContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: EntityActionContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
|
|||
export type IdentityToolbarActionContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: ToolbarActionContributorCallback<IdentityRoleDto[]>[]; |
|||
[eIdentityComponents.Users]: ToolbarActionContributorCallback<IdentityUserDto[]>[]; |
|||
}>; |
|||
|
|||
export type IdentityEntityPropContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: EntityPropContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: EntityPropContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
|
|||
export type IdentityCreateFormPropContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: CreateFormPropContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: CreateFormPropContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
|
|||
export type IdentityEditFormPropContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: EditFormPropContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: EditFormPropContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
|
|||
export interface IdentityConfigOptions { |
|||
entityActionContributors?: IdentityEntityActionContributors; |
|||
toolbarActionContributors?: IdentityToolbarActionContributors; |
|||
entityPropContributors?: IdentityEntityPropContributors; |
|||
createFormPropContributors?: IdentityCreateFormPropContributors; |
|||
editFormPropContributors?: IdentityEditFormPropContributors; |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
import { PagedResultDto } from '@abp/ng.core'; |
|||
import { IdentityRoleDto, IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export namespace Identity { |
|||
export interface State { |
|||
roles: PagedResultDto<IdentityRoleDto>; |
|||
users: PagedResultDto<IdentityUserDto>; |
|||
selectedRole: IdentityRoleDto; |
|||
selectedUser: IdentityUserDto; |
|||
selectedUserRoles: IdentityRoleDto[]; |
|||
} |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
export * from './config-options'; |
|||
export * from './identity'; |
|||
File diff suppressed because it is too large
@ -0,0 +1,58 @@ |
|||
import type { ListResultDto, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core'; |
|||
import { RestService } from '@abp/ng.core'; |
|||
import { Injectable } from '@angular/core'; |
|||
import type { IdentityRoleCreateDto, IdentityRoleDto, IdentityRoleUpdateDto } from './models'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class IdentityRoleService { |
|||
apiName = 'AbpIdentity'; |
|||
|
|||
create = (input: IdentityRoleCreateDto) => |
|||
this.restService.request<any, IdentityRoleDto>({ |
|||
method: 'POST', |
|||
url: '/api/identity/roles', |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
delete = (id: string) => |
|||
this.restService.request<any, void>({ |
|||
method: 'DELETE', |
|||
url: `/api/identity/roles/${id}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
get = (id: string) => |
|||
this.restService.request<any, IdentityRoleDto>({ |
|||
method: 'GET', |
|||
url: `/api/identity/roles/${id}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
getAllList = () => |
|||
this.restService.request<any, ListResultDto<IdentityRoleDto>>({ |
|||
method: 'GET', |
|||
url: '/api/identity/roles/all', |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
getList = (input: PagedAndSortedResultRequestDto) => |
|||
this.restService.request<any, PagedResultDto<IdentityRoleDto>>({ |
|||
method: 'GET', |
|||
url: '/api/identity/roles', |
|||
params: { sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
update = (id: string, input: IdentityRoleUpdateDto) => |
|||
this.restService.request<any, IdentityRoleDto>({ |
|||
method: 'PUT', |
|||
url: `/api/identity/roles/${id}`, |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
constructor(private restService: RestService) {} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
import type { UserLookupCountInputDto, UserLookupSearchInputDto } from './models'; |
|||
import { RestService } from '@abp/ng.core'; |
|||
import type { ListResultDto } from '@abp/ng.core'; |
|||
import { Injectable } from '@angular/core'; |
|||
import type { UserData } from '../users/models'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class IdentityUserLookupService { |
|||
apiName = 'AbpIdentity'; |
|||
|
|||
findById = (id: string) => |
|||
this.restService.request<any, UserData>({ |
|||
method: 'GET', |
|||
url: `/api/identity/users/lookup/${id}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
findByUserName = (userName: string) => |
|||
this.restService.request<any, UserData>({ |
|||
method: 'GET', |
|||
url: `/api/identity/users/lookup/by-username/${userName}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
getCount = (input: UserLookupCountInputDto) => |
|||
this.restService.request<any, number>({ |
|||
method: 'GET', |
|||
url: '/api/identity/users/lookup/count', |
|||
params: { filter: input.filter }, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
search = (input: UserLookupSearchInputDto) => |
|||
this.restService.request<any, ListResultDto<UserData>>({ |
|||
method: 'GET', |
|||
url: '/api/identity/users/lookup/search', |
|||
params: { filter: input.filter, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
constructor(private restService: RestService) {} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
import type { |
|||
GetIdentityUsersInput, |
|||
IdentityRoleDto, |
|||
IdentityUserCreateDto, |
|||
IdentityUserDto, |
|||
IdentityUserUpdateDto, |
|||
IdentityUserUpdateRolesDto } from './models'; |
|||
import { RestService } from '@abp/ng.core'; |
|||
import type { ListResultDto, PagedResultDto } from '@abp/ng.core'; |
|||
import { Injectable } from '@angular/core'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class IdentityUserService { |
|||
apiName = 'AbpIdentity'; |
|||
|
|||
create = (input: IdentityUserCreateDto) => |
|||
this.restService.request<any, IdentityUserDto>({ |
|||
method: 'POST', |
|||
url: '/api/identity/users', |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
delete = (id: string) => |
|||
this.restService.request<any, void>({ |
|||
method: 'DELETE', |
|||
url: `/api/identity/users/${id}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
findByEmail = (email: string) => |
|||
this.restService.request<any, IdentityUserDto>({ |
|||
method: 'GET', |
|||
url: `/api/identity/users/by-email/${email}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
findByUsername = (username: string) => |
|||
this.restService.request<any, IdentityUserDto>({ |
|||
method: 'GET', |
|||
url: '/api/identity/users/by-username/{userName}', |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
get = (id: string) => |
|||
this.restService.request<any, IdentityUserDto>({ |
|||
method: 'GET', |
|||
url: `/api/identity/users/${id}`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
getAssignableRoles = () => |
|||
this.restService.request<any, ListResultDto<IdentityRoleDto>>({ |
|||
method: 'GET', |
|||
url: '/api/identity/users/assignable-roles', |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
getList = (input: GetIdentityUsersInput) => |
|||
this.restService.request<any, PagedResultDto<IdentityUserDto>>({ |
|||
method: 'GET', |
|||
url: '/api/identity/users', |
|||
params: { filter: input.filter, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
getRoles = (id: string) => |
|||
this.restService.request<any, ListResultDto<IdentityRoleDto>>({ |
|||
method: 'GET', |
|||
url: `/api/identity/users/${id}/roles`, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
update = (id: string, input: IdentityUserUpdateDto) => |
|||
this.restService.request<any, IdentityUserDto>({ |
|||
method: 'PUT', |
|||
url: `/api/identity/users/${id}`, |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
updateRoles = (id: string, input: IdentityUserUpdateRolesDto) => |
|||
this.restService.request<any, void>({ |
|||
method: 'PUT', |
|||
url: `/api/identity/users/${id}/roles`, |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
constructor(private restService: RestService) {} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
export * from './identity-role.service'; |
|||
export * from './identity-user-lookup.service'; |
|||
export * from './identity-user.service'; |
|||
export * from './models'; |
|||
export * from './profile.service'; |
|||
@ -0,0 +1,95 @@ |
|||
import type { ExtensibleEntityDto, ExtensibleFullAuditedEntityDto, ExtensibleObject, PagedAndSortedResultRequestDto } from '@abp/ng.core'; |
|||
|
|||
export interface ChangePasswordInput { |
|||
currentPassword: string; |
|||
newPassword: string; |
|||
} |
|||
|
|||
export interface GetIdentityUsersInput extends PagedAndSortedResultRequestDto { |
|||
filter: string; |
|||
} |
|||
|
|||
// tslint:disable-next-line: no-empty-interface
|
|||
export interface IdentityRoleCreateDto extends IdentityRoleCreateOrUpdateDtoBase { |
|||
} |
|||
|
|||
export interface IdentityRoleCreateOrUpdateDtoBase extends ExtensibleObject { |
|||
name: string; |
|||
isDefault: boolean; |
|||
isPublic: boolean; |
|||
} |
|||
|
|||
export interface IdentityRoleDto extends ExtensibleEntityDto<string> { |
|||
name: string; |
|||
isDefault: boolean; |
|||
isStatic: boolean; |
|||
isPublic: boolean; |
|||
concurrencyStamp: string; |
|||
} |
|||
|
|||
export interface IdentityRoleUpdateDto extends IdentityRoleCreateOrUpdateDtoBase { |
|||
concurrencyStamp: string; |
|||
} |
|||
|
|||
export interface IdentityUserCreateDto extends IdentityUserCreateOrUpdateDtoBase { |
|||
password: string; |
|||
} |
|||
|
|||
export interface IdentityUserCreateOrUpdateDtoBase extends ExtensibleObject { |
|||
userName: string; |
|||
name: string; |
|||
surname: string; |
|||
email: string; |
|||
phoneNumber: string; |
|||
lockoutEnabled: boolean; |
|||
roleNames: string[]; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
|
|||
export interface IdentityUserUpdateDto extends IdentityUserCreateOrUpdateDtoBase { |
|||
password: string; |
|||
concurrencyStamp: string; |
|||
} |
|||
|
|||
export interface IdentityUserUpdateRolesDto { |
|||
roleNames: string[]; |
|||
} |
|||
|
|||
export interface ProfileDto extends ExtensibleObject { |
|||
userName: string; |
|||
email: string; |
|||
name: string; |
|||
surname: string; |
|||
phoneNumber: string; |
|||
isExternal: boolean; |
|||
hasPassword: boolean; |
|||
} |
|||
|
|||
export interface UpdateProfileDto extends ExtensibleObject { |
|||
userName: string; |
|||
email: string; |
|||
name: string; |
|||
surname: string; |
|||
phoneNumber: string; |
|||
} |
|||
|
|||
export interface UserLookupCountInputDto { |
|||
filter: string; |
|||
} |
|||
|
|||
export interface UserLookupSearchInputDto extends PagedAndSortedResultRequestDto { |
|||
filter: string; |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
import type { ChangePasswordInput, ProfileDto, UpdateProfileDto } from './models'; |
|||
import { RestService } from '@abp/ng.core'; |
|||
import { Injectable } from '@angular/core'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class ProfileService { |
|||
apiName = 'AbpIdentity'; |
|||
|
|||
changePassword = (input: ChangePasswordInput) => |
|||
this.restService.request<any, void>({ |
|||
method: 'POST', |
|||
url: '/api/identity/my-profile/change-password', |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
get = () => |
|||
this.restService.request<any, ProfileDto>({ |
|||
method: 'GET', |
|||
url: '/api/identity/my-profile', |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
update = (input: UpdateProfileDto) => |
|||
this.restService.request<any, ProfileDto>({ |
|||
method: 'PUT', |
|||
url: '/api/identity/my-profile', |
|||
body: input, |
|||
}, |
|||
{ apiName: this.apiName }); |
|||
|
|||
constructor(private restService: RestService) {} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './models'; |
|||
@ -0,0 +1,12 @@ |
|||
|
|||
export interface UserData { |
|||
id: string; |
|||
tenantId?: string; |
|||
userName: string; |
|||
name: string; |
|||
surname: string; |
|||
email: string; |
|||
emailConfirmed: boolean; |
|||
phoneNumber: string; |
|||
phoneNumberConfirmed: boolean; |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
import { ABP } from '@abp/ng.core'; |
|||
import { Injectable } from '@angular/core'; |
|||
import { Store } from '@ngxs/store'; |
|||
import { |
|||
CreateRole, |
|||
CreateUser, |
|||
DeleteRole, |
|||
DeleteUser, |
|||
GetRoleById, |
|||
GetRoles, |
|||
GetUserById, |
|||
GetUsers, |
|||
UpdateRole, |
|||
UpdateUser, |
|||
GetUserRoles, |
|||
} from '../actions/identity.actions'; |
|||
import { Identity } from '../models/identity'; |
|||
import { IdentityState } from '../states/identity.state'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class IdentityStateService { |
|||
constructor(private store: Store) {} |
|||
|
|||
getRoles() { |
|||
return this.store.selectSnapshot(IdentityState.getRoles); |
|||
} |
|||
getRolesTotalCount() { |
|||
return this.store.selectSnapshot(IdentityState.getRolesTotalCount); |
|||
} |
|||
getUsers() { |
|||
return this.store.selectSnapshot(IdentityState.getUsers); |
|||
} |
|||
getUsersTotalCount() { |
|||
return this.store.selectSnapshot(IdentityState.getUsersTotalCount); |
|||
} |
|||
|
|||
dispatchGetRoles(...args: ConstructorParameters<typeof GetRoles>) { |
|||
return this.store.dispatch(new GetRoles(...args)); |
|||
} |
|||
|
|||
dispatchGetRoleById(...args: ConstructorParameters<typeof GetRoleById>) { |
|||
return this.store.dispatch(new GetRoleById(...args)); |
|||
} |
|||
|
|||
dispatchDeleteRole(...args: ConstructorParameters<typeof DeleteRole>) { |
|||
return this.store.dispatch(new DeleteRole(...args)); |
|||
} |
|||
|
|||
dispatchCreateRole(...args: ConstructorParameters<typeof CreateRole>) { |
|||
return this.store.dispatch(new CreateRole(...args)); |
|||
} |
|||
|
|||
dispatchUpdateRole(...args: ConstructorParameters<typeof UpdateRole>) { |
|||
return this.store.dispatch(new UpdateRole(...args)); |
|||
} |
|||
|
|||
dispatchGetUsers(...args: ConstructorParameters<typeof GetUsers>) { |
|||
return this.store.dispatch(new GetUsers(...args)); |
|||
} |
|||
|
|||
dispatchGetUserById(...args: ConstructorParameters<typeof GetUserById>) { |
|||
return this.store.dispatch(new GetUserById(...args)); |
|||
} |
|||
|
|||
dispatchDeleteUser(...args: ConstructorParameters<typeof DeleteUser>) { |
|||
return this.store.dispatch(new DeleteUser(...args)); |
|||
} |
|||
|
|||
dispatchCreateUser(...args: ConstructorParameters<typeof CreateUser>) { |
|||
return this.store.dispatch(new CreateUser(...args)); |
|||
} |
|||
|
|||
dispatchUpdateUser(...args: ConstructorParameters<typeof UpdateUser>) { |
|||
return this.store.dispatch(new UpdateUser(...args)); |
|||
} |
|||
|
|||
dispatchGetUserRoles(...args: ConstructorParameters<typeof GetUserRoles>) { |
|||
return this.store.dispatch(new GetUserRoles(...args)); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './identity-state.service'; |
|||
@ -0,0 +1,138 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import { Action, Selector, State, StateContext } from '@ngxs/store'; |
|||
import { pluck, tap } from 'rxjs/operators'; |
|||
import { |
|||
CreateRole, |
|||
CreateUser, |
|||
DeleteRole, |
|||
DeleteUser, |
|||
GetRoleById, |
|||
GetRoles, |
|||
GetUserById, |
|||
GetUserRoles, |
|||
GetUsers, |
|||
UpdateRole, |
|||
UpdateUser, |
|||
} from '../actions/identity.actions'; |
|||
import { Identity } from '../models/identity'; |
|||
import { IdentityRoleService } from '../proxy/identity/identity-role.service'; |
|||
import { IdentityUserService } from '../proxy/identity/identity-user.service'; |
|||
import { IdentityRoleDto, IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
@State<Identity.State>({ |
|||
name: 'IdentityState', |
|||
defaults: { roles: {}, selectedRole: {}, users: {}, selectedUser: {} } as Identity.State, |
|||
}) |
|||
@Injectable() |
|||
export class IdentityState { |
|||
@Selector() |
|||
static getRoles({ roles }: Identity.State): IdentityRoleDto[] { |
|||
return roles.items || []; |
|||
} |
|||
|
|||
@Selector() |
|||
static getRolesTotalCount({ roles }: Identity.State): number { |
|||
return roles.totalCount || 0; |
|||
} |
|||
|
|||
@Selector() |
|||
static getUsers({ users }: Identity.State): IdentityUserDto[] { |
|||
return users.items || []; |
|||
} |
|||
|
|||
@Selector() |
|||
static getUsersTotalCount({ users }: Identity.State): number { |
|||
return users.totalCount || 0; |
|||
} |
|||
|
|||
constructor( |
|||
private identityUserService: IdentityUserService, |
|||
private identityRoleService: IdentityRoleService, |
|||
) {} |
|||
|
|||
@Action(GetRoles) |
|||
getRoles({ patchState }: StateContext<Identity.State>, { payload }: GetRoles) { |
|||
return this.identityRoleService.getList(payload).pipe( |
|||
tap(roles => |
|||
patchState({ |
|||
roles, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
|
|||
@Action(GetRoleById) |
|||
getRole({ patchState }: StateContext<Identity.State>, { payload }: GetRoleById) { |
|||
return this.identityRoleService.get(payload).pipe( |
|||
tap(selectedRole => |
|||
patchState({ |
|||
selectedRole, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
|
|||
@Action(DeleteRole) |
|||
deleteRole(_, { payload }: GetRoleById) { |
|||
return this.identityRoleService.delete(payload); |
|||
} |
|||
|
|||
@Action(CreateRole) |
|||
addRole(_, { payload }: CreateRole) { |
|||
return this.identityRoleService.create(payload); |
|||
} |
|||
|
|||
@Action(UpdateRole) |
|||
updateRole({ getState }: StateContext<Identity.State>, { payload }: UpdateRole) { |
|||
return this.identityRoleService.update(payload.id, { ...getState().selectedRole, ...payload }); |
|||
} |
|||
|
|||
@Action(GetUsers) |
|||
getUsers({ patchState }: StateContext<Identity.State>, { payload }: GetUsers) { |
|||
return this.identityUserService.getList(payload).pipe( |
|||
tap(users => |
|||
patchState({ |
|||
users, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
|
|||
@Action(GetUserById) |
|||
getUser({ patchState }: StateContext<Identity.State>, { payload }: GetUserById) { |
|||
return this.identityUserService.get(payload).pipe( |
|||
tap(selectedUser => |
|||
patchState({ |
|||
selectedUser, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
|
|||
@Action(DeleteUser) |
|||
deleteUser(_, { payload }: GetUserById) { |
|||
return this.identityUserService.delete(payload); |
|||
} |
|||
|
|||
@Action(CreateUser) |
|||
addUser(_, { payload }: CreateUser) { |
|||
return this.identityUserService.create(payload); |
|||
} |
|||
|
|||
@Action(UpdateUser) |
|||
updateUser({ getState }: StateContext<Identity.State>, { payload }: UpdateUser) { |
|||
return this.identityUserService.update(payload.id, { ...getState().selectedUser, ...payload }); |
|||
} |
|||
|
|||
@Action(GetUserRoles) |
|||
getUserRoles({ patchState }: StateContext<Identity.State>, { payload }: GetUserRoles) { |
|||
return this.identityUserService.getRoles(payload).pipe( |
|||
pluck('items'), |
|||
tap(selectedUserRoles => |
|||
patchState({ |
|||
selectedUserRoles, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './identity.state'; |
|||
@ -0,0 +1,58 @@ |
|||
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest'; |
|||
import { IdentityStateService } from '../services/identity-state.service'; |
|||
import { IdentityState } from '../states/identity.state'; |
|||
import { Store } from '@ngxs/store'; |
|||
import * as IdentityActions from '../actions/identity.actions'; |
|||
|
|||
describe('IdentityStateService', () => { |
|||
let service: IdentityStateService; |
|||
let spectator: SpectatorService<IdentityStateService>; |
|||
let store: SpyObject<Store>; |
|||
|
|||
const createService = createServiceFactory({ service: IdentityStateService, mocks: [Store] }); |
|||
beforeEach(() => { |
|||
spectator = createService(); |
|||
service = spectator.service; |
|||
store = spectator.inject(Store); |
|||
}); |
|||
|
|||
test('should have the all IdentityState static methods', () => { |
|||
const reg = /(?<=static )(.*)(?=\()/gm; |
|||
IdentityState.toString() |
|||
.match(reg) |
|||
.forEach(fnName => { |
|||
expect(service[fnName]).toBeTruthy(); |
|||
|
|||
const spy = jest.spyOn(store, 'selectSnapshot'); |
|||
spy.mockClear(); |
|||
|
|||
const isDynamicSelector = IdentityState[fnName].name !== 'memoized'; |
|||
|
|||
if (isDynamicSelector) { |
|||
IdentityState[fnName] = jest.fn((...args) => args); |
|||
service[fnName]('test', 0, {}); |
|||
expect(IdentityState[fnName]).toHaveBeenCalledWith('test', 0, {}); |
|||
} else { |
|||
service[fnName](); |
|||
expect(spy).toHaveBeenCalledWith(IdentityState[fnName]); |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
test('should have a dispatch method for every IdentityState action', () => { |
|||
const reg = /(?<=dispatch)(\w+)(?=\()/gm; |
|||
IdentityStateService.toString() |
|||
.match(reg) |
|||
.forEach(fnName => { |
|||
expect(IdentityActions[fnName]).toBeTruthy(); |
|||
|
|||
const spy = jest.spyOn(store, 'dispatch'); |
|||
spy.mockClear(); |
|||
|
|||
const params = Array.from(new Array(IdentityActions[fnName].length)); |
|||
|
|||
service[`dispatch${fnName}`](...params); |
|||
expect(spy).toHaveBeenCalledWith(new IdentityActions[fnName](...params)); |
|||
}); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,91 @@ |
|||
import { |
|||
CreateFormPropContributorCallback, |
|||
EditFormPropContributorCallback, |
|||
EntityActionContributorCallback, |
|||
EntityPropContributorCallback, |
|||
ToolbarActionContributorCallback, |
|||
} from '@abp/ng.theme.shared/extensions'; |
|||
import { InjectionToken } from '@angular/core'; |
|||
import { DEFAULT_ROLES_ENTITY_ACTIONS } from '../defaults/default-roles-entity-actions'; |
|||
import { DEFAULT_ROLES_ENTITY_PROPS } from '../defaults/default-roles-entity-props'; |
|||
import { |
|||
DEFAULT_ROLES_CREATE_FORM_PROPS, |
|||
DEFAULT_ROLES_EDIT_FORM_PROPS, |
|||
} from '../defaults/default-roles-form-props'; |
|||
import { DEFAULT_ROLES_TOOLBAR_ACTIONS } from '../defaults/default-roles-toolbar-actions'; |
|||
import { DEFAULT_USERS_ENTITY_ACTIONS } from '../defaults/default-users-entity-actions'; |
|||
import { DEFAULT_USERS_ENTITY_PROPS } from '../defaults/default-users-entity-props'; |
|||
import { |
|||
DEFAULT_USERS_CREATE_FORM_PROPS, |
|||
DEFAULT_USERS_EDIT_FORM_PROPS, |
|||
} from '../defaults/default-users-form-props'; |
|||
import { DEFAULT_USERS_TOOLBAR_ACTIONS } from '../defaults/default-users-toolbar-actions'; |
|||
import { eIdentityComponents } from '../enums/components'; |
|||
import { IdentityRoleDto, IdentityUserDto } from '../proxy/identity/models'; |
|||
|
|||
export const DEFAULT_IDENTITY_ENTITY_ACTIONS = { |
|||
[eIdentityComponents.Roles]: DEFAULT_ROLES_ENTITY_ACTIONS, |
|||
[eIdentityComponents.Users]: DEFAULT_USERS_ENTITY_ACTIONS, |
|||
}; |
|||
|
|||
export const DEFAULT_IDENTITY_TOOLBAR_ACTIONS = { |
|||
[eIdentityComponents.Roles]: DEFAULT_ROLES_TOOLBAR_ACTIONS, |
|||
[eIdentityComponents.Users]: DEFAULT_USERS_TOOLBAR_ACTIONS, |
|||
}; |
|||
|
|||
export const DEFAULT_IDENTITY_ENTITY_PROPS = { |
|||
[eIdentityComponents.Roles]: DEFAULT_ROLES_ENTITY_PROPS, |
|||
[eIdentityComponents.Users]: DEFAULT_USERS_ENTITY_PROPS, |
|||
}; |
|||
|
|||
export const DEFAULT_IDENTITY_CREATE_FORM_PROPS = { |
|||
[eIdentityComponents.Roles]: DEFAULT_ROLES_CREATE_FORM_PROPS, |
|||
[eIdentityComponents.Users]: DEFAULT_USERS_CREATE_FORM_PROPS, |
|||
}; |
|||
|
|||
export const DEFAULT_IDENTITY_EDIT_FORM_PROPS = { |
|||
[eIdentityComponents.Roles]: DEFAULT_ROLES_EDIT_FORM_PROPS, |
|||
[eIdentityComponents.Users]: DEFAULT_USERS_EDIT_FORM_PROPS, |
|||
}; |
|||
|
|||
export const IDENTITY_ENTITY_ACTION_CONTRIBUTORS = new InjectionToken<EntityActionContributors>( |
|||
'IDENTITY_ENTITY_ACTION_CONTRIBUTORS', |
|||
); |
|||
|
|||
export const IDENTITY_TOOLBAR_ACTION_CONTRIBUTORS = new InjectionToken<ToolbarActionContributors>( |
|||
'IDENTITY_TOOLBAR_ACTION_CONTRIBUTORS', |
|||
); |
|||
|
|||
export const IDENTITY_ENTITY_PROP_CONTRIBUTORS = new InjectionToken<EntityPropContributors>( |
|||
'IDENTITY_ENTITY_PROP_CONTRIBUTORS', |
|||
); |
|||
|
|||
export const IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS = new InjectionToken<CreateFormPropContributors>( |
|||
'IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS', |
|||
); |
|||
|
|||
export const IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS = new InjectionToken<EditFormPropContributors>( |
|||
'IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS', |
|||
); |
|||
|
|||
// Fix for TS4023 -> https://github.com/microsoft/TypeScript/issues/9944#issuecomment-254693497
|
|||
type EntityActionContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: EntityActionContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: EntityActionContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
type ToolbarActionContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: ToolbarActionContributorCallback<IdentityRoleDto[]>[]; |
|||
[eIdentityComponents.Users]: ToolbarActionContributorCallback<IdentityUserDto[]>[]; |
|||
}>; |
|||
type EntityPropContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: EntityPropContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: EntityPropContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
type CreateFormPropContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: CreateFormPropContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: CreateFormPropContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
type EditFormPropContributors = Partial<{ |
|||
[eIdentityComponents.Roles]: EditFormPropContributorCallback<IdentityRoleDto>[]; |
|||
[eIdentityComponents.Users]: EditFormPropContributorCallback<IdentityUserDto>[]; |
|||
}>; |
|||
@ -0,0 +1 @@ |
|||
export * from './extensions.token'; |
|||
@ -0,0 +1,11 @@ |
|||
export * from './lib/actions'; |
|||
export * from './lib/components'; |
|||
export * from './lib/enums'; |
|||
export * from './lib/guards'; |
|||
export * from './lib/identity.module'; |
|||
export * from './lib/models'; |
|||
export * from './lib/proxy/identity'; |
|||
export * from './lib/proxy/users'; |
|||
export * from './lib/services'; |
|||
export * from './lib/states'; |
|||
export * from './lib/tokens'; |
|||
@ -0,0 +1 @@ |
|||
import 'jest-preset-angular/setup-jest'; |
|||
@ -0,0 +1,13 @@ |
|||
{ |
|||
"extends": "../../tsconfig.base.json", |
|||
"files": [], |
|||
"include": [], |
|||
"references": [ |
|||
{ |
|||
"path": "./tsconfig.lib.json" |
|||
}, |
|||
{ |
|||
"path": "./tsconfig.spec.json" |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"extends": "./tsconfig.json", |
|||
"compilerOptions": { |
|||
"outDir": "../../dist/out-tsc", |
|||
"target": "es2015", |
|||
"declaration": true, |
|||
"declarationMap": true, |
|||
"inlineSources": true, |
|||
"types": [], |
|||
"lib": ["dom", "es2018"] |
|||
}, |
|||
"exclude": ["src/test-setup.ts", "**/*.spec.ts"], |
|||
"include": ["**/*.ts"] |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
/* To learn more about this file see: https://angular.io/config/tsconfig. */ |
|||
{ |
|||
"extends": "./tsconfig.lib.json", |
|||
"compilerOptions": { |
|||
"declarationMap": false |
|||
}, |
|||
"angularCompilerOptions": { |
|||
"compilationMode": "partial", |
|||
"enableIvy": false |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
{ |
|||
"extends": "./tsconfig.json", |
|||
"compilerOptions": { |
|||
"outDir": "../../dist/out-tsc", |
|||
"module": "commonjs", |
|||
"types": ["jest", "node"] |
|||
}, |
|||
"files": ["src/test-setup.ts"], |
|||
"include": ["**/*.spec.ts", "**/*.d.ts"] |
|||
} |
|||
Loading…
Reference in new issue