diff --git a/console/src/app/app.component.html b/console/src/app/app.component.html index 18c5c72501..5b31b33dc4 100644 --- a/console/src/app/app.component.html +++ b/console/src/app/app.component.html @@ -1,5 +1,5 @@
- + this.onSetTheme(dark ? 'dark-theme' : 'light-theme')); + this.isDarkTheme + .pipe(takeUntil(this.destroy$)) + .subscribe((dark) => this.onSetTheme(dark ? 'dark-theme' : 'light-theme')); - this.translate.onLangChange.subscribe((language: LangChangeEvent) => { + this.translate.onLangChange.pipe(takeUntil(this.destroy$)).subscribe((language: LangChangeEvent) => { this.document.documentElement.lang = language.lang; this.language = language.lang; }); @@ -271,7 +273,7 @@ export class AppComponent implements OnDestroy { this.translate.addLangs(supportedLanguages); this.translate.setDefaultLang(fallbackLanguage); - this.authService.user.subscribe((userprofile) => { + this.authService.userSubject.pipe(takeUntil(this.destroy$)).subscribe((userprofile) => { if (userprofile) { const cropped = navigator.language.split('-')[0] ?? fallbackLanguage; const fallbackLang = cropped.match(supportedLanguagesRegexp) ? cropped : fallbackLanguage; diff --git a/console/src/app/guards/user.guard.ts b/console/src/app/guards/user.guard.ts index c57b896ece..b4527753fe 100644 --- a/console/src/app/guards/user.guard.ts +++ b/console/src/app/guards/user.guard.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { map, Observable, take } from 'rxjs'; import { GrpcAuthService } from '../services/grpc-auth.service'; @@ -19,11 +18,13 @@ export class UserGuard { state: RouterStateSnapshot, ): Observable | Promise | boolean { return this.authService.user.pipe( - map((user) => user?.id !== route.params['id']), - tap((isNotMe) => { - if (!isNotMe) { + take(1), + map((user) => { + const isMe = user?.id === route.params['id']; + if (isMe) { this.router.navigate(['/users', 'me']); } + return !isMe; }), ); } diff --git a/console/src/app/services/authentication.service.ts b/console/src/app/services/authentication.service.ts index c53047c047..314b9edb7e 100644 --- a/console/src/app/services/authentication.service.ts +++ b/console/src/app/services/authentication.service.ts @@ -3,6 +3,7 @@ import { AuthConfig, OAuthService } from 'angular-oauth2-oidc'; import { BehaviorSubject, from, lastValueFrom, Observable } from 'rxjs'; import { StatehandlerService } from './statehandler/statehandler.service'; +import { ToastService } from './toast.service'; @Injectable({ providedIn: 'root', @@ -15,6 +16,7 @@ export class AuthenticationService { constructor( private oauthService: OAuthService, private statehandler: StatehandlerService, + private toast: ToastService, ) {} public initConfig(data: AuthConfig): void { @@ -39,7 +41,10 @@ export class AuthenticationService { } this.oauthService.configure(this.authConfig); this.oauthService.strictDiscoveryDocumentValidation = false; - await this.oauthService.loadDiscoveryDocumentAndTryLogin(); + await this.oauthService.loadDiscoveryDocumentAndTryLogin().catch((error) => { + this.toast.showError(error, false, false); + }); + this._authenticated = this.oauthService.hasValidAccessToken(); if (!this.oauthService.hasValidIdToken() || !this.authenticated || partialConfig || force) { const newState = await lastValueFrom(this.statehandler.createState()); diff --git a/console/src/app/services/grpc-auth.service.ts b/console/src/app/services/grpc-auth.service.ts index 18fc7f928d..dbb2d6dd5f 100644 --- a/console/src/app/services/grpc-auth.service.ts +++ b/console/src/app/services/grpc-auth.service.ts @@ -1,19 +1,8 @@ import { Injectable } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; import { OAuthService } from 'angular-oauth2-oidc'; -import { BehaviorSubject, from, merge, Observable, of, Subject } from 'rxjs'; -import { - catchError, - distinctUntilChanged, - filter, - finalize, - map, - mergeMap, - switchMap, - take, - timeout, - withLatestFrom, -} from 'rxjs/operators'; +import { BehaviorSubject, forkJoin, from, Observable, of, Subject } from 'rxjs'; +import { catchError, distinctUntilChanged, filter, finalize, map, switchMap, timeout, withLatestFrom } from 'rxjs/operators'; import { AddMyAuthFactorOTPEmailRequest, @@ -184,25 +173,21 @@ export class GrpcAuthService { }, }); - this.user = merge( - of(this.oauthService.getAccessToken()).pipe(filter((token) => (token ? true : false))), + this.user = forkJoin([ + of(this.oauthService.getAccessToken()), this.oauthService.events.pipe( filter((e) => e.type === 'token_received'), timeout(this.oauthService.waitForTokenInMsec || 0), catchError((_) => of(null)), // timeout is not an error map((_) => this.oauthService.getAccessToken()), ), - ).pipe( - take(1), - mergeMap(() => { + ]).pipe( + filter((token) => (token ? true : false)), + distinctUntilChanged(), + switchMap(() => { return from( this.getMyUser().then((resp) => { - const user = resp.user; - if (user) { - return user; - } else { - return undefined; - } + return resp.user; }), ); }),