feat(console): friendly quota exhausted screen (#5790)

* fix: remove access interceptor for console

* feat: show dialog on exhausted requests

* fix exhausted cookie handling

* fix quota exhausted screen

* read instance mgmt from environment.json

* fix interceptors

* don't check cookie on environment.json

* fix environment.json path

* exclude environment.json from cookie check

* remove cookie before loading env

* use UTC to delete the cookie

* delete cookie before fetching env

* simplify cookie handling

* lint

* review cleanup

* use exhausted property from env json

* fix bootstrapping

* lint

* always open mgmt link if present

* chore: fetch env json before ng serve

* wait for cookie to be removed

* fix typo

* don't wait for cookie to be set
This commit is contained in:
Elio Bischof
2023-05-19 12:48:39 +02:00
committed by GitHub
parent 2e86c44aa5
commit b475068140
26 changed files with 336 additions and 155 deletions

View File

@@ -1,18 +1,22 @@
import { PlatformLocation } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { TranslateService } from '@ngx-translate/core';
import { AuthConfig } from 'angular-oauth2-oidc';
import { catchError, switchMap, tap, throwError } from 'rxjs';
import { AdminServiceClient } from '../proto/generated/zitadel/AdminServiceClientPb';
import { AuthServiceClient } from '../proto/generated/zitadel/AuthServiceClientPb';
import { ManagementServiceClient } from '../proto/generated/zitadel/ManagementServiceClientPb';
import { AuthenticationService } from './authentication.service';
import { EnvironmentService } from './environment.service';
import { ExhaustedService } from './exhausted.service';
import { AuthInterceptor } from './interceptors/auth.interceptor';
import { ExhaustedGrpcInterceptor } from './interceptors/exhausted.grpc.interceptor';
import { I18nInterceptor } from './interceptors/i18n.interceptor';
import { OrgInterceptor } from './interceptors/org.interceptor';
import { StorageService } from './storage.service';
import { ThemeService } from './theme.service';
@Injectable({
providedIn: 'root',
@@ -23,22 +27,30 @@ export class GrpcService {
public admin!: AdminServiceClient;
constructor(
private http: HttpClient,
private envService: EnvironmentService,
private platformLocation: PlatformLocation,
private authenticationService: AuthenticationService,
private storageService: StorageService,
private dialog: MatDialog,
private translate: TranslateService,
private exhaustedService: ExhaustedService,
private themeService: ThemeService,
) {}
public async loadAppEnvironment(): Promise<any> {
return this.http
.get('./assets/environment.json')
.toPromise()
.then((data: any) => {
if (data && data.api && data.issuer) {
public loadAppEnvironment(): Promise<any> {
this.themeService.applyLabelPolicy();
// We use the browser language until we can make API requests to get the users configured language.
return this.translate
.use(this.translate.getBrowserLang() || this.translate.defaultLang)
.pipe(
switchMap(() => this.envService.env),
tap((env) => {
if (!env?.api || !env?.issuer) {
return;
}
const interceptors = {
unaryInterceptors: [
new ExhaustedGrpcInterceptor(this.exhaustedService, this.envService),
new OrgInterceptor(this.storageService),
new AuthInterceptor(this.authenticationService, this.storageService, this.dialog),
new I18nInterceptor(this.translate),
@@ -46,19 +58,19 @@ export class GrpcService {
};
this.auth = new AuthServiceClient(
data.api,
env.api,
null,
// @ts-ignore
interceptors,
);
this.mgmt = new ManagementServiceClient(
data.api,
env.api,
null,
// @ts-ignore
interceptors,
);
this.admin = new AdminServiceClient(
data.api,
env.api,
null,
// @ts-ignore
interceptors,
@@ -68,19 +80,20 @@ export class GrpcService {
scope: 'openid profile email',
responseType: 'code',
oidc: true,
clientId: data.clientid,
issuer: data.issuer,
clientId: env.clientid,
issuer: env.issuer,
redirectUri: window.location.origin + this.platformLocation.getBaseHrefFromDOM() + 'auth/callback',
postLogoutRedirectUri: window.location.origin + this.platformLocation.getBaseHrefFromDOM() + 'signedout',
requireHttps: false,
};
this.authenticationService.initConfig(authConfig);
}
return Promise.resolve(data);
})
.catch(() => {
console.error('Failed to load environment from assets');
});
}),
catchError((err) => {
console.error('Failed to load environment from assets', err);
return throwError(() => err);
}),
)
.toPromise();
}
}