fix(console): Idp settings, settings reset warn dialog, Accept-Language header interceptor, i18n (#3727)

* fix idp table, settings reset warn dialog, fix i18n interceptor, i18n

* fix label policy on org change

* fallback

* fix preview button styles

* footer, login-policy null check

* org create btn alignment

* show error with toast

* error toast
This commit is contained in:
Max Peintner
2022-05-31 09:08:47 +02:00
committed by GitHub
parent 3513148cf6
commit f9e9b4b64b
45 changed files with 472 additions and 413 deletions
+13 -12
View File
@@ -216,9 +216,9 @@ export class GrpcAuthService {
* returns true if user has one of the provided roles
* @param roles roles of the user
*/
public isAllowed(roles: string[] | RegExp[]): Observable<boolean> {
public isAllowed(roles: string[] | RegExp[], requiresAll: boolean = false): Observable<boolean> {
if (roles && roles.length > 0) {
return this.zitadelPermissions.pipe(switchMap((zroles) => of(this.hasRoles(zroles, roles))));
return this.zitadelPermissions.pipe(switchMap((zroles) => of(this.hasRoles(zroles, roles, requiresAll))));
} else {
return of(false);
}
@@ -228,17 +228,18 @@ export class GrpcAuthService {
* returns true if user has one of the provided roles
* @param userRoles roles of the user
* @param requestedRoles required roles for accessing the respective component
* @param requiresAll true - if all regexes must match, false - if only one regex must match
*/
public hasRoles(userRoles: string[], requestedRoles: string[] | RegExp[]): boolean {
return (
requestedRoles.findIndex((regexp: any) => {
return (
userRoles.findIndex((role) => {
return new RegExp(regexp).test(role);
}) > -1
);
}) > -1
);
public hasRoles(userRoles: string[], requestedRoles: string[] | RegExp[], requiresAll: boolean = false): boolean {
const test = (reqRegexp: string | RegExp) =>
userRoles.some((role) => {
return new RegExp(reqRegexp).test(role);
});
const allCheck = requestedRoles.map(test).every((x) => !!x);
const oneCheck = requestedRoles.some(test);
return requiresAll ? allCheck : oneCheck;
}
public getMyProfile(): Promise<GetMyProfileResponse.AsObject> {
+3 -1
View File
@@ -2,6 +2,7 @@ import { PlatformLocation } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
import { AuthConfig } from 'angular-oauth2-oidc';
import { AdminServiceClient } from '../proto/generated/zitadel/AdminServiceClientPb';
@@ -27,6 +28,7 @@ export class GrpcService {
private authenticationService: AuthenticationService,
private storageService: StorageService,
private dialog: MatDialog,
private translate: TranslateService,
) {}
public async loadAppEnvironment(): Promise<any> {
@@ -39,7 +41,7 @@ export class GrpcService {
unaryInterceptors: [
new OrgInterceptor(this.storageService),
new AuthInterceptor(this.authenticationService, this.storageService, this.dialog),
new I18nInterceptor(),
new I18nInterceptor(this.translate),
],
};
@@ -1,27 +1,29 @@
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { Request, UnaryInterceptor, UnaryResponse } from 'grpc-web';
const i18nHeader = 'Accept-Language';
@Injectable({ providedIn: 'root' })
/**
* Set the navigator language as header to all grpc requests
*/
export class I18nInterceptor<TReq = unknown, TResp = unknown> implements UnaryInterceptor<TReq, TResp> {
constructor() { }
constructor(private translate: TranslateService) {}
public async intercept(request: Request<TReq, TResp>, invoker: any): Promise<UnaryResponse<TReq, TResp>> {
const metadata = request.getMetadata();
public async intercept(request: Request<TReq, TResp>, invoker: any): Promise<UnaryResponse<TReq, TResp>> {
const metadata = request.getMetadata();
const navLang = navigator.language;
if (navLang) {
metadata[i18nHeader] = navLang;
}
return invoker(request).then((response: any) => {
return response;
}).catch((error: any) => {
return Promise.reject(error);
});
const navLang = this.translate.currentLang ?? navigator.language;
if (navLang) {
metadata[i18nHeader] = navLang;
}
return invoker(request)
.then((response: any) => {
return response;
})
.catch((error: any) => {
return Promise.reject(error);
});
}
}
@@ -98,12 +98,6 @@ export class KeyboardShortcutsService implements OnDestroy {
this.router.navigate(DOMAINS.link);
}
}
// if (secondKey.shiftKey && (secondKey.code === 'Digit7' || secondKey.key==='/')) {
// }
// SIDEWIDESHORTCUTS.f
} else if (secondKey && exclude.indexOf(secondTagname?.toLowerCase()) === -1) {
if (secondKey.key === '?') {
this.openOverviewDialog();
+96 -1
View File
@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { ManagementService } from './mgmt.service';
declare const tinycolor: any;
export interface Color {
@@ -19,7 +21,7 @@ export class ThemeService {
private warnColorPalette: Color[] = [];
private backgroundColorPalette: Color[] = [];
constructor() {
constructor(private mgmtService: ManagementService) {
const theme = localStorage.getItem('theme');
if (theme) {
if (theme === 'light-theme') {
@@ -111,4 +113,97 @@ export class ThemeService {
return '#ffffff';
}
}
public setDefaultColors = () => {
const darkPrimary = '#bbbafa';
const lightPrimary = '#5469d4';
const darkWarn = '#ff3b5b';
const lightWarn = '#cd3d56';
const darkBackground = '#111827';
const lightBackground = '#fafafa';
const darkText = '#ffffff';
const lightText = '#000000';
this.savePrimaryColor(darkPrimary, true);
this.savePrimaryColor(lightPrimary, false);
this.saveWarnColor(darkWarn, true);
this.saveWarnColor(lightWarn, false);
this.saveBackgroundColor(darkBackground, true);
this.saveBackgroundColor(lightBackground, false);
this.saveTextColor(darkText, true);
this.saveTextColor(lightText, false);
};
public loadPrivateLabelling(): void {
this.setDefaultColors();
const isDark = (color: string) => this.isDark(color);
const isLight = (color: string) => this.isLight(color);
this.mgmtService
.getLabelPolicy()
.then((lpresp) => {
const labelpolicy = lpresp.policy;
const darkPrimary = labelpolicy?.primaryColorDark || '#bbbafa';
const lightPrimary = labelpolicy?.primaryColor || '#5469d4';
const darkWarn = labelpolicy?.warnColorDark || '#ff3b5b';
const lightWarn = labelpolicy?.warnColor || '#cd3d56';
let darkBackground = labelpolicy?.backgroundColorDark;
let lightBackground = labelpolicy?.backgroundColor;
let darkText = labelpolicy?.fontColorDark ?? '#ffffff';
let lightText = labelpolicy?.fontColor ?? '#000000';
this.savePrimaryColor(darkPrimary, true);
this.savePrimaryColor(lightPrimary, false);
this.saveWarnColor(darkWarn, true);
this.saveWarnColor(lightWarn, false);
if (darkBackground && !isDark(darkBackground)) {
console.info(
`Background (${darkBackground}) is not dark enough for a dark theme. Falling back to zitadel background`,
);
darkBackground = '#111827';
}
this.saveBackgroundColor(darkBackground || '#111827', true);
if (lightBackground && !isLight(lightBackground)) {
console.info(
`Background (${lightBackground}) is not light enough for a light theme. Falling back to zitadel background`,
);
lightBackground = '#fafafa';
}
this.saveBackgroundColor(lightBackground || '#fafafa', false);
if (darkText && !isLight(darkText)) {
console.info(
`Text color (${darkText}) is not light enough for a dark theme. Falling back to zitadel's text color`,
);
darkText = '#ffffff';
}
this.saveTextColor(darkText || '#ffffff', true);
if (lightText && !isDark(lightText)) {
console.info(
`Text color (${lightText}) is not dark enough for a light theme. Falling back to zitadel's text color`,
);
lightText = '#000000';
}
this.saveTextColor(lightText || '#000000', false);
})
.catch((error) => {
console.error('could not load private labelling policy!', error);
this.setDefaultColors();
});
}
}