diff --git a/docs/en/UI/Angular/Permission-Management.md b/docs/en/UI/Angular/Permission-Management.md index b9c4649c03..a6d7d13c14 100644 --- a/docs/en/UI/Angular/Permission-Management.md +++ b/docs/en/UI/Angular/Permission-Management.md @@ -2,18 +2,20 @@ A permission is a simple policy that is granted or prohibited for a particular user, role or client. You can read more about [authorization in ABP](../../Authorization.md) document. -You can get permission of authenticated user using `getGrantedPolicy` selector of `ConfigState`. +You can get permission of authenticated user using `getGrantedPolicy` or `getGrantedPolicy$` method of `PermissionService`. + +> ConfigState's getGrantedPolicy selector and ConfigStateService's getGrantedPolicy method deprecated. Use permission service's `getGrantedPolicy$` or `getGrantedPolicy`methods instead You can get permission as boolean value: ```js -import { ConfigStateService } from '@abp/ng.core'; +import { PermissionService } from '@abp/ng.core'; export class YourComponent { - constructor(private config: ConfigStateService) {} + constructor(private permissionService: PermissionService) {} ngOnInit(): void { - const canCreate = this.config.getGrantedPolicy('AbpIdentity.Roles.Create'); + const canCreate = this.permissionService.getGrantedPolicy('AbpIdentity.Roles.Create'); } } ``` @@ -59,4 +61,4 @@ Granted Policies are stored in the `auth` property of `ConfigState`. ## What's Next? -* [Multi Tenancy](./Multi-Tenancy.md) \ No newline at end of file +* [Multi Tenancy](./Multi-Tenancy.md) diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts index 2fa8ce1bb8..a6cf4cefd8 100644 --- a/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts +++ b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts @@ -1,27 +1,26 @@ import { eLayoutType, RoutesService } from '@abp/ng.core'; -import { eThemeSharedRouteNames } from '@abp/ng.theme.shared'; import { APP_INITIALIZER } from '@angular/core'; import { eCmsKitRouteNames } from '../enums/route-names'; export const MY_PROJECT_NAME_ROUTE_PROVIDERS = [ - { - provide: APP_INITIALIZER, - useFactory: configureRoutes, - deps: [RoutesService], - multi: true, - }, + { + provide: APP_INITIALIZER, + useFactory: configureRoutes, + deps: [RoutesService], + multi: true, + }, ]; -export function configureRoutes(routes: RoutesService) { - return () => { - routes.add([ - { - path: '/cms-kit', - name: eCmsKitRouteNames.CmsKit, - iconClass: 'fas fa-book', - layout: eLayoutType.application, - order: 3, - }, - ]); - }; +export function configureRoutes(routesService: RoutesService) { + return () => { + routesService.add([ + { + path: '/cms-kit', + name: eCmsKitRouteNames.CmsKit, + iconClass: 'fas fa-book', + layout: eLayoutType.application, + order: 3, + }, + ]); + }; } diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts b/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts index a412259466..1c7138236f 100644 --- a/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts +++ b/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts @@ -10,9 +10,9 @@ export const APP_ROUTE_PROVIDER = [ }, ]; -function configureRoutes(routes: RoutesService) { +function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/', name: 'Home', diff --git a/npm/ng-packs/apps/dev-app/src/app/route.provider.ts b/npm/ng-packs/apps/dev-app/src/app/route.provider.ts index 5a14ad7ba0..73865dfd0a 100644 --- a/npm/ng-packs/apps/dev-app/src/app/route.provider.ts +++ b/npm/ng-packs/apps/dev-app/src/app/route.provider.ts @@ -5,9 +5,9 @@ export const APP_ROUTE_PROVIDER = [ { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, ]; -function configureRoutes(routes: RoutesService) { +function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/', name: '::Menu:Home', diff --git a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts index 2deb086b10..2094c4dca3 100644 --- a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts @@ -6,9 +6,9 @@ export const ACCOUNT_ROUTE_PROVIDERS = [ { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, ]; -export function configureRoutes(routes: RoutesService) { +export function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/account', name: eAccountRouteNames.Account, diff --git a/npm/ng-packs/packages/core/src/lib/directives/index.ts b/npm/ng-packs/packages/core/src/lib/directives/index.ts index 73b572f61d..a297faa14b 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/index.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/index.ts @@ -1,10 +1,10 @@ export * from './autofocus.directive'; +export * from './debounce.directive'; export * from './ellipsis.directive'; export * from './for.directive'; export * from './form-submit.directive'; export * from './init.directive'; export * from './permission.directive'; export * from './replaceable-template.directive'; -export * from './visibility.directive'; -export * from './debounce.directive'; export * from './stop-propagation.directive'; +export * from './visibility.directive'; diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index fda8b7d315..c24cd9b2d1 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -11,9 +11,8 @@ import { TemplateRef, ViewContainerRef, } from '@angular/core'; -import { Store } from '@ngxs/store'; import { Subscription } from 'rxjs'; -import { ConfigState } from '../states'; +import { PermissionService } from '../services/permission.service'; @Directive({ selector: '[abpPermission]', @@ -26,18 +25,17 @@ export class PermissionDirective implements OnInit, OnDestroy, OnChanges { constructor( private elRef: ElementRef, private renderer: Renderer2, - private store: Store, @Optional() private templateRef: TemplateRef, private vcRef: ViewContainerRef, + private permissionService: PermissionService, ) {} private check() { if (this.subscription) { this.subscription.unsubscribe(); } - - this.subscription = this.store - .select(ConfigState.getGrantedPolicy(this.condition)) + this.subscription = this.permissionService + .getGrantedPolicy$(this.condition) .subscribe(isGranted => { if (this.templateRef && isGranted) { this.vcRef.clear(); diff --git a/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts b/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts index 5c94873ee2..8b18eec798 100644 --- a/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts +++ b/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts @@ -5,26 +5,31 @@ import { Observable, of } from 'rxjs'; import { tap } from 'rxjs/operators'; import { RestOccurError } from '../actions/rest.actions'; import { RoutesService } from '../services/routes.service'; -import { ConfigState } from '../states/config.state'; import { findRoute, getRoutePath } from '../utils/route-utils'; +import { PermissionService } from '../services/permission.service'; @Injectable({ providedIn: 'root', }) export class PermissionGuard implements CanActivate { - constructor(private router: Router, private routes: RoutesService, private store: Store) {} + constructor( + private router: Router, + private routesService: RoutesService, + private store: Store, + private permissionService: PermissionService, + ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { let { requiredPolicy } = route.data || {}; if (!requiredPolicy) { - const routeFound = findRoute(this.routes, getRoutePath(this.router, state.url)); + const routeFound = findRoute(this.routesService, getRoutePath(this.router, state.url)); requiredPolicy = routeFound?.requiredPolicy; } if (!requiredPolicy) return of(true); - return this.store.select(ConfigState.getGrantedPolicy(requiredPolicy)).pipe( + return this.permissionService.getGrantedPolicy$(requiredPolicy).pipe( tap(access => { if (!access) { this.store.dispatch(new RestOccurError({ status: 403 })); diff --git a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts index ee3f49e17a..e7bbc8599d 100644 --- a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts @@ -45,6 +45,7 @@ export class ConfigStateService { return this.store.selectSnapshot(ConfigState.getSettings(...args)); } + /** @deprecated Use PermissionService's getGrantedPolicySnapshot method */ getGrantedPolicy(...args: Parameters) { return this.store.selectSnapshot(ConfigState.getGrantedPolicy(...args)); } diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index d3d13de20b..670a2fe5f1 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -7,6 +7,7 @@ export * from './lazy-load.service'; export * from './list.service'; export * from './localization.service'; export * from './multi-tenancy.service'; +export * from './permission.service'; export * from './profile-state.service'; export * from './profile.service'; export * from './replaceable-components.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/permission.service.ts b/npm/ng-packs/packages/core/src/lib/services/permission.service.ts new file mode 100644 index 0000000000..522d8b57ae --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/permission.service.ts @@ -0,0 +1,60 @@ +import { ConfigState } from '../states'; +import { Store } from '@ngxs/store'; +import { map } from 'rxjs/operators'; +import { ApplicationConfiguration } from '../models/application-configuration'; +import snq from 'snq'; +import { Injectable } from '@angular/core'; + +@Injectable({ providedIn: 'root' }) +export class PermissionService { + constructor(private store: Store) {} + + getGrantedPolicy$(key: string) { + return this.getStream().pipe(map(policies => this.isPolicyGranted(key, policies))); + } + + getGrantedPolicy(key: string) { + const policies = this.getSnapshot(); + return this.isPolicyGranted(key, policies); + } + + private isPolicyGranted(key: string, policies: ApplicationConfiguration.Policy) { + if (!key) return true; + + const orRegexp = /\|\|/g; + const andRegexp = /&&/g; + + // TODO: Allow combination of ANDs & ORs + if (orRegexp.test(key)) { + const keys = key.split('||').filter(Boolean); + + if (keys.length < 2) return false; + + return keys.some(k => this.getPolicy(k.trim(), policies)); + } else if (andRegexp.test(key)) { + const keys = key.split('&&').filter(Boolean); + + if (keys.length < 2) return false; + + return keys.every(k => this.getPolicy(k.trim(), policies)); + } + + return this.getPolicy(key, policies); + } + + private getStream() { + return this.store.select(ConfigState).pipe(map(this.mapToPolicies)); + } + + private getSnapshot() { + return this.mapToPolicies(this.store.selectSnapshot(ConfigState)); + } + + private mapToPolicies(applicationConfiguration: ApplicationConfiguration.Response) { + return snq(() => applicationConfiguration.auth.grantedPolicies); + } + + private getPolicy(policy: string, policies: ApplicationConfiguration.Policy) { + return snq(() => policies[policy], false); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index c19628760c..3ce32401d2 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -1,11 +1,11 @@ -import { Injectable, OnDestroy } from '@angular/core'; -import { Actions, ofActionSuccessful, Store } from '@ngxs/store'; +import { Injectable, Injector, OnDestroy } from '@angular/core'; +import { Actions, ofActionSuccessful } from '@ngxs/store'; import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { GetAppConfiguration } from '../actions/config.actions'; import { ABP } from '../models/common'; -import { ConfigState } from '../states/config.state'; import { pushValueTo } from '../utils/array-utils'; import { BaseTreeNode, createTreeFromList, TreeNode } from '../utils/tree-utils'; +import { PermissionService } from './permission.service'; export abstract class AbstractTreeService { abstract id: string; @@ -134,9 +134,12 @@ export abstract class AbstractTreeService { } @Injectable() -export abstract class AbstractNavTreeService extends AbstractTreeService +export abstract class AbstractNavTreeService + extends AbstractTreeService implements OnDestroy { + protected actions: Actions; private subscription: Subscription; + private permissionService: PermissionService; readonly id = 'name'; readonly parentId = 'parentName'; readonly hide = (item: T) => item.invisible || !this.isGranted(item); @@ -147,16 +150,17 @@ export abstract class AbstractNavTreeService extends Abstract return a.order - b.order; }; - constructor(protected actions: Actions, protected store: Store) { + constructor(protected injector: Injector) { super(); - + this.actions = injector.get(Actions); this.subscription = this.actions .pipe(ofActionSuccessful(GetAppConfiguration)) .subscribe(() => this.refresh()); + this.permissionService = injector.get(PermissionService); } protected isGranted({ requiredPolicy }: T): boolean { - return this.store.selectSnapshot(ConfigState.getGrantedPolicy(requiredPolicy)); + return this.permissionService.getGrantedPolicy(requiredPolicy); } hasChildren(identifier: string): boolean { diff --git a/npm/ng-packs/packages/core/src/lib/states/config.state.ts b/npm/ng-packs/packages/core/src/lib/states/config.state.ts index 2953c5212f..a721299411 100644 --- a/npm/ng-packs/packages/core/src/lib/states/config.state.ts +++ b/npm/ng-packs/packages/core/src/lib/states/config.state.ts @@ -104,6 +104,9 @@ export class ConfigState { return selector; } + /** + * @deprecated use PermissionService's getGrantedPolicyStream or getGrantedPolicy methods. + */ static getGrantedPolicy(key: string) { const selector = createSelector([ConfigState], (state: Config.State): boolean => { if (!key) return true; diff --git a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts index 43ad6f87b1..68ab0eecd0 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts @@ -2,17 +2,16 @@ import { HttpClient } from '@angular/common/http'; import { Component, NgModule } from '@angular/core'; import { ActivatedRoute, RouterModule } from '@angular/router'; import { createRoutingFactory, SpectatorRouting } from '@ngneat/spectator/jest'; -import { Actions, NgxsModule, Store } from '@ngxs/store'; -import { NEVER } from 'rxjs'; +import { NgxsModule } from '@ngxs/store'; import { DynamicLayoutComponent, RouterOutletComponent } from '../components'; import { eLayoutType } from '../enums/common'; import { ABP } from '../models'; import { ApplicationConfigurationService, - RoutesService, ReplaceableComponentsService, + RoutesService, } from '../services'; -import { ReplaceableComponentsState } from '../states'; +import { mockRoutesService } from './utils'; @Component({ selector: 'abp-layout-application', @@ -91,12 +90,7 @@ describe('DynamicLayoutComponent', () => { providers: [ { provide: RoutesService, - useFactory: () => - new RoutesService(NEVER, ({ - selectSnapshot() { - return true; - }, - } as unknown) as Store), + useFactory: () => mockRoutesService(), }, ReplaceableComponentsService, ], diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts index 4c6356634b..067a620606 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts @@ -1,16 +1,20 @@ import { PermissionDirective } from '../directives/permission.directive'; -import { SpectatorDirective, createDirectiveFactory, SpyObject } from '@ngneat/spectator/jest'; +import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/jest'; import { Store } from '@ngxs/store'; -import { of, Subject } from 'rxjs'; +import { Subject } from 'rxjs'; +import { PermissionService } from '../services'; +import { mockStore } from './utils/common.utils'; describe('PermissionDirective', () => { let spectator: SpectatorDirective; let directive: PermissionDirective; - const grantedPolicy$ = new Subject(); - + const grantedPolicy$ = new Subject(); const createDirective = createDirectiveFactory({ directive: PermissionDirective, - providers: [{ provide: Store, useValue: { select: () => grantedPolicy$ } }], + providers: [ + { provide: Store, useValue: mockStore }, + { provide: PermissionService, useValue: { getGrantedPolicy$: () => grantedPolicy$ } }, + ], }); describe('with condition', () => { diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts index cd9108ec87..c69dcf4346 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts @@ -7,19 +7,21 @@ import { of } from 'rxjs'; import { RestOccurError } from '../actions'; import { PermissionGuard } from '../guards/permission.guard'; import { RoutesService } from '../services/routes.service'; +import { PermissionService } from '../services'; describe('PermissionGuard', () => { let spectator: SpectatorService; let guard: PermissionGuard; let routes: SpyObject; let store: SpyObject; + let permissionService: SpyObject; @Component({ template: '' }) class DummyComponent {} const createService = createServiceFactory({ service: PermissionGuard, - mocks: [Store], + mocks: [PermissionService, Store], declarations: [DummyComponent], imports: [ RouterModule.forRoot([ @@ -53,10 +55,11 @@ describe('PermissionGuard', () => { guard = spectator.service; routes = spectator.inject(RoutesService); store = spectator.inject(Store); + permissionService = spectator.inject(PermissionService); }); it('should return true when the grantedPolicy is true', done => { - store.select.andReturn(of(true)); + permissionService.getGrantedPolicy$.andReturn(of(true)); const spy = jest.spyOn(store, 'dispatch'); guard.canActivate({ data: { requiredPolicy: 'test' } } as any, null).subscribe(res => { expect(res).toBe(true); @@ -66,7 +69,7 @@ describe('PermissionGuard', () => { }); it('should return false and dispatch RestOccurError when the grantedPolicy is false', done => { - store.select.andReturn(of(false)); + permissionService.getGrantedPolicy$.andReturn(of(false)); const spy = jest.spyOn(store, 'dispatch'); guard.canActivate({ data: { requiredPolicy: 'test' } } as any, null).subscribe(res => { expect(res).toBe(false); @@ -84,10 +87,9 @@ describe('PermissionGuard', () => { requiredPolicy: 'TestPolicy', }, ]); - store.select.andReturn(of(false)); - const spy = jest.spyOn(store, 'select'); - guard.canActivate({ data: {} } as any, { url: 'test' } as any).subscribe(() => { - expect(spy.mock.calls[0][0]({ auth: { grantedPolicies: { TestPolicy: true } } })).toBe(true); + permissionService.getGrantedPolicy$.mockImplementation(policy => of(policy === 'TestPolicy')); + guard.canActivate({ data: {} } as any, { url: 'test' } as any).subscribe(result => { + expect(result).toBe(true); done(); }); }); diff --git a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts index 6b7ae3f50a..35d56dbf81 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts @@ -3,6 +3,8 @@ import { Subject } from 'rxjs'; import { take } from 'rxjs/operators'; import { GetAppConfiguration } from '../actions'; import { RoutesService } from '../services'; +import { mockRoutesService } from './utils'; +import { mockActions } from './utils/common.utils'; describe('Routes Service', () => { let service: RoutesService; @@ -14,15 +16,9 @@ describe('Routes Service', () => { { path: '/foo/x', name: 'x', parentName: 'foo', order: 1 }, ]; - const mockActions = new Subject(); - const mockStore = ({ - selectSnapshot() { - return true; - }, - } as unknown) as Store; beforeEach(() => { - service = new RoutesService(mockActions, mockStore); + service = mockRoutesService(); }); describe('#add', () => { diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts new file mode 100644 index 0000000000..ba05659736 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts @@ -0,0 +1,28 @@ +import { Observable, of, Subject } from 'rxjs'; +import { Store } from '@ngxs/store'; +import { AbstractType, InjectFlags, InjectionToken, Injector, Type } from '@angular/core'; + +export const mockActions = new Subject(); +export const mockStore = ({ + selectSnapshot() { + return true; + }, + select(): Observable { + return of(null); + }, +} as unknown) as Store; + +export class DummyInjector extends Injector { + constructor(public payload: { [key: string]: any }) { + super(); + } + get( + token: Type | InjectionToken | AbstractType, + notFoundValue?: T, + flags?: InjectFlags, + ): T; + get(token: any, notFoundValue?: any): any; + get(token, notFoundValue?, flags?: InjectFlags): any { + return this.payload[token.name || token]; + } +} diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/index.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/index.ts new file mode 100644 index 0000000000..75de71af2f --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/index.ts @@ -0,0 +1 @@ +export * from './routes-service.spec.utils'; diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts new file mode 100644 index 0000000000..ef1a264c2b --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts @@ -0,0 +1,7 @@ +import { PermissionService } from '../../services'; +import { Subject } from 'rxjs'; + +export const mockPermissionService = (args = {} as Partial) => { + const permissionService = { getGrantedPolicy$: new Subject(), getGrantedPolicy: arg => true }; + return Object.assign({}, permissionService, args); +}; diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts new file mode 100644 index 0000000000..303bfbba18 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts @@ -0,0 +1,12 @@ +import { RoutesService } from '../../services'; +import { mockPermissionService } from './permission-service.spec.utils'; +import { DummyInjector, mockActions } from './common.utils'; + +export const mockRoutesService = (injectorPayload = {} as { [key: string]: any }) => { + const injector = new DummyInjector({ + PermissionService: mockPermissionService(), + Actions: mockActions, + ...injectorPayload, + }); + return new RoutesService(injector); +}; diff --git a/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts index 8c9553fac2..07fad6a1fe 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts @@ -5,12 +5,12 @@ import { RoutesService } from '../services/routes.service'; import { noop } from './common-utils'; import { TreeNode } from './tree-utils'; -export function findRoute(routes: RoutesService, path: string): TreeNode { - const node = routes.find(route => route.path === path); +export function findRoute(routesService: RoutesService, path: string): TreeNode { + const node = routesService.find(route => route.path === path); return node || path === '/' ? node - : findRoute(routes, path.split('/').slice(0, -1).join('/') || '/'); + : findRoute(routesService, path.split('/').slice(0, -1).join('/') || '/'); } export function getRoutePath(router: Router, url = router.url) { diff --git a/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts b/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts index 1ab2cbb3ee..f5c2bc2327 100644 --- a/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts @@ -8,9 +8,9 @@ export const IDENTITY_ROUTE_PROVIDERS = [ { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, ]; -export function configureRoutes(routes: RoutesService) { +export function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/identity', name: eIdentityRouteNames.IdentityManagement, diff --git a/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts b/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts index 28c0fb7388..9d272b8be0 100644 --- a/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts @@ -14,9 +14,9 @@ export const SETTING_MANAGEMENT_ROUTE_PROVIDERS = [ }, ]; -export function configureRoutes(routes: RoutesService) { +export function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { name: eSettingManagementRouteNames.Settings, path: '/setting-management', @@ -29,13 +29,15 @@ export function configureRoutes(routes: RoutesService) { }; } -export function hideRoutes(routes: RoutesService, tabs: SettingTabsService) { +export function hideRoutes(routesService: RoutesService, settingTabsService: SettingTabsService) { return () => { - tabs.visible$ + settingTabsService.visible$ .pipe( debounceTime(0), map(nodes => !nodes.length), ) - .subscribe(invisible => routes.patch(eSettingManagementRouteNames.Settings, { invisible })); + .subscribe(invisible => + routesService.patch(eSettingManagementRouteNames.Settings, { invisible }), + ); }; } diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts b/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts index 5b65c1f76d..e8e94293e9 100644 --- a/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts +++ b/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts @@ -24,7 +24,7 @@ export class SettingManagementComponent implements OnDestroy, OnInit { trackByFn: TrackByFunction = (_, item) => item.name; - constructor(private store: Store, private settingTabs: SettingTabsService) {} + constructor(private store: Store, private settingTabsService: SettingTabsService) {} ngOnDestroy() { this.subscription.unsubscribe(); @@ -32,7 +32,7 @@ export class SettingManagementComponent implements OnDestroy, OnInit { ngOnInit() { this.subscription.add( - this.settingTabs.visible$.subscribe(settings => { + this.settingTabsService.visible$.subscribe(settings => { this.settings = settings; if (!this.selected) this.selected = this.settings[0]; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html index 4e6395da05..cf27990b4e 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html @@ -1,6 +1,6 @@