Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AAE-25392 Convert route guards to functional - part two #10116

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions lib/core/src/lib/auth/oidc/auth-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@
*/

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { provideRouter, Routes } from '@angular/router';
import { AuthenticationConfirmationComponent } from './view/authentication-confirmation/authentication-confirmation.component';
import { OidcAuthGuard } from './oidc-auth.guard';

const routes: Routes = [
{ path: 'view/authentication-confirmation', component: AuthenticationConfirmationComponent, canActivate: [OidcAuthGuard]}
];
const routes: Routes = [{ path: 'view/authentication-confirmation', component: AuthenticationConfirmationComponent, canActivate: [OidcAuthGuard] }];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
providers: [provideRouter(routes)]
})
export class AuthRoutingModule {}
50 changes: 9 additions & 41 deletions lib/core/src/lib/auth/oidc/oidc-auth.guard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,77 +17,45 @@

import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
import { OidcAuthGuard } from './oidc-auth.guard';
import { AuthService } from './auth.service';

describe('OidcAuthGuard', () => {
let oidcAuthGuard: OidcAuthGuard;
let authServiceSpy: jasmine.SpyObj<AuthService>;
let routerSpy: jasmine.SpyObj<Router>;
const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
const state: RouterStateSnapshot = {} as RouterStateSnapshot;

beforeEach(() => {
const routerSpyObj = jasmine.createSpyObj('Router', ['navigateByUrl']);
const authSpy = jasmine.createSpyObj('AuthService', ['loginCallback']);

TestBed.configureTestingModule({
providers: [
OidcAuthGuard,
{ provide: AuthService, useValue: authSpy },
{ provide: Router, useValue: routerSpyObj }
],
providers: [OidcAuthGuard, { provide: AuthService, useValue: authSpy }, { provide: Router, useValue: routerSpyObj }],
imports: [RouterTestingModule]
});

routerSpy = TestBed.inject(Router) as jasmine.SpyObj<Router>;
oidcAuthGuard = TestBed.inject(OidcAuthGuard);
authServiceSpy = TestBed.inject(AuthService) as jasmine.SpyObj<AuthService>;
});

describe('canActivate', () => {
it('should return true if is authenticated', () => {
it('should return true if is authenticated', async () => {
authServiceSpy.authenticated = true;

const result = oidcAuthGuard.canActivate();
const oidcAuthGuard = await TestBed.runInInjectionContext(() => OidcAuthGuard(route, state));

expect(result).toBe(true);
});

it('should call isAuthenticated and return the result', () => {
const isAuthenticatedSpy = spyOn<any>(oidcAuthGuard, '_isAuthenticated').and.returnValue(true);

const result = oidcAuthGuard.canActivate();

expect(isAuthenticatedSpy).toHaveBeenCalled();
expect(result).toBe(true);
});
});

describe('canActivateChild', () => {
it('should call isAuthenticated and return its result', () => {
const isAuthenticatedSpy = spyOn<any>(oidcAuthGuard, '_isAuthenticated').and.returnValue(true);

const result = oidcAuthGuard.canActivateChild();

expect(isAuthenticatedSpy).toHaveBeenCalled();
expect(result).toBe(true);
expect(oidcAuthGuard).toBe(true);
});
});

describe('isAuthenticated', () => {
it('should return true if is authenticated', () => {
authServiceSpy.authenticated = true;

const result = oidcAuthGuard['_isAuthenticated']();

expect(result).toBe(true);
});

it('should call loginCallback and navigateByUrl if not authenticated', async () => {
authServiceSpy.authenticated = false;
authServiceSpy.loginCallback.and.returnValue(Promise.resolve('/fake-route'));

await oidcAuthGuard.canActivate();
await TestBed.runInInjectionContext(() => OidcAuthGuard(route, state));

expect(authServiceSpy.loginCallback).toHaveBeenCalled();
expect(routerSpy.navigateByUrl).toHaveBeenCalledWith('/fake-route', { replaceUrl: true });
Expand All @@ -97,7 +65,7 @@ describe('OidcAuthGuard', () => {
authServiceSpy.authenticated = false;
authServiceSpy.loginCallback.and.returnValue(Promise.reject(new Error()));

await oidcAuthGuard.canActivate();
await TestBed.runInInjectionContext(() => OidcAuthGuard(route, state));

expect(routerSpy.navigateByUrl).toHaveBeenCalledWith('/', { replaceUrl: true });
});
Expand Down
39 changes: 13 additions & 26 deletions lib/core/src/lib/auth/oidc/oidc-auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,24 @@
* limitations under the License.
*/

import { Injectable } from '@angular/core';
import { CanActivate, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';

const ROUTE_DEFAULT = '/';

@Injectable({
providedIn: 'root'
})
export class OidcAuthGuard implements CanActivate {
constructor(private auth: AuthService, private _router: Router) { }
export const OidcAuthGuard: CanActivateFn = async (): Promise<boolean> => {
const authService = inject(AuthService);
const router = inject(Router);

canActivate(
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this._isAuthenticated();
if (authService.authenticated) {
return Promise.resolve(true);
}

canActivateChild() {
return this._isAuthenticated();
try {
const route = await authService.loginCallback({ customHashFragment: window.location.search });
return router.navigateByUrl(route, { replaceUrl: true });
} catch (error) {
return router.navigateByUrl(ROUTE_DEFAULT, { replaceUrl: true });
}

private _isAuthenticated() {
if (this.auth.authenticated) {
return true;
}

return this.auth.loginCallback({ customHashFragment: window.location.search })
.then(route => this._router.navigateByUrl(route, { replaceUrl: true }))
.catch(() => this._router.navigateByUrl(ROUTE_DEFAULT, { replaceUrl: true }));
}

}

};
Loading