forked from onecx/onecx-portal-ui-libs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: fix permission issues in edge cases by... (onecx#252)
* fix: move initializeModuleGuard to angular-integration-interface to fix permission issues in edge cases * fix: better deprecation info message * fix: add missing exports in index ts --------- Co-authored-by: kim.tran <[email protected]>
- Loading branch information
Showing
8 changed files
with
372 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
libs/angular-integration-interface/src/lib/services/initialize-module-guard.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Injectable } from '@angular/core' | ||
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router' | ||
import { TranslateService } from '@ngx-translate/core' | ||
import { filter, from, isObservable, map, mergeMap, Observable, of, tap, zip } from 'rxjs' | ||
import { AppStateService } from './app-state.service'; | ||
import { ConfigurationService } from './configuration.service'; | ||
import { UserService } from './user.service'; | ||
|
||
@Injectable({ providedIn: 'any' }) | ||
export class InitializeModuleGuard implements CanActivate { | ||
private SUPPORTED_LANGS = ['en', 'de'] | ||
private DEFAULT_LANG = 'en' | ||
constructor( | ||
protected translateService: TranslateService, | ||
protected configService: ConfigurationService, | ||
protected appStateService: AppStateService, | ||
protected userService: UserService | ||
) {} | ||
|
||
canActivate( | ||
_route: ActivatedRouteSnapshot, | ||
_state: RouterStateSnapshot | ||
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { | ||
console.time('InitializeModuleGuard') | ||
return zip([ | ||
this.loadTranslations(), | ||
from(this.configService.isInitialized), | ||
from(this.userService.isInitialized), | ||
from(this.appStateService.currentWorkspace$.isInitialized), | ||
]).pipe( | ||
tap(() => { | ||
console.timeEnd('InitializeModuleGuard') | ||
}), | ||
map(() => true) | ||
) | ||
} | ||
|
||
getBestMatchLanguage(lang: string) { | ||
if (this.SUPPORTED_LANGS.includes(lang)) { | ||
return lang | ||
} else { | ||
console.log(`${lang} is not supported. Using ${this.DEFAULT_LANG} as a fallback.`) | ||
} | ||
return this.DEFAULT_LANG | ||
} | ||
|
||
loadTranslations(): Observable<boolean> { | ||
return this.userService.lang$.pipe( | ||
filter((v) => v !== undefined), | ||
mergeMap((lang) => { | ||
const bestMatchLang = this.getBestMatchLanguage(lang as string) | ||
return this.translateService.use(bestMatchLang) | ||
}), | ||
mergeMap(() => of(true)) | ||
) | ||
} | ||
|
||
protected toObservable( | ||
canActivateResult: Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree | ||
): Observable<boolean | UrlTree> { | ||
if (isObservable(canActivateResult)) { | ||
return canActivateResult | ||
} | ||
return from(Promise.resolve(canActivateResult)) | ||
} | ||
} |
240 changes: 240 additions & 0 deletions
240
libs/angular-integration-interface/src/lib/utils/add-initialize-module-guard.utils.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
import { TranslateService } from '@ngx-translate/core' | ||
import { AppStateService } from '../services/app-state.service'; | ||
import { UserService } from '../services/user.service'; | ||
import { ConfigurationService } from '../services/configuration.service'; | ||
import { InitializeModuleGuard } from '../services/initialize-module-guard.service' | ||
import { addInitializeModuleGuard } from './add-initialize-module-guard.utils' | ||
|
||
class MockInitializeModuleGuard extends InitializeModuleGuard { | ||
constructor( | ||
translateService: TranslateService, | ||
configService: ConfigurationService, | ||
appStateService: AppStateService, | ||
userService: UserService | ||
) { | ||
super(translateService, configService, appStateService, userService) | ||
} | ||
} | ||
|
||
describe('AddInitializeGuard', () => { | ||
it('should add canActivate array with InitializeModuleGuard to routes without canActivate and redirectTo properties', () => { | ||
const testRoutesNoCanActivate = [ | ||
{ | ||
path: 'testPathAddInitializerModuleGuard1', | ||
}, | ||
{ | ||
path: 'testPathAddInitializerModuleGuard2', | ||
}, | ||
] | ||
|
||
const expectedRoutes = [ | ||
{ | ||
path: 'testPathAddInitializerModuleGuard1', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathAddInitializerModuleGuard2', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
] | ||
const modifiedRoutes = addInitializeModuleGuard(testRoutesNoCanActivate) | ||
|
||
expect(modifiedRoutes).toEqual(expectedRoutes) | ||
expect(testRoutesNoCanActivate).not.toEqual(expectedRoutes) | ||
}) | ||
|
||
it('should add InitializeModuleGuard to canActivate array which already has some other guard', () => { | ||
const testRoutesWithMockInitializeModuleGuard = [ | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard1', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPath', | ||
}, | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard2', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
] | ||
|
||
const expectedRoutes = [ | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard1', | ||
canActivate: [MockInitializeModuleGuard, InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPath', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard2', | ||
canActivate: [MockInitializeModuleGuard, InitializeModuleGuard], | ||
}, | ||
] | ||
const modifiedRoutes = addInitializeModuleGuard(testRoutesWithMockInitializeModuleGuard) | ||
|
||
expect(modifiedRoutes).toEqual(expectedRoutes) | ||
expect(testRoutesWithMockInitializeModuleGuard).not.toEqual(expectedRoutes) | ||
}) | ||
|
||
it('should not add another InitializeModuleGuard to canActivate array which already has an InitializeModuleGuard', () => { | ||
const testRoutesWithInitializeModuleGuard = [ | ||
{ | ||
path: 'testPath1', | ||
}, | ||
{ | ||
path: 'testPathHasInitializeModueGuard1', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasInitializeModueGuard2', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPath2', | ||
}, | ||
{ | ||
path: 'testPathHasInitializeModueGuard3', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
] | ||
|
||
const expectedRoutes = [ | ||
{ | ||
path: 'testPath1', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasInitializeModueGuard1', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasInitializeModueGuard2', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPath2', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasInitializeModueGuard3', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
] | ||
const modifiedRoutes = addInitializeModuleGuard(testRoutesWithInitializeModuleGuard) | ||
|
||
expect(modifiedRoutes).toEqual(expectedRoutes) | ||
expect(testRoutesWithInitializeModuleGuard).not.toEqual(expectedRoutes) | ||
}) | ||
|
||
it('should not add InitializeModuleGuard if a route has the redirectTo property', () => { | ||
const testRoutesWithRedirectTo = [ | ||
{ | ||
path: 'testPathHasRedirectTo1', | ||
redirectTo: 'redirectToPath1', | ||
}, | ||
{ | ||
path: 'someTestPath1', | ||
}, | ||
{ | ||
path: 'testPathHasRedirectTo2', | ||
redirectTo: 'redirectToPath2', | ||
}, | ||
{ | ||
path: 'someTestPath2', | ||
}, | ||
] | ||
|
||
const expectedRoutes = [ | ||
{ | ||
path: 'testPathHasRedirectTo1', | ||
redirectTo: 'redirectToPath1', | ||
}, | ||
{ | ||
path: 'someTestPath1', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasRedirectTo2', | ||
redirectTo: 'redirectToPath2', | ||
}, | ||
{ | ||
path: 'someTestPath2', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
] | ||
const modifiedRoutes = addInitializeModuleGuard(testRoutesWithRedirectTo) | ||
|
||
expect(modifiedRoutes).toEqual(expectedRoutes) | ||
expect(testRoutesWithRedirectTo).not.toEqual(expectedRoutes) | ||
}) | ||
|
||
it('should add canActivate array with MockInitializeModuleGuard to routes without canActivate and redirectTo properties', () => { | ||
const testRoutesNoCanActivate = [ | ||
{ | ||
path: 'testPathAddMockInitializerModuleGuard1', | ||
}, | ||
{ | ||
path: 'testPathAddMockInitializerModuleGuard2', | ||
}, | ||
{ | ||
path: 'testPathAddMockInitializerModuleGuard3', | ||
}, | ||
] | ||
|
||
const expectedRoutes = [ | ||
{ | ||
path: 'testPathAddMockInitializerModuleGuard1', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathAddMockInitializerModuleGuard2', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathAddMockInitializerModuleGuard3', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
] | ||
const modifiedRoutes = addInitializeModuleGuard(testRoutesNoCanActivate, MockInitializeModuleGuard) | ||
|
||
expect(modifiedRoutes).toEqual(expectedRoutes) | ||
expect(testRoutesNoCanActivate).not.toEqual(expectedRoutes) | ||
}) | ||
|
||
it('should add MockInitializeModuleGuard to canActivate array', () => { | ||
const testRoutesWithMockInitializeModuleGuard = [ | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard1', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'somePath', | ||
}, | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard2', | ||
canActivate: [InitializeModuleGuard], | ||
}, | ||
] | ||
|
||
const expectedRoutes = [ | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard1', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'somePath', | ||
canActivate: [MockInitializeModuleGuard], | ||
}, | ||
{ | ||
path: 'testPathHasMockInitializeModueGuard2', | ||
canActivate: [InitializeModuleGuard, MockInitializeModuleGuard], | ||
}, | ||
] | ||
const modifiedRoutes = addInitializeModuleGuard(testRoutesWithMockInitializeModuleGuard, MockInitializeModuleGuard) | ||
|
||
expect(modifiedRoutes).toEqual(expectedRoutes) | ||
expect(testRoutesWithMockInitializeModuleGuard).not.toEqual(expectedRoutes) | ||
}) | ||
}) |
21 changes: 21 additions & 0 deletions
21
libs/angular-integration-interface/src/lib/utils/add-initialize-module-guard.utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { CanActivateFn, Route } from '@angular/router' | ||
import { InitializeModuleGuard } from '../services/initialize-module-guard.service' | ||
|
||
export function addInitializeModuleGuard( | ||
routes: Route[], | ||
initializeModuleGuard: typeof InitializeModuleGuard | CanActivateFn = InitializeModuleGuard | ||
): Route[] { | ||
return routes.map((r) => { | ||
if (r.redirectTo) { | ||
return r | ||
} | ||
const route = { | ||
canActivate: [], | ||
...r, | ||
} | ||
if (!route.canActivate.includes(initializeModuleGuard)) { | ||
route.canActivate.push(initializeModuleGuard) | ||
} | ||
return route | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.