fix(console): auth response interceptor, new assets, async route guard, pipe modules cleanup, disable custom idp editation for orgs, refresh list on idp creation (#793)

* chore(deps-dev): bump @angular/cli from 10.0.8 to 10.1.3 in /console (#785)

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 10.0.8 to 10.1.3.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v10.0.8...v10.1.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#784)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1000.8 to 0.1001.3.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>

* chore(deps-dev): bump @angular/language-service in /console (#783)

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 10.1.0 to 10.1.3.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/10.1.3/packages/language-service)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump stylelint from 13.7.1 to 13.7.2 in /console (#782)

Bumps [stylelint](https://github.com/stylelint/stylelint) from 13.7.1 to 13.7.2.
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/13.7.1...13.7.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump karma from 5.2.1 to 5.2.3 in /console (#781)

Bumps [karma](https://github.com/karma-runner/karma) from 5.2.1 to 5.2.3.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v5.2.1...v5.2.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump moment from 2.27.0 to 2.29.0 in /console (#780)

Bumps [moment](https://github.com/moment/moment) from 2.27.0 to 2.29.0.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.27.0...2.29.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @types/node from 14.6.4 to 14.11.2 in /console (#778)

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.6.4 to 14.11.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump prettier from 2.1.1 to 2.1.2 in /console (#757)

Bumps [prettier](https://github.com/prettier/prettier) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.1.1...2.1.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump ts-protoc-gen from 0.12.0 to 0.13.0 in /console (#737)

Bumps [ts-protoc-gen](https://github.com/improbable-eng/ts-protoc-gen) from 0.12.0 to 0.13.0.
- [Release notes](https://github.com/improbable-eng/ts-protoc-gen/releases)
- [Changelog](https://github.com/improbable-eng/ts-protoc-gen/blob/master/CHANGELOG.md)
- [Commits](https://github.com/improbable-eng/ts-protoc-gen/compare/0.12.0...0.13.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump jasmine-spec-reporter in /console (#762)

Bumps [jasmine-spec-reporter](https://github.com/bcaudan/jasmine-spec-reporter) from 5.0.2 to 6.0.0.
- [Release notes](https://github.com/bcaudan/jasmine-spec-reporter/releases)
- [Changelog](https://github.com/bcaudan/jasmine-spec-reporter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcaudan/jasmine-spec-reporter/compare/v5.0.2...v6.0.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>

* fix: package

* change html lang to translation lang

* disable detail view org idp

* catch errorcode 16 in auth response interceptor

* new icons

* refactor pipes, idp table config

* fix router guard

* lint

* allowed commonjs deps

* Update console/src/assets/i18n/en.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Florian Forster <florian@caos.ch>
This commit is contained in:
Max Peintner
2020-09-29 13:21:40 +02:00
committed by GitHub
parent 83b0ac1fdb
commit dd1ccefd29
59 changed files with 646 additions and 449 deletions

View File

@@ -44,6 +44,8 @@ export class GrpcAuthService {
private _activeOrgChanged: Subject<Org.AsObject> = new Subject();
public user!: Observable<UserProfileView.AsObject>;
private zitadelPermissions: BehaviorSubject<string[]> = new BehaviorSubject(['user.resourceowner']);
public readonly fetchedZitadelPermissions: BehaviorSubject<boolean> = new BehaviorSubject(false as boolean);
private cachedOrgs: Org.AsObject[] = [];
constructor(
@@ -125,6 +127,12 @@ export class GrpcAuthService {
first(),
switchMap(() => from(this.GetMyzitadelPermissions())),
map(rolesResp => rolesResp.toObject().permissionsList),
catchError(_ => {
return of([]);
}),
finalize(() => {
this.fetchedZitadelPermissions.next(true);
}),
).subscribe(roles => {
this.zitadelPermissions.next(roles);
});
@@ -136,9 +144,7 @@ export class GrpcAuthService {
*/
public isAllowed(roles: string[] | RegExp[]): Observable<boolean> {
if (roles && roles.length > 0) {
return this.zitadelPermissions.pipe(switchMap(zroles => {
return of(this.hasRoles(zroles, roles));
}));
return this.zitadelPermissions.pipe(switchMap(zroles => of(this.hasRoles(zroles, roles))));
} else {
return of(false);
}
@@ -220,6 +226,10 @@ export class GrpcAuthService {
return this.grpcService.auth.updateMyUserProfile(req);
}
public get zitadelPermissionsChanged(): Observable<string[]> {
return this.zitadelPermissions;
}
public async getMyUserSessions(): Promise<UserSessionViews> {
return this.grpcService.auth.getMyUserSessions(
new Empty(),
@@ -286,15 +296,15 @@ export class GrpcAuthService {
}
public async SearchExternalIdps(
userId: string,
limit: number,
offset: number,
asc?: boolean,
userId: string,
limit: number,
offset: number,
asc?: boolean,
): Promise<ExternalIDPSearchResponse> {
const req = new ExternalIDPSearchRequest();
req.setLimit(limit);
req.setOffset(offset);
return this.grpcService.auth.searchMyExternalIDPs(req);
const req = new ExternalIDPSearchRequest();
req.setLimit(limit);
req.setOffset(offset);
return this.grpcService.auth.searchMyExternalIDPs(req);
}
public async AddMfaOTP(): Promise<MfaOtpResponse> {

View File

@@ -1,6 +1,7 @@
import { PlatformLocation } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AuthConfig } from 'angular-oauth2-oidc';
import { AdminServicePromiseClient } from '../proto/generated/admin_grpc_web_pb';
@@ -24,6 +25,8 @@ export class GrpcService {
private platformLocation: PlatformLocation,
private authenticationService: AuthenticationService,
private storageService: StorageService,
private dialog: MatDialog,
// private toast: ToastService,
) { }
public async loadAppEnvironment(): Promise<any> {
@@ -31,9 +34,9 @@ export class GrpcService {
.toPromise().then((data: any) => {
if (data && data.authServiceUrl && data.mgmtServiceUrl && data.issuer) {
const interceptors = {
'unaryInterceptors': [
new AuthInterceptor(this.authenticationService, this.storageService),
unaryInterceptors: [
new OrgInterceptor(this.storageService),
new AuthInterceptor(this.authenticationService, this.storageService, this.dialog),
],
};

View File

@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Request, UnaryInterceptor, UnaryResponse } from 'grpc-web';
import { filter, first } from 'rxjs/operators';
import { filter, first, take } from 'rxjs/operators';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import { AuthenticationService } from '../authentication.service';
import { StorageService } from '../storage.service';
@@ -10,8 +12,15 @@ const authorizationKey = 'Authorization';
const bearerPrefix = 'Bearer';
const accessTokenStorageKey = 'access_token';
@Injectable({ providedIn: 'root' })
/**
* Set the authentication token
*/
export class AuthInterceptor<TReq = unknown, TResp = unknown> implements UnaryInterceptor<TReq, TResp> {
constructor(private authenticationService: AuthenticationService, private storageService: StorageService) { }
constructor(
private authenticationService: AuthenticationService,
private storageService: StorageService,
private dialog: MatDialog,
) { }
public async intercept(request: Request<TReq, TResp>, invoker: any): Promise<UnaryResponse<TReq, TResp>> {
await this.authenticationService.authenticationChanged.pipe(
@@ -24,17 +33,25 @@ export class AuthInterceptor<TReq = unknown, TResp = unknown> implements UnaryIn
metadata[authorizationKey] = `${bearerPrefix} ${accessToken}`;
return invoker(request).then((response: any) => {
// const message = response.getResponseMessage();
const respMetadata = response.getMetadata();
// TODO: intercept unauthenticated an authenticate
// const status = respMetadata['grpc-status'];
// console.log(respMetadata, status);
// if (status?.code === 16) {
// this.authenticationService.authenticate();
// }
return response;
}).catch((error: any) => {
console.error('error: ', error);
if (error.code === 16) {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.LOGIN',
titleKey: 'ERRORS.TOKENINVALID.TITLE',
descriptionKey: 'ERRORS.TOKENINVALID.DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().pipe(take(1)).subscribe(resp => {
if (resp) {
this.authenticationService.authenticate(undefined, true, true);
}
});
}
});
}
}

View File

@@ -3,9 +3,7 @@ import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { WarnDialogComponent } from '../modules/warn-dialog/warn-dialog.component';
import { AuthenticationService } from './authentication.service';
@Injectable({
@@ -32,24 +30,8 @@ export class ToastService {
public showError(grpcError: any): void {
const { message, code, metadata } = grpcError;
// TODO: remove check for code === 7
if (code === 16 || (code === 7 && message === 'invalid token')) {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.LOGIN',
titleKey: 'ERRORS.TOKENINVALID.TITLE',
descriptionKey: 'ERRORS.TOKENINVALID.DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().pipe(take(1)).subscribe(resp => {
if (resp) {
this.authService.authenticate(undefined, true, true);
}
});
} else {
this.showMessage(decodeURI(message), 'close', { duration: 3000 });
if (code !== 16) {
this.showMessage(decodeURI(message), 'close', { duration: 4000 });
}
}