fix(console): app details (#7827)

* cleanup app urls

* fix app details

* styles and specific urls

* lint

* explicit urls

* deterministic order

* lint

---------

Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
Elio Bischof 2024-04-29 12:16:59 +02:00 committed by GitHub
parent 6ab06aa249
commit 8c1a8f792a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 48 deletions

View File

@ -422,19 +422,21 @@
</ng-container> </ng-container>
<ng-container *ngIf="currentSetting === 'urls'"> <ng-container *ngIf="currentSetting === 'urls'">
<cnsl-card title=" {{ 'APP.URLS' | translate }}"> <cnsl-card title=" {{ 'APP.URLS' | translate }}">
<cnsl-info-section *ngIf="(apiMap$ | async)?.issuer as issuer"> <cnsl-info-section *ngIf="issuer$ | async as issuer">
<div <div
class="link" class="link"
[innerHtml]="'APP.OIDC.WELLKNOWN' | translate: { url: issuer + '/.well-known/openid-configuration' }" [innerHtml]="'APP.OIDC.WELLKNOWN' | translate: { url: issuer + '/.well-known/openid-configuration' }"
></div> ></div>
</cnsl-info-section> </cnsl-info-section>
<cnsl-copy-row <ng-container *ngIf="app?.apiConfig && apiURLs$ | async as apiURLs">
labelMinWidth="220px" <cnsl-copy-row
*ngFor="let apiUrl of apiMap$ | async | keyvalue" labelMinWidth="220px"
[label]="apiUrl.key" *ngFor="let apiUrl of apiURLs"
[value]="apiUrl.value" [label]="apiUrl[0]"
></cnsl-copy-row> [value]="apiUrl[1]"
<ng-container *ngIf="app?.samlConfig && samlMap$ | async as samlMap"> ></cnsl-copy-row>
</ng-container>
<ng-container *ngIf="app?.samlConfig && samlURLs$ | async as samlMap">
<cnsl-copy-row <cnsl-copy-row
labelMinWidth="220px" labelMinWidth="220px"
*ngIf="samlMap['samlCertificateURL'] as url" *ngIf="samlMap['samlCertificateURL'] as url"
@ -456,14 +458,9 @@
[value]="url" [value]="url"
></cnsl-copy-row> ></cnsl-copy-row>
</ng-container> </ng-container>
<ng-container *ngIf="!app?.samlConfig"> <ng-container *ngIf="app?.oidcConfig && wellknownURLs$ | async as wellKnownURLs">
<ng-container *ngFor="let wellknown of wellknownMap$ | async | keyvalue"> <ng-container *ngFor="let wellknown of wellKnownURLs">
<cnsl-copy-row <cnsl-copy-row labelMinWidth="220px" [label]="wellknown[0]" [value]="wellknown[1]"></cnsl-copy-row>
labelMinWidth="220px"
*ngIf="wellknown.key.endsWith('endpoint') || wellknown.key.toString() === 'jwks_uri'"
[label]="wellknown.key"
[value]="wellknown.value"
></cnsl-copy-row>
</ng-container> </ng-container>
</ng-container> </ng-container>
</cnsl-card> </cnsl-card>

View File

@ -304,8 +304,9 @@
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
font-family: inherit; font-family: inherit;
text-decoration: underline;
&:hover { }
text-decoration: underline;
} .download-button {
margin-left: 1rem;
} }

View File

