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;
}),
);
}),