@ -8,7 +8,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Buffer } from 'buffer'; import { Buffer } from 'buffer';
import { Duration } from 'google-protobuf/google/protobuf/duration_pb'; import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
import { Subject, Subscription } from 'rxjs'; import { mergeMap, Subject, Subscription } from 'rxjs';
import { map, take } from 'rxjs/operators'; import { map, take } from 'rxjs/operators';
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component'; import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
import { ChangeType } from 'src/app/modules/changes/changes.component'; import { ChangeType } from 'src/app/modules/changes/changes.component';
@ -80,30 +80,27 @@ export class AppDetailComponent implements OnInit, OnDestroy {
public appId: string = ''; public appId: string = '';
public app?: App.AsObject; public app?: App.AsObject;
public environmentMap$ = this.envSvc.env.pipe( public apiURLs$ = this.envSvc.env.pipe(
map((env) => { mergeMap((env) =>
return { this.wellknownURLs$.pipe(
issuer: env.issuer, map((wellknown) => {
adminServiceUrl: `${env.api}/admin/v1`, return [
mgmtServiceUrl: `${env.api}/management/v1`, ['Issuer', env.issuer],
authServiceUrl: `${env.api}/auth/v1`, ['Admin Service URL', `${env.api}/admin/v1`],
samlCertificateURL: `${env.issuer}/saml/v2/certificate`, ['Management Service URL', `${env.api}/management/v1`],
samlSSO: `${env.issuer}/saml/v2/SSO`, ['Auth Service URL', `${env.api}/auth/v1`],
samlSLO: `${env.issuer}/saml/v2/SLO`, ...wellknown.filter(
}; ([k, v]) => k === 'Revocation Endpoint' || k === 'JKWS URI' || k === 'Introspection Endpoint',
}), ),
];
}),
),
),
); );
public apiMap$ = this.envSvc.env.pipe(
map((env) => { public issuer$ = this.apiURLs$.pipe(map((urls) => urls.find(([k, v]) => k === 'Issuer')?.[1]));
return {
issuer: env.issuer, public samlURLs$ = this.envSvc.env.pipe(
adminServiceUrl: `${env.api}/admin/v1`,
mgmtServiceUrl: `${env.api}/management/v1`,
authServiceUrl: `${env.api}/auth/v1`,
};
}),
);
public samlMap$ = this.envSvc.env.pipe(
map((env) => { map((env) => {
return { return {
samlCertificateURL: `${env.issuer}/saml/v2/certificate`, samlCertificateURL: `${env.issuer}/saml/v2/certificate`,
@ -112,7 +109,21 @@ export class AppDetailComponent implements OnInit, OnDestroy {
}; };
}), }),
); );
public wellknownMap$ = this.envSvc.wellknown;
public wellknownURLs$ = this.envSvc.wellknown.pipe(
map((wellknown) => {
return [
['Authorization Endpoint', wellknown.authorization_endpoint],
['Device Authorization Endpoint', wellknown.device_authorization_endpoint],
['End Session Endpoint', wellknown.end_session_endpoint],
['Introspection Endpoint', wellknown.introspection_endpoint],
['JKWS URI', wellknown.jwks_uri],
['Revocation Endpoint', wellknown.revocation_endpoint],
['Token Endpoint', wellknown.token_endpoint],
['Userinfo Endpoint', wellknown.userinfo_endpoint],
];
}),
);
public oidcResponseTypes: OIDCResponseType[] = [ public oidcResponseTypes: OIDCResponseType[] = [
OIDCResponseType.OIDC_RESPONSE_TYPE_CODE, OIDCResponseType.OIDC_RESPONSE_TYPE_CODE,
@ -217,9 +228,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
if (!this.app) { if (!this.app) {
this.app = new App().toObject(); this.app = new App().toObject();
} }
if (!this.app.samlConfig) {
this.app.samlConfig = new SAMLConfig().toObject();
}
let minimalMetadata = let minimalMetadata =
this.entityId?.value && this.acsURL?.value this.entityId?.value && this.acsURL?.value
@ -231,6 +239,14 @@ export class AppDetailComponent implements OnInit, OnDestroy {
</md:EntityDescriptor>` </md:EntityDescriptor>`
: ''; : '';
if (!minimalMetadata && !this.metadataUrl?.value) {
return;
}
if (!this.app.samlConfig) {
this.app.samlConfig = new SAMLConfig().toObject();
}
if (minimalMetadata) { if (minimalMetadata) {
const base64 = Buffer.from(minimalMetadata, 'utf-8').toString('base64'); const base64 = Buffer.from(minimalMetadata, 'utf-8').toString('base64');
this.app.samlConfig.metadataXml = base64; this.app.samlConfig.metadataXml = base64;

View File

@ -18,10 +18,13 @@ export interface Environment {
interface WellKnown { interface WellKnown {
authorization_endpoint: string; authorization_endpoint: string;
device_authorization_endpoint: string;
end_session_endpoint: string; end_session_endpoint: string;
introspection_endpoint: string; introspection_endpoint: string;
token_endpoint: string; token_endpoint: string;
userinfo_endpoint: string; userinfo_endpoint: string;
jwks_uri: string;
revocation_endpoint: string;
} }
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',