mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-14 01:45:12 +00:00
fix(console-v2): app detail layout, create layout stepper (#3680)
* app detail * app-detail layout * app layout, create layout component, cleanup * lint
This commit is contained in:
@@ -1,133 +1,313 @@
|
||||
<div class="max-width-container">
|
||||
<div class="enlarged-container">
|
||||
<div class="abort-container">
|
||||
<button (click)="close()" mat-icon-button>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<span class="abort">{{ 'APP.PAGES.CREATE_OIDC' | translate }}</span
|
||||
><span class="abort-2">Step {{ currentCreateStep }} of {{ createSteps }}</span>
|
||||
</div>
|
||||
<cnsl-create-layout
|
||||
title="{{ 'APP.PAGES.CREATE_OIDC' | translate }}"
|
||||
[createSteps]="createSteps"
|
||||
[currentCreateStep]="currentCreateStep"
|
||||
(closed)="close()"
|
||||
>
|
||||
<h1>{{ 'APP.PAGES.CREATE_OIDC_DESC_TITLE' | translate }}</h1>
|
||||
<mat-progress-bar class="progress-bar" color="primary" *ngIf="loading" mode="indeterminate"></mat-progress-bar>
|
||||
|
||||
<div class="app-create-content">
|
||||
<h1>{{ 'APP.PAGES.CREATE_OIDC_DESC_TITLE' | translate }}</h1>
|
||||
<mat-progress-bar class="progress-bar" color="primary" *ngIf="loading" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-checkbox class="proswitch" color="primary" [(ngModel)]="devmode">
|
||||
{{ 'APP.OIDC.PROSWITCH' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-checkbox class="proswitch" color="primary" [(ngModel)]="devmode">
|
||||
{{ 'APP.OIDC.PROSWITCH' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-horizontal-stepper
|
||||
class="stepper"
|
||||
*ngIf="!devmode"
|
||||
linear
|
||||
#stepper
|
||||
labelPosition="bottom"
|
||||
(selectionChange)="changeStep($event)"
|
||||
>
|
||||
<mat-step [stepControl]="firstFormGroup" [editable]="true">
|
||||
<form [formGroup]="firstFormGroup">
|
||||
<ng-template matStepLabel>{{ 'APP.OIDC.NAMEANDTYPESECTION' | translate }}</ng-template>
|
||||
|
||||
<mat-horizontal-stepper
|
||||
class="stepper"
|
||||
*ngIf="!devmode"
|
||||
linear
|
||||
#stepper
|
||||
labelPosition="bottom"
|
||||
(selectionChange)="changeStep($event)"
|
||||
>
|
||||
<mat-step [stepControl]="firstFormGroup" [editable]="true">
|
||||
<form [formGroup]="firstFormGroup">
|
||||
<ng-template matStepLabel>{{ 'APP.OIDC.NAMEANDTYPESECTION' | translate }}</ng-template>
|
||||
<p class="step-title">{{ 'APP.OIDC.TITLEFIRST' | translate }}</p>
|
||||
<cnsl-form-field appearance="outline" class="name-formfield">
|
||||
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput cdkFocusInitial formControlName="name" />
|
||||
<span cnslError *ngIf="name?.errors?.required">{{ 'PROJECT.APP.NAMEREQUIRED' | translate }}</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<p class="step-title">{{ 'APP.OIDC.TITLEFIRST' | translate }}</p>
|
||||
<cnsl-form-field appearance="outline" class="name-formfield">
|
||||
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput cdkFocusInitial formControlName="name" />
|
||||
<span cnslError *ngIf="name?.errors?.required">{{ 'PROJECT.APP.NAMEREQUIRED' | translate }}</span>
|
||||
</cnsl-form-field>
|
||||
<p class="step-title">{{ 'APP.OIDC.TYPETITLE' | translate }}</p>
|
||||
|
||||
<p class="step-title">{{ 'APP.OIDC.TYPETITLE' | translate }}</p>
|
||||
|
||||
<cnsl-type-radio [types]="appTypes" (selectedType)="appType?.setValue($event)" [selected]="appType?.value">
|
||||
</cnsl-type-radio>
|
||||
<div class="app-create-actions">
|
||||
<button
|
||||
mat-raised-button
|
||||
[disabled]="firstFormGroup.invalid"
|
||||
color="primary"
|
||||
matStepperNext
|
||||
[attr.data-e2e]="'continue-button-nameandtype'"
|
||||
>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<!-- skip for native applications -->
|
||||
<mat-step
|
||||
*ngIf="oidcAppRequest.appType !== OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
[stepControl]="secondFormGroup"
|
||||
[editable]="true"
|
||||
>
|
||||
<form [formGroup]="secondFormGroup">
|
||||
<ng-template matStepLabel>{{ 'APP.AUTHMETHODSECTION' | translate }}</ng-template>
|
||||
|
||||
<cnsl-auth-method-radio
|
||||
[authMethods]="authMethods"
|
||||
[selected]="authMethod?.value"
|
||||
[isOIDC]="appType?.value?.createType === AppCreateType.OIDC"
|
||||
(selectedMethod)="authMethod?.setValue($event)"
|
||||
>
|
||||
</cnsl-auth-method-radio>
|
||||
|
||||
<div class="app-create-actions">
|
||||
<button class="bck-button" mat-stroked-button matStepperPrevious>{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="secondFormGroup.invalid"
|
||||
matStepperNext
|
||||
[attr.data-e2e]="'continue-button-authmethod'"
|
||||
>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<!-- show redirect step only for OIDC apps -->
|
||||
<mat-step *ngIf="appType?.value?.createType === AppCreateType.OIDC" [editable]="true">
|
||||
<ng-template matStepLabel>{{ 'APP.OIDC.REDIRECTSECTION' | translate }}</ng-template>
|
||||
|
||||
<p class="step-title">{{ 'APP.OIDC.REDIRECTTITLE' | translate }}</p>
|
||||
<p
|
||||
class="step-description cnsl-secondary-text"
|
||||
*ngIf="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
<cnsl-type-radio [types]="appTypes" (selectedType)="appType?.setValue($event)" [selected]="appType?.value">
|
||||
</cnsl-type-radio>
|
||||
<div class="app-create-actions">
|
||||
<button
|
||||
mat-raised-button
|
||||
[disabled]="firstFormGroup.invalid"
|
||||
color="primary"
|
||||
matStepperNext
|
||||
[attr.data-e2e]="'continue-button-nameandtype'"
|
||||
>
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate }}
|
||||
</p>
|
||||
<p class="step-description cnsl-secondary-text" *ngIf="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_WEB">
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate }}
|
||||
</p>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<!-- skip for native applications -->
|
||||
<mat-step
|
||||
*ngIf="oidcAppRequest.appType !== OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
[stepControl]="secondFormGroup"
|
||||
[editable]="true"
|
||||
>
|
||||
<form [formGroup]="secondFormGroup">
|
||||
<ng-template matStepLabel>{{ 'APP.AUTHMETHODSECTION' | translate }}</ng-template>
|
||||
|
||||
<cnsl-auth-method-radio
|
||||
[authMethods]="authMethods"
|
||||
[selected]="authMethod?.value"
|
||||
[isOIDC]="appType?.value?.createType === AppCreateType.OIDC"
|
||||
(selectedMethod)="authMethod?.setValue($event)"
|
||||
>
|
||||
</cnsl-auth-method-radio>
|
||||
|
||||
<div class="app-create-actions">
|
||||
<button class="bck-button" mat-stroked-button matStepperPrevious>{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="secondFormGroup.invalid"
|
||||
matStepperNext
|
||||
[attr.data-e2e]="'continue-button-authmethod'"
|
||||
>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<!-- show redirect step only for OIDC apps -->
|
||||
<mat-step *ngIf="appType?.value?.createType === AppCreateType.OIDC" [editable]="true">
|
||||
<ng-template matStepLabel>{{ 'APP.OIDC.REDIRECTSECTION' | translate }}</ng-template>
|
||||
|
||||
<p class="step-title">{{ 'APP.OIDC.REDIRECTTITLE' | translate }}</p>
|
||||
<p class="step-description cnsl-secondary-text" *ngIf="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate }}
|
||||
</p>
|
||||
<p class="step-description cnsl-secondary-text" *ngIf="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_WEB">
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate }}
|
||||
</p>
|
||||
|
||||
<cnsl-redirect-uris
|
||||
class="redirect-section"
|
||||
[canWrite]="true"
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
(changedUris)="oidcAppRequest.redirectUrisList = $any($event)"
|
||||
[urisList]="oidcAppRequest.redirectUrisList"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<p class="step-title">{{ 'APP.OIDC.POSTREDIRECTTITLE' | translate }}</p>
|
||||
<p class="step-description cnsl-secondary-text" *ngIf="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate }}
|
||||
</p>
|
||||
<p
|
||||
class="step-description cnsl-secondary-text"
|
||||
*ngIf="
|
||||
oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_WEB ||
|
||||
oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_USER_AGENT
|
||||
"
|
||||
>
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate }}
|
||||
</p>
|
||||
|
||||
<cnsl-redirect-uris
|
||||
class="redirect-section"
|
||||
[canWrite]="true"
|
||||
(changedUris)="oidcAppRequest.postLogoutRedirectUrisList = $any($event)"
|
||||
[urisList]="oidcAppRequest.postLogoutRedirectUrisList"
|
||||
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<div class="app-create-actions">
|
||||
<button mat-stroked-button class="bck-button" matStepperPrevious>{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button mat-raised-button color="primary" matStepperNext [attr.data-e2e]="'continue-button-redirecturis'">
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'APP.OIDC.OVERVIEWSECTION' | translate }}</ng-template>
|
||||
<p class="step-title">{{ 'APP.OIDC.OVERVIEWTITLE' | translate }}</p>
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.NAME' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
{{ oidcAppRequest.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="appType?.value?.createType === AppCreateType.OIDC">
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.TYPE' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
{{ 'APP.OIDC.APPTYPE.' + oidcAppRequest.appType | translate }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.GRANT' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="oidcAppRequest.grantTypesList && oidcAppRequest.grantTypesList.length > 0">
|
||||
[<span *ngFor="let element of oidcAppRequest.grantTypesList; index as i">
|
||||
{{ 'APP.OIDC.GRANT.' + element | translate }}
|
||||
{{ i < oidcAppRequest.grantTypesList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.OIDC.RESPONSETYPE' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="oidcAppRequest.responseTypesList && oidcAppRequest.responseTypesList.length > 0">
|
||||
[<span *ngFor="let element of oidcAppRequest.responseTypesList; index as i">
|
||||
{{ 'APP.OIDC.RESPONSE.' + element | translate }}
|
||||
{{ i < oidcAppRequest.responseTypesList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.AUTHMETHOD' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + oidcAppRequest?.authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.OIDC.REDIRECT' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="oidcAppRequest.redirectUrisList && oidcAppRequest.redirectUrisList.length > 0">
|
||||
[<span *ngFor="let redirect of oidcAppRequest.redirectUrisList; index as i">
|
||||
{{ redirect }}
|
||||
{{ i < oidcAppRequest.redirectUrisList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}
|
||||
</span>
|
||||
<span
|
||||
class="right"
|
||||
*ngIf="oidcAppRequest.postLogoutRedirectUrisList && oidcAppRequest.postLogoutRedirectUrisList.length > 0"
|
||||
>
|
||||
[<span *ngFor="let redirect of oidcAppRequest.postLogoutRedirectUrisList; index as i">
|
||||
{{ redirect }}
|
||||
{{ i < oidcAppRequest.postLogoutRedirectUrisList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="appType?.value?.createType === AppCreateType.API">
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.AUTHMETHOD' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.API.AUTHMETHOD.' + apiAppRequest?.authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div class="app-create-actions">
|
||||
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
class="create-button"
|
||||
color="primary"
|
||||
(click)="createApp()"
|
||||
[attr.data-e2e]="'create-button'"
|
||||
>
|
||||
{{ 'ACTIONS.CREATE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
||||
|
||||
<div *ngIf="devmode" class="dev">
|
||||
<form [formGroup]="form" (ngSubmit)="createApp()" [attr.data-e2e]="'create-app-wizzard-3'">
|
||||
<div class="content">
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="name" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="appType">
|
||||
<mat-option *ngFor="let appType of appTypes" [value]="appType">
|
||||
{{ appType.titleI18nKey | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<ng-container *ngIf="formappType?.value?.createType === AppCreateType.OIDC">
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.OIDC.GRANTTYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="grantTypesList" multiple>
|
||||
<mat-option *ngFor="let grant of oidcGrantTypes" [value]="grant.type">
|
||||
{{ 'APP.OIDC.GRANT.' + grant.type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.OIDC.RESPONSETYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="responseTypesList" multiple>
|
||||
<mat-option *ngFor="let type of oidcResponseTypes" [value]="type.type">
|
||||
{{ 'APP.OIDC.RESPONSE.' + type.type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</ng-container>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.AUTHMETHOD' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="authMethodType">
|
||||
<mat-option *ngFor="let type of authMethodTypes" [value]="type.type">
|
||||
<span *ngIf="type.oidc">{{ 'APP.OIDC.AUTHMETHOD.' + type.type | translate }}</span>
|
||||
<span *ngIf="type.api">{{ 'APP.API.AUTHMETHOD.' + type.type | translate }}</span>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<div class="content" *ngIf="formappType?.value?.createType === AppCreateType.OIDC">
|
||||
<div class="formfield full-width">
|
||||
<cnsl-redirect-uris
|
||||
class="redirect-section"
|
||||
[canWrite]="true"
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
(changedUris)="oidcAppRequest.redirectUrisList = $any($event)"
|
||||
[urisList]="oidcAppRequest.redirectUrisList"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<p class="step-title">{{ 'APP.OIDC.POSTREDIRECTTITLE' | translate }}</p>
|
||||
<p
|
||||
class="step-description cnsl-secondary-text"
|
||||
*ngIf="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate }}
|
||||
</p>
|
||||
<p
|
||||
class="step-description cnsl-secondary-text"
|
||||
*ngIf="
|
||||
oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_WEB ||
|
||||
oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_USER_AGENT
|
||||
"
|
||||
>
|
||||
{{ 'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate }}
|
||||
</p>
|
||||
|
||||
<cnsl-redirect-uris
|
||||
class="redirect-section"
|
||||
[canWrite]="true"
|
||||
@@ -138,212 +318,19 @@
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<div class="app-create-actions">
|
||||
<button mat-stroked-button class="bck-button" matStepperPrevious>{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button mat-raised-button color="primary" matStepperNext [attr.data-e2e]="'continue-button-redirecturis'">
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'APP.OIDC.OVERVIEWSECTION' | translate }}</ng-template>
|
||||
<p class="step-title">{{ 'APP.OIDC.OVERVIEWTITLE' | translate }}</p>
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.NAME' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
{{ oidcAppRequest.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="appType?.value?.createType === AppCreateType.OIDC">
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.TYPE' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
{{ 'APP.OIDC.APPTYPE.' + oidcAppRequest.appType | translate }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.GRANT' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="oidcAppRequest.grantTypesList && oidcAppRequest.grantTypesList.length > 0">
|
||||
[<span *ngFor="let element of oidcAppRequest.grantTypesList; index as i">
|
||||
{{ 'APP.OIDC.GRANT.' + element | translate }}
|
||||
{{ i < oidcAppRequest.grantTypesList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.OIDC.RESPONSETYPE' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="oidcAppRequest.responseTypesList && oidcAppRequest.responseTypesList.length > 0">
|
||||
[<span *ngFor="let element of oidcAppRequest.responseTypesList; index as i">
|
||||
{{ 'APP.OIDC.RESPONSE.' + element | translate }}
|
||||
{{ i < oidcAppRequest.responseTypesList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.AUTHMETHOD' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + oidcAppRequest?.authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.OIDC.REDIRECT' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="oidcAppRequest.redirectUrisList && oidcAppRequest.redirectUrisList.length > 0">
|
||||
[<span *ngFor="let redirect of oidcAppRequest.redirectUrisList; index as i">
|
||||
{{ redirect }}
|
||||
{{ i < oidcAppRequest.redirectUrisList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}
|
||||
</span>
|
||||
<span
|
||||
class="right"
|
||||
*ngIf="oidcAppRequest.postLogoutRedirectUrisList && oidcAppRequest.postLogoutRedirectUrisList.length > 0"
|
||||
>
|
||||
[<span *ngFor="let redirect of oidcAppRequest.postLogoutRedirectUrisList; index as i">
|
||||
{{ redirect }}
|
||||
{{ i < oidcAppRequest.postLogoutRedirectUrisList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="appType?.value?.createType === AppCreateType.API">
|
||||
<div class="row cnsl-secondary-text">
|
||||
<span class="left">
|
||||
{{ 'APP.AUTHMETHOD' | translate }}
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.API.AUTHMETHOD.' + apiAppRequest?.authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div class="app-create-actions">
|
||||
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
class="create-button"
|
||||
color="primary"
|
||||
(click)="createApp()"
|
||||
[attr.data-e2e]="'create-button'"
|
||||
>
|
||||
{{ 'ACTIONS.CREATE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
||||
|
||||
<div *ngIf="devmode" class="dev">
|
||||
<form [formGroup]="form" (ngSubmit)="createApp()" [attr.data-e2e]="'create-app-wizzard-3'">
|
||||
<div class="content">
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="name" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="appType">
|
||||
<mat-option *ngFor="let appType of appTypes" [value]="appType">
|
||||
{{ appType.titleI18nKey | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<ng-container *ngIf="formappType?.value?.createType === AppCreateType.OIDC">
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.OIDC.GRANTTYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="grantTypesList" multiple>
|
||||
<mat-option *ngFor="let grant of oidcGrantTypes" [value]="grant.type">
|
||||
{{ 'APP.OIDC.GRANT.' + grant.type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.OIDC.RESPONSETYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="responseTypesList" multiple>
|
||||
<mat-option *ngFor="let type of oidcResponseTypes" [value]="type.type">
|
||||
{{ 'APP.OIDC.RESPONSE.' + type.type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</ng-container>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="formfield">
|
||||
<cnsl-label>{{ 'APP.AUTHMETHOD' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="authMethodType">
|
||||
<mat-option *ngFor="let type of authMethodTypes" [value]="type.type">
|
||||
<span *ngIf="type.oidc">{{ 'APP.OIDC.AUTHMETHOD.' + type.type | translate }}</span>
|
||||
<span *ngIf="type.api">{{ 'APP.API.AUTHMETHOD.' + type.type | translate }}</span>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<div class="content" *ngIf="formappType?.value?.createType === AppCreateType.OIDC">
|
||||
<div class="formfield full-width">
|
||||
<cnsl-redirect-uris
|
||||
class="redirect-section"
|
||||
[canWrite]="true"
|
||||
(changedUris)="oidcAppRequest.redirectUrisList = $any($event)"
|
||||
[urisList]="oidcAppRequest.redirectUrisList"
|
||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<cnsl-redirect-uris
|
||||
class="redirect-section"
|
||||
[canWrite]="true"
|
||||
(changedUris)="oidcAppRequest.postLogoutRedirectUrisList = $any($event)"
|
||||
[urisList]="oidcAppRequest.postLogoutRedirectUrisList"
|
||||
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
[isNative]="oidcAppRequest.appType === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
class="continue-button"
|
||||
[disabled]="form.invalid"
|
||||
cdkFocusInitial
|
||||
type="submit"
|
||||
>
|
||||
{{ 'ACTIONS.CREATE' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
class="continue-button"
|
||||
[disabled]="form.invalid"
|
||||
cdkFocusInitial
|
||||
type="submit"
|
||||
>
|
||||
{{ 'ACTIONS.CREATE' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-create-layout>
|
||||
|
||||
@@ -12,122 +12,101 @@ p.desc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.abort-container {
|
||||
.name-formfield {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.app-create-container {
|
||||
padding-top: 2rem;
|
||||
|
||||
.progress-bar {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-right {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.stepper {
|
||||
background: inherit !important;
|
||||
margin: 0 -1.5rem;
|
||||
|
||||
.formfield {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-size: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.step-description {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.checkbox {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.app-create-actions {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
.abort {
|
||||
font-size: 1.2rem;
|
||||
margin-left: 2rem;
|
||||
.bck-button {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.abort-2 {
|
||||
font-size: 1.2rem;
|
||||
margin-left: 2rem;
|
||||
white-space: nowrap;
|
||||
.create-button {
|
||||
padding: 0.5rem 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.app-create-content {
|
||||
padding-left: 4.5rem;
|
||||
|
||||
.name-formfield {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.app-create-container {
|
||||
padding-top: 2rem;
|
||||
|
||||
.progress-bar {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-right {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.stepper {
|
||||
background: inherit !important;
|
||||
margin: 0 -1.5rem;
|
||||
.dev {
|
||||
.content {
|
||||
display: flex;
|
||||
margin: 0 -0.5rem;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
|
||||
.formfield {
|
||||
max-width: 400px;
|
||||
}
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
margin: 0 0.5rem;
|
||||
|
||||
.step-title {
|
||||
font-size: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.step-description {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.checkbox {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.app-create-actions {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.bck-button {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.create-button {
|
||||
padding: 0.5rem 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.dev {
|
||||
.content {
|
||||
display: flex;
|
||||
margin: 0 -0.5rem;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
|
||||
.formfield {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
margin: 0 0.5rem;
|
||||
|
||||
&.full-width {
|
||||
flex-basis: 80%;
|
||||
}
|
||||
&.full-width {
|
||||
flex-basis: 80%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.continue-button {
|
||||
margin-top: 3rem;
|
||||
display: block;
|
||||
padding: 0.5rem 4rem;
|
||||
}
|
||||
.continue-button {
|
||||
margin-top: 3rem;
|
||||
display: block;
|
||||
padding: 0.5rem 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,150 +1,90 @@
|
||||
<cnsl-top-view title="{{app?.name}}"
|
||||
[hasActions]="isZitadel === false && (['project.app.write:'+projectId, 'project.app.write'] | hasRole | async)"
|
||||
docLink="https://docs.zitadel.com/docs/guides/basics/projects"
|
||||
[sub]="app?.oidcConfig ? ('APP.OIDC.APPTYPE.'+app?.oidcConfig?.appType | translate): 'API'"
|
||||
[isActive]="app?.state === AppState.APP_STATE_ACTIVE" [isInactive]="app?.state === AppState.APP_STATE_INACTIVE"
|
||||
stateTooltip="{{('APP.PAGES.DETAIL.STATE.'+app?.state) | translate}}">
|
||||
<ng-template topActions cnslHasRole [hasRole]="['project.app.write:'+projectId, 'project.app.write']">
|
||||
<div class="regen-secret"
|
||||
*ngIf="isZitadel === false && this.app?.oidcConfig && (currentAuthMethod === 'CODE' || currentAuthMethod === 'POST')">
|
||||
<button type="button" [disabled]="!canWrite" mat-menu-item
|
||||
(click)="regenerateOIDCClientSecret()">{{'APP.OIDC.REGENERATESECRET' | translate}}</button>
|
||||
<cnsl-top-view
|
||||
title="{{ app?.name }}"
|
||||
[hasActions]="isZitadel === false && (['project.app.write:' + projectId, 'project.app.write'] | hasRole | async)"
|
||||
docLink="https://docs.zitadel.ch/docs/guides/basics/projects"
|
||||
[sub]="app?.oidcConfig ? ('APP.OIDC.APPTYPE.' + app?.oidcConfig?.appType | translate) : 'API'"
|
||||
[isActive]="app?.state === AppState.APP_STATE_ACTIVE"
|
||||
[isInactive]="app?.state === AppState.APP_STATE_INACTIVE"
|
||||
stateTooltip="{{ 'APP.PAGES.DETAIL.STATE.' + app?.state | translate }}"
|
||||
>
|
||||
<ng-template topActions cnslHasRole [hasRole]="['project.app.write:' + projectId, 'project.app.write']">
|
||||
<div
|
||||
class="regen-secret"
|
||||
*ngIf="isZitadel === false && this.app?.oidcConfig && (currentAuthMethod === 'CODE' || currentAuthMethod === 'POST')"
|
||||
>
|
||||
<button type="button" [disabled]="!canWrite" mat-menu-item (click)="regenerateOIDCClientSecret()">
|
||||
{{ 'APP.OIDC.REGENERATESECRET' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="regen-secret" *ngIf="isZitadel === false && this.app?.apiConfig && currentAuthMethod === 'BASIC'">
|
||||
<button [disabled]="!canWrite" mat-menu-item (click)="regenerateAPIClientSecret()">{{'APP.API.REGENERATESECRET' |
|
||||
translate}}</button>
|
||||
<button [disabled]="!canWrite" mat-menu-item (click)="regenerateAPIClientSecret()">
|
||||
{{ 'APP.API.REGENERATESECRET' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button *ngIf="isZitadel === false" mat-menu-item (click)="openNameDialog()" aria-label="Edit project name">
|
||||
{{'ACTIONS.RENAME' | translate}}
|
||||
{{ 'ACTIONS.RENAME' | translate }}
|
||||
</button>
|
||||
<button mat-menu-item *ngIf="isZitadel === false && app?.state !== AppState.APP_STATE_INACTIVE"
|
||||
(click)="changeState(AppState.APP_STATE_INACTIVE)">
|
||||
{{'ACTIONS.DEACTIVATE' | translate}}
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngIf="isZitadel === false && app?.state !== AppState.APP_STATE_INACTIVE"
|
||||
(click)="changeState(AppState.APP_STATE_INACTIVE)"
|
||||
>
|
||||
{{ 'ACTIONS.DEACTIVATE' | translate }}
|
||||
</button>
|
||||
<button mat-menu-item *ngIf="isZitadel === false && app?.state === AppState.APP_STATE_INACTIVE"
|
||||
(click)="changeState(AppState.APP_STATE_ACTIVE)">
|
||||
{{'ACTIONS.REACTIVATE' | translate}}
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngIf="isZitadel === false && app?.state === AppState.APP_STATE_INACTIVE"
|
||||
(click)="changeState(AppState.APP_STATE_ACTIVE)"
|
||||
>
|
||||
{{ 'ACTIONS.REACTIVATE' | translate }}
|
||||
</button>
|
||||
<ng-template cnslHasRole [hasRole]="['project.app.delete:'+projectId, 'project.app.delete']">
|
||||
<button *ngIf="isZitadel === false" mat-menu-item matTooltip="{{'APP.PAGES.DELETE' | translate}}"
|
||||
(click)="deleteApp()">
|
||||
<span [style.color]="'var(--warn)'">{{'APP.PAGES.DELETE' | translate}}</span>
|
||||
<ng-template cnslHasRole [hasRole]="['project.app.delete:' + projectId, 'project.app.delete']">
|
||||
<button
|
||||
*ngIf="isZitadel === false"
|
||||
mat-menu-item
|
||||
matTooltip="{{ 'APP.PAGES.DELETE' | translate }}"
|
||||
(click)="deleteApp()"
|
||||
>
|
||||
<span [style.color]="'var(--warn)'">{{ 'APP.PAGES.DELETE' | translate }}</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
<span *ngIf="errorMessage" class="app-err-container">{{errorMessage}}</span>
|
||||
<span *ngIf="errorMessage" class="app-err-container">{{ errorMessage }}</span>
|
||||
|
||||
<cnsl-info-row topContent *ngIf="app" [app]="app"></cnsl-info-row>
|
||||
</cnsl-top-view>
|
||||
|
||||
<div class="max-width-container">
|
||||
<cnsl-auth-method-radio *ngIf="authMethods && initialAuthMethod && (app?.oidcConfig || app?.apiConfig)"
|
||||
[authMethods]="authMethods" [selected]="initialAuthMethod" [current]="currentAuthMethod"
|
||||
[isOIDC]="app?.oidcConfig !== undefined" (selectedMethod)="setPartialConfigFromAuthMethod($event)">
|
||||
</cnsl-auth-method-radio>
|
||||
<div class="compliance" *ngIf="app?.oidcConfig?.complianceProblemsList && app.oidcConfig?.complianceProblemsList?.length">
|
||||
<h2 class="compliance-title">{{ 'APP.COMPLIANCE' | translate }}</h2>
|
||||
<cnsl-info-section class="problem" [type]="InfoSectionType.ALERT">
|
||||
<ul style="margin: 0">
|
||||
<li style="margin: 0 0 0.5rem 0" *ngFor="let problem of app.oidcConfig?.complianceProblemsList || []">
|
||||
{{ problem.localizedMessage }}
|
||||
</li>
|
||||
</ul>
|
||||
</cnsl-info-section>
|
||||
</div>
|
||||
|
||||
<div class="app-main-content">
|
||||
<cnsl-meta-layout>
|
||||
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList">
|
||||
<ng-container *ngIf="currentSetting === 'redirect-uris'">
|
||||
<cnsl-card title=" {{ 'APP.OIDC.REDIRECTSECTIONTITLE' | translate }}">
|
||||
<cnsl-info-section *ngIf="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
||||
<div class="dev-col">
|
||||
<span>{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</span>
|
||||
<mat-slide-toggle *ngIf="devMode" color="primary" class="devmode" [formControl]="devMode" name="devMode"
|
||||
matTooltip="{{'APP.OIDC.DEVMODEDESC' | translate}}">
|
||||
{{ 'APP.OIDC.DEVMODE' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</cnsl-info-section>
|
||||
<cnsl-info-section
|
||||
*ngIf="appType?.value === OIDCAppType.OIDC_APP_TYPE_WEB || appType?.value === OIDCAppType.OIDC_APP_TYPE_USER_AGENT">
|
||||
<div class="dev-col">
|
||||
<span>{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</span>
|
||||
<mat-slide-toggle *ngIf="devMode" color="primary" class="devmode" [formControl]="devMode" name="devMode"
|
||||
matTooltip="{{'APP.OIDC.DEVMODEDESC' | translate}}">
|
||||
{{ 'APP.OIDC.DEVMODE' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</cnsl-info-section>
|
||||
|
||||
<cnsl-redirect-uris *ngIf="appType?.value !== undefined" class="redirect-section" [canWrite]="canWrite"
|
||||
[devMode]="devMode?.value" [getValues]="requestRedirectValuesSubject$"
|
||||
(changedUris)="redirectUrisList = $any($event)" [urisList]="redirectUrisList"
|
||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<cnsl-redirect-uris *ngIf="appType?.value !== undefined" class="redirect-section" [canWrite]="canWrite"
|
||||
[devMode]="devMode?.value" (changedUris)="postLogoutRedirectUrisList = $any($event)"
|
||||
[urisList]="postLogoutRedirectUrisList" [getValues]="requestRedirectValuesSubject$"
|
||||
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<div class="btn-container">
|
||||
<button class="submit-button" color="primary" (click)="saveOIDCApp()" [disabled]="!canWrite"
|
||||
mat-raised-button>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'additional-origins'">
|
||||
<cnsl-card title=" {{ 'APP.ADDITIONALORIGINS' | translate }}">
|
||||
<p class="app-desc cnsl-secondary-text">{{'APP.ADDITIONALORIGINSDESC' | translate}}</p>
|
||||
<cnsl-additional-origins *ngIf="additionalOriginsList && appType && appType?.value !== undefined"
|
||||
class="app-input" [canWrite]="canWrite" [getValues]="requestRedirectValuesSubject$"
|
||||
(changedUris)="additionalOriginsListChanged($event)" [urisList]="additionalOriginsList"
|
||||
title="{{ 'APP.ORIGINS' | translate }}">
|
||||
</cnsl-additional-origins>
|
||||
|
||||
<div class="btn-container">
|
||||
<button class="submit-button" (click)="saveOIDCApp()" color="primary" [disabled]="!canWrite"
|
||||
mat-raised-button>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'urls'">
|
||||
<cnsl-card title=" {{ 'APP.URLS' | translate }}">
|
||||
<div class="app-info-row">
|
||||
<div class="app-info-wrapper" *ngFor="let environmentV of (environmentMap | keyvalue)">
|
||||
<p class="app-info-row-title cnsl-secondary-text">{{environmentV.key}}</p>
|
||||
<div class="app-copy-row">
|
||||
<div *ngIf="environmentV.value" class="environment">
|
||||
<button [disabled]="copied === environmentV.value"
|
||||
[matTooltip]="(copied !== environmentV.value ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
|
||||
cnslCopyToClipboard [valueToCopy]="environmentV.value" (copiedValue)="copied = environmentV.key">
|
||||
{{environmentV.value}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'configuration'">
|
||||
<cnsl-card *ngIf="oidcForm && app?.oidcConfig" title=" {{ 'APP.OIDC.TITLE' | translate }}">
|
||||
<form [formGroup]="oidcForm" (ngSubmit)="saveOIDCApp()">
|
||||
<div class="compliance"
|
||||
*ngIf="app?.oidcConfig?.complianceProblemsList && app.oidcConfig?.complianceProblemsList?.length">
|
||||
<h2 class="compliance-title">{{'APP.COMPLIANCE' | translate}}</h2>
|
||||
<cnsl-info-section class="problem" [type]="InfoSectionType.WARN">
|
||||
<ul style="margin: 0;">
|
||||
<li style="margin: 0 0 .5rem 0;"
|
||||
*ngFor="let problem of app.oidcConfig?.complianceProblemsList || []">
|
||||
{{problem.localizedMessage}}</li>
|
||||
</ul>
|
||||
</cnsl-info-section>
|
||||
</div>
|
||||
<div
|
||||
class="current-auth-method"
|
||||
*ngIf="currentRadioItemAuthType"
|
||||
[ngStyle]="{ background: currentRadioItemAuthType.background }"
|
||||
>
|
||||
<h3>{{ currentRadioItemAuthType.titleI18nKey | translate }}</h3>
|
||||
<p>{{ currentRadioItemAuthType.descI18nKey | translate }}</p>
|
||||
<span class="fill-space"></span>
|
||||
<button mat-icon-button (click)="changeAuthMethod()"><i class="las la-pen"></i></button>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="oidcForm" (ngSubmit)="saveOIDCApp()">
|
||||
<div class="app-oidc-content">
|
||||
<div class="app-oidc-grid">
|
||||
<cnsl-form-field class="app-formfield" appearance="outline">
|
||||
@@ -156,7 +96,7 @@
|
||||
<cnsl-label>{{ 'APP.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="appType">
|
||||
<mat-option *ngFor="let type of oidcAppTypes" [value]="type">
|
||||
{{ 'APP.OIDC.APPTYPE.'+type | translate }}
|
||||
{{ 'APP.OIDC.APPTYPE.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
@@ -165,7 +105,7 @@
|
||||
<cnsl-label>{{ 'APP.OIDC.RESPONSETYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="responseTypesList" multiple>
|
||||
<mat-option *ngFor="let type of oidcResponseTypes" [value]="type">
|
||||
{{ 'APP.OIDC.RESPONSE.'+type | translate }}
|
||||
{{ 'APP.OIDC.RESPONSE.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
@@ -174,7 +114,7 @@
|
||||
<cnsl-label>{{ 'APP.AUTHMETHOD' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="authMethodType">
|
||||
<mat-option *ngFor="let type of oidcAuthMethodType" [value]="type">
|
||||
{{ 'APP.OIDC.AUTHMETHOD.'+type | translate }}
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
@@ -183,62 +123,31 @@
|
||||
<cnsl-label>{{ 'APP.OIDC.GRANTTYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="grantTypesList" multiple>
|
||||
<mat-option *ngFor="let grant of oidcGrantTypes" [value]="grant">
|
||||
{{ 'APP.OIDC.GRANT.'+grant | translate }}
|
||||
{{ 'APP.OIDC.GRANT.' + grant | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-checkbox color="primary" class="rt" (change)="toggleRefreshToken($event)"
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
class="rt"
|
||||
(change)="toggleRefreshToken($event)"
|
||||
[disabled]="!this.grantTypesList?.value.includes(OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE)"
|
||||
[checked]="this.grantTypesList?.value.includes(OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN)">
|
||||
[checked]="this.grantTypesList?.value.includes(OIDCGrantType.OIDC_GRANT_TYPE_REFRESH_TOKEN)"
|
||||
>
|
||||
{{ 'APP.OIDC.REFRESHTOKEN' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<p class="app-full-width app-section-title">{{'APP.OIDC.TOKENSECTIONTITLE' | translate}}</p>
|
||||
|
||||
<cnsl-form-field appearance="outline" class="app-formfield">
|
||||
<cnsl-label>{{ 'APP.OIDC.TOKENTYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="accessTokenType">
|
||||
<mat-option *ngFor="let type of oidcTokenTypes" [value]="type">
|
||||
{{ 'APP.OIDC.TOKENTYPE'+type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-checkbox *ngIf="accessTokenType?.value === OIDCTokenType.OIDC_TOKEN_TYPE_JWT" class="full-width"
|
||||
formControlName="accessTokenRoleAssertion" color="primary">
|
||||
{{'APP.OIDC.ACCESSTOKENROLEASSERTION' | translate}}</mat-checkbox>
|
||||
|
||||
<cnsl-info-section class="app-full-width app-desc">
|
||||
<span>{{'APP.OIDC.ACCESSTOKENROLEASSERTION_DESCRIPTION' | translate}}</span>
|
||||
</cnsl-info-section>
|
||||
<mat-checkbox class="app-full-width" style="margin-top: 1.5rem" formControlName="idTokenRoleAssertion"
|
||||
color="primary">
|
||||
{{'APP.OIDC.IDTOKENROLEASSERTION' | translate}}</mat-checkbox>
|
||||
<cnsl-info-section class="full-width app-desc">
|
||||
<span>{{'APP.OIDC.IDTOKENROLEASSERTION_DESCRIPTION' | translate}}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<mat-checkbox class="app-full-width" style="margin-top: 1.5rem"
|
||||
formControlName="idTokenUserinfoAssertion" color="primary">
|
||||
{{'APP.OIDC.IDTOKENUSERINFOASSERTION' | translate}}</mat-checkbox>
|
||||
<cnsl-info-section class="app-full-width app-desc">
|
||||
<span>{{'APP.OIDC.IDTOKENUSERINFOASSERTION_DESCRIPTION' | translate}}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<p class="clockskew-title cnsl-secondary-text">ClockSkew</p>
|
||||
<mat-slider color="primary" formControlName="clockSkewSeconds" class="clockskew-slider" thumbLabel
|
||||
[displayWith]="formatClockSkewLabel" tickInterval=".1" min="0" [step]="1" max="5">
|
||||
</mat-slider>
|
||||
<cnsl-info-section class="app-full-width app-desc">
|
||||
<span>{{'APP.OIDC.CLOCKSKEW' | translate}}</span>
|
||||
</cnsl-info-section>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button class="submit-button" type="submit" color="primary" [disabled]="oidcForm.invalid || !canWrite"
|
||||
mat-raised-button>
|
||||
<button
|
||||
class="submit-button"
|
||||
type="submit"
|
||||
color="primary"
|
||||
[disabled]="oidcForm.invalid || !canWrite"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -246,14 +155,220 @@
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'token'">
|
||||
<cnsl-card *ngIf="oidcTokenForm && app?.oidcConfig" title=" {{ 'APP.OIDC.TOKENSECTIONTITLE' | translate }}">
|
||||
<form [formGroup]="oidcTokenForm" (ngSubmit)="saveOIDCApp()">
|
||||
<cnsl-form-field appearance="outline" class="app-formfield">
|
||||
<cnsl-label>{{ 'APP.OIDC.TOKENTYPE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="accessTokenType">
|
||||
<mat-option *ngFor="let type of oidcTokenTypes" [value]="type">
|
||||
{{ 'APP.OIDC.TOKENTYPE' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-checkbox
|
||||
*ngIf="accessTokenType?.value === OIDCTokenType.OIDC_TOKEN_TYPE_JWT"
|
||||
class="full-width"
|
||||
style="margin-top: 1.5rem"
|
||||
formControlName="accessTokenRoleAssertion"
|
||||
color="primary"
|
||||
>
|
||||
{{ 'APP.OIDC.ACCESSTOKENROLEASSERTION' | translate }}</mat-checkbox
|
||||
>
|
||||
|
||||
<cnsl-info-section class="full-width app-desc">
|
||||
<span>{{ 'APP.OIDC.ACCESSTOKENROLEASSERTION_DESCRIPTION' | translate }}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<mat-checkbox
|
||||
class="full-width"
|
||||
style="margin-top: 1.5rem"
|
||||
formControlName="idTokenRoleAssertion"
|
||||
color="primary"
|
||||
>
|
||||
{{ 'APP.OIDC.IDTOKENROLEASSERTION' | translate }}</mat-checkbox
|
||||
>
|
||||
<cnsl-info-section class="full-width app-desc">
|
||||
<span>{{ 'APP.OIDC.IDTOKENROLEASSERTION_DESCRIPTION' | translate }}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<mat-checkbox
|
||||
class="full-width"
|
||||
style="margin-top: 1.5rem"
|
||||
formControlName="idTokenUserinfoAssertion"
|
||||
color="primary"
|
||||
>
|
||||
{{ 'APP.OIDC.IDTOKENUSERINFOASSERTION' | translate }}</mat-checkbox
|
||||
>
|
||||
<cnsl-info-section class="full-width app-desc">
|
||||
<span>{{ 'APP.OIDC.IDTOKENUSERINFOASSERTION_DESCRIPTION' | translate }}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<p class="clockskew-title cnsl-secondary-text">ClockSkew</p>
|
||||
<mat-slider
|
||||
color="primary"
|
||||
formControlName="clockSkewSeconds"
|
||||
class="clockskew-slider"
|
||||
thumbLabel
|
||||
[displayWith]="formatClockSkewLabel"
|
||||
tickInterval=".1"
|
||||
min="0"
|
||||
[step]="1"
|
||||
max="5"
|
||||
>
|
||||
</mat-slider>
|
||||
<cnsl-info-section class="full-width app-desc">
|
||||
<span>{{ 'APP.OIDC.CLOCKSKEW' | translate }}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="btn-container">
|
||||
<button
|
||||
class="submit-button"
|
||||
type="submit"
|
||||
color="primary"
|
||||
[disabled]="oidcTokenForm.invalid || !canWrite"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'redirect-uris'">
|
||||
<cnsl-card title=" {{ 'APP.OIDC.REDIRECTSECTIONTITLE' | translate }}">
|
||||
<cnsl-info-section *ngIf="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
||||
<div class="dev-col">
|
||||
<span>{{ 'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate }}</span>
|
||||
<mat-slide-toggle
|
||||
*ngIf="devMode"
|
||||
color="primary"
|
||||
class="devmode"
|
||||
[formControl]="devMode"
|
||||
name="devMode"
|
||||
matTooltip="{{ 'APP.OIDC.DEVMODEDESC' | translate }}"
|
||||
>
|
||||
{{ 'APP.OIDC.DEVMODE' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</cnsl-info-section>
|
||||
<cnsl-info-section
|
||||
*ngIf="
|
||||
appType?.value === OIDCAppType.OIDC_APP_TYPE_WEB || appType?.value === OIDCAppType.OIDC_APP_TYPE_USER_AGENT
|
||||
"
|
||||
>
|
||||
<div class="dev-col">
|
||||
<span>{{ 'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate }}</span>
|
||||
<mat-slide-toggle
|
||||
*ngIf="devMode"
|
||||
color="primary"
|
||||
class="devmode"
|
||||
[formControl]="devMode"
|
||||
name="devMode"
|
||||
matTooltip="{{ 'APP.OIDC.DEVMODEDESC' | translate }}"
|
||||
>
|
||||
{{ 'APP.OIDC.DEVMODE' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</cnsl-info-section>
|
||||
|
||||
<cnsl-redirect-uris
|
||||
*ngIf="appType?.value !== undefined"
|
||||
class="redirect-section"
|
||||
[canWrite]="canWrite"
|
||||
[devMode]="devMode?.value"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
(changedUris)="redirectUrisList = $any($event)"
|
||||
[urisList]="redirectUrisList"
|
||||
title="{{ 'APP.OIDC.REDIRECT' | translate }}"
|
||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<cnsl-redirect-uris
|
||||
*ngIf="appType?.value !== undefined"
|
||||
class="redirect-section"
|
||||
[canWrite]="canWrite"
|
||||
[devMode]="devMode?.value"
|
||||
(changedUris)="postLogoutRedirectUrisList = $any($event)"
|
||||
[urisList]="postLogoutRedirectUrisList"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
||||
[isNative]="appType?.value === OIDCAppType.OIDC_APP_TYPE_NATIVE"
|
||||
>
|
||||
</cnsl-redirect-uris>
|
||||
|
||||
<div class="btn-container">
|
||||
<button class="submit-button" color="primary" (click)="saveOIDCApp()" [disabled]="!canWrite" mat-raised-button>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'additional-origins'">
|
||||
<cnsl-card title=" {{ 'APP.ADDITIONALORIGINS' | translate }}">
|
||||
<p class="app-desc cnsl-secondary-text">{{ 'APP.ADDITIONALORIGINSDESC' | translate }}</p>
|
||||
<cnsl-additional-origins
|
||||
*ngIf="additionalOriginsList && appType && appType?.value !== undefined"
|
||||
class="app-input"
|
||||
[canWrite]="canWrite"
|
||||
[getValues]="requestRedirectValuesSubject$"
|
||||
(changedUris)="additionalOriginsListChanged($event)"
|
||||
[urisList]="additionalOriginsList"
|
||||
title="{{ 'APP.ORIGINS' | translate }}"
|
||||
>
|
||||
</cnsl-additional-origins>
|
||||
|
||||
<div class="btn-container">
|
||||
<button class="submit-button" (click)="saveOIDCApp()" color="primary" [disabled]="!canWrite" mat-raised-button>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'urls'">
|
||||
<cnsl-card title=" {{ 'APP.URLS' | translate }}">
|
||||
<div class="app-info-row">
|
||||
<div class="app-info-wrapper" *ngFor="let environmentV of environmentMap | keyvalue">
|
||||
<p class="app-info-row-title cnsl-secondary-text">{{ environmentV.key }}</p>
|
||||
<div class="app-copy-row">
|
||||
<div *ngIf="environmentV.value" class="environment">
|
||||
<button
|
||||
[disabled]="copied === environmentV.value"
|
||||
[matTooltip]="(copied !== environmentV.value ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="environmentV.value"
|
||||
(copiedValue)="copied = environmentV.key"
|
||||
>
|
||||
{{ environmentV.value }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'configuration'">
|
||||
<cnsl-card *ngIf="currentAuthMethod === 'PK_JWT' && projectId && app?.id"
|
||||
title="{{ 'USER.MACHINE.KEYSTITLE' | translate }}" description="{{ 'USER.MACHINE.KEYSDESC' | translate }}">
|
||||
<cnsl-card
|
||||
*ngIf="initialAuthMethod === 'PK_JWT' && projectId && app?.id"
|
||||
title="{{ 'USER.MACHINE.KEYSTITLE' | translate }}"
|
||||
description="{{ 'USER.MACHINE.KEYSDESC' | translate }}"
|
||||
>
|
||||
<cnsl-client-keys [projectId]="projectId" [appId]="app.id"></cnsl-client-keys>
|
||||
|
||||
<div *ngIf="apiForm && app?.apiConfig" class="btn-container">
|
||||
<button class="submit-button" (click)="saveAPIApp()" color="primary"
|
||||
[disabled]="apiForm.invalid || !canWrite" mat-raised-button>
|
||||
<button
|
||||
class="submit-button"
|
||||
(click)="saveAPIApp()"
|
||||
color="primary"
|
||||
[disabled]="apiForm.invalid || !canWrite"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -261,11 +376,9 @@
|
||||
</ng-container>
|
||||
</cnsl-sidenav>
|
||||
|
||||
<!-- <cnsl-links [links]="nextLinks"></cnsl-links> -->
|
||||
|
||||
<div metainfo>
|
||||
<cnsl-changes *ngIf="app" [changeType]="ChangeType.APP" [id]="app.id" [secId]="projectId"></cnsl-changes>
|
||||
</div>
|
||||
</cnsl-meta-layout>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,11 +44,6 @@
|
||||
flex-direction: column;
|
||||
margin: 0 -0.5rem;
|
||||
|
||||
@media only screen and (min-width: 500px) {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.app-info-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -77,6 +72,7 @@
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
align-items: stretch;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
button {
|
||||
transition: opacity 0.15s ease-in-out;
|
||||
@@ -109,22 +105,53 @@
|
||||
}
|
||||
}
|
||||
|
||||
.compliance {
|
||||
padding-bottom: 1rem;
|
||||
padding-top: 0.5rem;
|
||||
border-bottom: 1px solid $divider-color;
|
||||
|
||||
.compliance-title {
|
||||
margin: 1rem 0 1rem 0;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.problem {
|
||||
font-size: 14px;
|
||||
margin: 0 0 0.5rem 0;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.app-main-content {
|
||||
border-top: 1px solid $divider-color;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
}
|
||||
margin-top: 0.5rem;
|
||||
|
||||
.compliance {
|
||||
.compliance-title {
|
||||
margin: 1rem 0 1rem 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
.current-auth-method {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
.problem {
|
||||
font-size: 14px;
|
||||
margin: 0 0 0.5rem 0;
|
||||
display: block;
|
||||
h3 {
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { AbstractControl, FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
@@ -14,7 +13,6 @@ import { take } from 'rxjs/operators';
|
||||
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 { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
|
||||
import { CnslLinks } from 'src/app/modules/links/links.component';
|
||||
import { NameDialogComponent } from 'src/app/modules/name-dialog/name-dialog.component';
|
||||
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
@@ -52,6 +50,7 @@ import {
|
||||
PKCE_METHOD,
|
||||
POST_METHOD,
|
||||
} from '../authmethods';
|
||||
import { AuthMethodDialogComponent } from './auth-method-dialog/auth-method-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-app-detail',
|
||||
@@ -103,6 +102,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
public AppState: any = AppState;
|
||||
public oidcForm!: FormGroup;
|
||||
public oidcTokenForm!: FormGroup;
|
||||
public apiForm!: FormGroup;
|
||||
|
||||
public redirectUrisList: string[] = [];
|
||||
@@ -122,7 +122,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
public requestRedirectValuesSubject$: Subject<void> = new Subject();
|
||||
public copiedKey: any = '';
|
||||
public nextLinks: Array<CnslLinks> = [];
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
public copied: string = '';
|
||||
|
||||
@@ -139,7 +138,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
private mgmtService: ManagementService,
|
||||
private authService: GrpcAuthService,
|
||||
private router: Router,
|
||||
private snackbar: MatSnackBar,
|
||||
private breadcrumbService: BreadcrumbService,
|
||||
private http: HttpClient,
|
||||
) {
|
||||
@@ -150,6 +148,9 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
grantTypesList: [{ value: [], disabled: true }],
|
||||
appType: [{ value: '', disabled: true }],
|
||||
authMethodType: [{ value: '', disabled: true }],
|
||||
});
|
||||
|
||||
this.oidcTokenForm = this.fb.group({
|
||||
accessTokenType: [{ value: '', disabled: true }],
|
||||
accessTokenRoleAssertion: [{ value: false, disabled: true }],
|
||||
idTokenRoleAssertion: [{ value: false, disabled: true }],
|
||||
@@ -212,32 +213,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
this.subscription?.unsubscribe();
|
||||
}
|
||||
|
||||
private initLinks(): void {
|
||||
this.nextLinks = [
|
||||
{
|
||||
i18nTitle: 'APP.PAGES.NEXTSTEPS.0.TITLE',
|
||||
i18nDesc: 'APP.PAGES.NEXTSTEPS.0.DESC',
|
||||
routerLink: ['/projects', this.projectId, 'roles'],
|
||||
iconClasses: 'las la-user-tag',
|
||||
},
|
||||
{
|
||||
i18nTitle: 'APP.PAGES.NEXTSTEPS.1.TITLE',
|
||||
i18nDesc: 'APP.PAGES.NEXTSTEPS.1.DESC',
|
||||
routerLink: ['/users', 'create'],
|
||||
iconClasses: 'las la-user-plus',
|
||||
},
|
||||
{
|
||||
i18nTitle: 'APP.PAGES.NEXTSTEPS.2.TITLE',
|
||||
i18nDesc: 'APP.PAGES.NEXTSTEPS.2.DESC',
|
||||
href: 'https://docs.zitadel.comm',
|
||||
iconClasses: 'las la-people-carry',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private async getData(projectId: string, appId: string): Promise<void> {
|
||||
this.initLinks();
|
||||
|
||||
this.mgmtService.getIAM().then((iam) => {
|
||||
this.isZitadel = iam.iamProjectId === this.projectId;
|
||||
});
|
||||
@@ -277,6 +253,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.settingsList = [
|
||||
{ id: 'configuration', i18nKey: 'APP.CONFIGURATION' },
|
||||
{ id: 'token', i18nKey: 'APP.TOKEN' },
|
||||
{ id: 'redirect-uris', i18nKey: 'APP.OIDC.REDIRECTSECTIONTITLE' },
|
||||
{ id: 'additional-origins', i18nKey: 'APP.ADDITIONALORIGINS' },
|
||||
{ id: 'urls', i18nKey: 'APP.URLS' },
|
||||
@@ -317,6 +294,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (allowed) {
|
||||
this.oidcForm.enable();
|
||||
this.oidcTokenForm.enable();
|
||||
this.apiForm.enable();
|
||||
}
|
||||
|
||||
@@ -332,10 +310,11 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (this.app.oidcConfig?.clockSkew) {
|
||||
const inSecs = this.app.oidcConfig?.clockSkew.seconds + this.app.oidcConfig?.clockSkew.nanos / 100000;
|
||||
this.oidcForm.controls['clockSkewSeconds'].setValue(inSecs);
|
||||
this.oidcTokenForm.controls['clockSkewSeconds'].setValue(inSecs);
|
||||
}
|
||||
if (this.app.oidcConfig) {
|
||||
this.oidcForm.patchValue(this.app.oidcConfig);
|
||||
this.oidcTokenForm.patchValue(this.app.oidcConfig);
|
||||
}
|
||||
if (this.app.apiConfig) {
|
||||
this.apiForm.patchValue(this.app.apiConfig);
|
||||
@@ -350,8 +329,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
} else {
|
||||
this.authMethods = this.authMethods.filter((element) => element !== CUSTOM_METHOD);
|
||||
}
|
||||
|
||||
this.showSaveSnack();
|
||||
});
|
||||
|
||||
this.apiForm.valueChanges.subscribe((apiConfig) => {
|
||||
@@ -363,8 +340,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
} else {
|
||||
this.authMethods = this.authMethods.filter((element) => element !== CUSTOM_METHOD);
|
||||
}
|
||||
|
||||
this.showSaveSnack();
|
||||
});
|
||||
}
|
||||
})
|
||||
@@ -377,20 +352,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
this.docs = await this.mgmtService.getOIDCInformation();
|
||||
}
|
||||
|
||||
private async showSaveSnack(): Promise<void> {
|
||||
const message = await this.translate.get('APP.TOAST.CONFIGCHANGED').toPromise();
|
||||
const action = await this.translate.get('ACTIONS.SAVENOW').toPromise();
|
||||
|
||||
const snackRef = this.snackbar.open(message, action, { duration: 5000, verticalPosition: 'top' });
|
||||
snackRef.onAction().subscribe(() => {
|
||||
if (this.app.oidcConfig) {
|
||||
this.saveOIDCApp();
|
||||
} else if (this.app.apiConfig) {
|
||||
this.saveAPIApp();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getAuthMethodOptions(type: string): void {
|
||||
if (type === 'OIDC') {
|
||||
switch (this.app.oidcConfig?.appType) {
|
||||
@@ -426,6 +387,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
(partialConfig.oidc as Partial<OIDCConfig.AsObject>).authMethodType ?? OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE;
|
||||
|
||||
this.oidcForm.patchValue(this.app.oidcConfig);
|
||||
this.oidcTokenForm.patchValue(this.app.oidcConfig);
|
||||
} else if (partialConfig && partialConfig.api && this.app.apiConfig) {
|
||||
this.app.apiConfig.authMethodType =
|
||||
(partialConfig.api as Partial<APIConfig.AsObject>).authMethodType ?? APIAuthMethodType.API_AUTH_METHOD_TYPE_BASIC;
|
||||
@@ -444,6 +406,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp && this.projectId && this.app.id) {
|
||||
this.mgmtService
|
||||
@@ -519,40 +482,53 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
this.requestRedirectValuesSubject$.next();
|
||||
if (this.oidcForm.valid) {
|
||||
if (this.app.oidcConfig) {
|
||||
// configuration
|
||||
this.app.oidcConfig.responseTypesList = this.responseTypesList?.value;
|
||||
this.app.oidcConfig.grantTypesList = this.grantTypesList?.value;
|
||||
this.app.oidcConfig.appType = this.appType?.value;
|
||||
this.app.oidcConfig.authMethodType = this.authMethodType?.value;
|
||||
this.app.oidcConfig.redirectUrisList = this.redirectUrisList;
|
||||
this.app.oidcConfig.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
||||
this.app.oidcConfig.additionalOriginsList = this.additionalOriginsList;
|
||||
this.app.oidcConfig.devMode = this.devMode?.value;
|
||||
|
||||
// token
|
||||
this.app.oidcConfig.accessTokenType = this.accessTokenType?.value;
|
||||
this.app.oidcConfig.accessTokenRoleAssertion = this.accessTokenRoleAssertion?.value;
|
||||
this.app.oidcConfig.idTokenRoleAssertion = this.idTokenRoleAssertion?.value;
|
||||
this.app.oidcConfig.idTokenUserinfoAssertion = this.idTokenUserinfoAssertion?.value;
|
||||
|
||||
// redirects
|
||||
this.app.oidcConfig.redirectUrisList = this.redirectUrisList;
|
||||
this.app.oidcConfig.postLogoutRedirectUrisList = this.postLogoutRedirectUrisList;
|
||||
this.app.oidcConfig.additionalOriginsList = this.additionalOriginsList;
|
||||
this.app.oidcConfig.devMode = this.devMode?.value;
|
||||
|
||||
const req = new UpdateOIDCAppConfigRequest();
|
||||
req.setProjectId(this.projectId);
|
||||
req.setAppId(this.app.id);
|
||||
req.setRedirectUrisList(this.app.oidcConfig.redirectUrisList);
|
||||
|
||||
// configuration
|
||||
req.setResponseTypesList(this.app.oidcConfig.responseTypesList);
|
||||
req.setAdditionalOriginsList(this.app.oidcConfig.additionalOriginsList);
|
||||
req.setAuthMethodType(this.app.oidcConfig.authMethodType);
|
||||
req.setPostLogoutRedirectUrisList(this.app.oidcConfig.postLogoutRedirectUrisList);
|
||||
req.setGrantTypesList(this.app.oidcConfig.grantTypesList);
|
||||
req.setAppType(this.app.oidcConfig.appType);
|
||||
req.setDevMode(this.app.oidcConfig.devMode);
|
||||
|
||||
// token
|
||||
req.setAccessTokenType(this.app.oidcConfig.accessTokenType);
|
||||
req.setAccessTokenRoleAssertion(this.app.oidcConfig.accessTokenRoleAssertion);
|
||||
req.setIdTokenRoleAssertion(this.app.oidcConfig.idTokenRoleAssertion);
|
||||
req.setIdTokenUserinfoAssertion(this.app.oidcConfig.idTokenUserinfoAssertion);
|
||||
|
||||
// redirects
|
||||
req.setRedirectUrisList(this.app.oidcConfig.redirectUrisList);
|
||||
req.setAdditionalOriginsList(this.app.oidcConfig.additionalOriginsList);
|
||||
req.setPostLogoutRedirectUrisList(this.app.oidcConfig.postLogoutRedirectUrisList);
|
||||
req.setDevMode(this.app.oidcConfig.devMode);
|
||||
|
||||
if (this.clockSkewSeconds?.value) {
|
||||
const dur = new Duration();
|
||||
dur.setSeconds(Math.floor(this.clockSkewSeconds?.value));
|
||||
dur.setNanos(Math.floor(this.clockSkewSeconds?.value % 1) * 10000);
|
||||
req.setClockSkew(dur);
|
||||
}
|
||||
|
||||
this.mgmtService
|
||||
.updateOIDCAppConfig(req)
|
||||
.then(() => {
|
||||
@@ -622,6 +598,24 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
public changeAuthMethod(): void {
|
||||
const ref = this.dialog.open(AuthMethodDialogComponent, {
|
||||
data: {
|
||||
radioItemAuthType: this.currentRadioItemAuthType,
|
||||
initialAuthMethod: this.initialAuthMethod,
|
||||
currentAuthMethod: this.currentAuthMethod,
|
||||
authMethods: this.authMethods,
|
||||
isOIDC: this.app?.oidcConfig !== undefined,
|
||||
},
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe((authMethod: string) => {
|
||||
if (authMethod) {
|
||||
this.setPartialConfigFromAuthMethod(authMethod);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public regenerateAPIClientSecret(): void {
|
||||
this.mgmtService
|
||||
.regenerateAPIClientSecret(this.app.id, this.projectId)
|
||||
@@ -639,6 +633,10 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
public get currentRadioItemAuthType(): RadioItemAuthType | undefined {
|
||||
return this.authMethods.find((i) => i.key === this.initialAuthMethod);
|
||||
}
|
||||
|
||||
public navigateBack(): void {
|
||||
this._location.back();
|
||||
}
|
||||
@@ -672,22 +670,22 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public get accessTokenType(): AbstractControl | null {
|
||||
return this.oidcForm.get('accessTokenType');
|
||||
return this.oidcTokenForm.get('accessTokenType');
|
||||
}
|
||||
|
||||
public get idTokenRoleAssertion(): AbstractControl | null {
|
||||
return this.oidcForm.get('idTokenRoleAssertion');
|
||||
return this.oidcTokenForm.get('idTokenRoleAssertion');
|
||||
}
|
||||
|
||||
public get accessTokenRoleAssertion(): AbstractControl | null {
|
||||
return this.oidcForm.get('accessTokenRoleAssertion');
|
||||
return this.oidcTokenForm.get('accessTokenRoleAssertion');
|
||||
}
|
||||
|
||||
public get idTokenUserinfoAssertion(): AbstractControl | null {
|
||||
return this.oidcForm.get('idTokenUserinfoAssertion');
|
||||
return this.oidcTokenForm.get('idTokenUserinfoAssertion');
|
||||
}
|
||||
|
||||
public get clockSkewSeconds(): AbstractControl | null {
|
||||
return this.oidcForm.get('clockSkewSeconds');
|
||||
return this.oidcTokenForm.get('clockSkewSeconds');
|
||||
}
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<h1 mat-dialog-title>
|
||||
<span>{{ 'USER.CODEDIALOG.TITLE' | translate }} {{ data?.number }}</span>
|
||||
</h1>
|
||||
<p class="desc cnsl-secondary-text">{{ 'USER.CODEDIALOG.DESCRIPTION' | translate }}</p>
|
||||
<div mat-dialog-content>
|
||||
<cnsl-auth-method-radio
|
||||
[authMethods]="data.authMethods"
|
||||
[selected]="data.initialAuthMethod"
|
||||
[current]="data.currentAuthMethod"
|
||||
[isOIDC]="data.isOIDC"
|
||||
(selectedMethod)="authmethod = $event"
|
||||
[compact]="true"
|
||||
>
|
||||
</cnsl-auth-method-radio>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button color="primary" mat-stroked-button class="ok-button" (click)="closeDialog()">
|
||||
{{ 'ACTIONS.CLOSE' | translate }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
[disabled]="!authmethod"
|
||||
cdkFocusInitial
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
class="ok-button"
|
||||
(click)="closeDialogWithMethod()"
|
||||
>
|
||||
{{ 'ACTIONS.SELECT' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.formfield {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.ok-button {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { AuthMethodDialogComponent } from './auth-method-dialog.component';
|
||||
|
||||
describe('AuthMethodDialogComponent', () => {
|
||||
let component: AuthMethodDialogComponent;
|
||||
let fixture: ComponentFixture<AuthMethodDialogComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AuthMethodDialogComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AuthMethodDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-auth-method-dialog',
|
||||
templateUrl: './auth-method-dialog.component.html',
|
||||
styleUrls: ['./auth-method-dialog.component.scss'],
|
||||
})
|
||||
export class AuthMethodDialogComponent {
|
||||
public authmethod: string = '';
|
||||
constructor(public dialogRef: MatDialogRef<AuthMethodDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {
|
||||
this.authmethod = data.initialAuthMethod;
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
public closeDialogWithMethod(): void {
|
||||
this.dialogRef.close(this.authmethod);
|
||||
}
|
||||
}
|
||||
@@ -23,10 +23,10 @@ import { AppRadioModule } from 'src/app/modules/app-radio/app-radio.module';
|
||||
import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { ChangesModule } from 'src/app/modules/changes/changes.module';
|
||||
import { ClientKeysModule } from 'src/app/modules/client-keys/client-keys.module';
|
||||
import { CreateLayoutModule } from 'src/app/modules/create-layout/create-layout.module';
|
||||
import { InfoRowModule } from 'src/app/modules/info-row/info-row.module';
|
||||
import { InfoSectionModule } from 'src/app/modules/info-section/info-section.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { LinksModule } from 'src/app/modules/links/links.module';
|
||||
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
|
||||
import { NameDialogModule } from 'src/app/modules/name-dialog/name-dialog.module';
|
||||
import { SidenavModule } from 'src/app/modules/sidenav/sidenav.module';
|
||||
@@ -38,6 +38,7 @@ import { RedirectPipeModule } from 'src/app/pipes/redirect-pipe/redirect-pipe.mo
|
||||
import { AdditionalOriginsComponent } from './additional-origins/additional-origins.component';
|
||||
import { AppCreateComponent } from './app-create/app-create.component';
|
||||
import { AppDetailComponent } from './app-detail/app-detail.component';
|
||||
import { AuthMethodDialogComponent } from './app-detail/auth-method-dialog/auth-method-dialog.component';
|
||||
import { AppSecretDialogComponent } from './app-secret-dialog/app-secret-dialog.component';
|
||||
import { AppsRoutingModule } from './apps-routing.module';
|
||||
import { RedirectUrisComponent } from './redirect-uris/redirect-uris.component';
|
||||
@@ -49,12 +50,12 @@ import { RedirectUrisComponent } from './redirect-uris/redirect-uris.component';
|
||||
AppSecretDialogComponent,
|
||||
RedirectUrisComponent,
|
||||
AdditionalOriginsComponent,
|
||||
AuthMethodDialogComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
A11yModule,
|
||||
RedirectPipeModule,
|
||||
LinksModule,
|
||||
NameDialogModule,
|
||||
AppRadioModule,
|
||||
AppsRoutingModule,
|
||||
@@ -66,6 +67,7 @@ import { RedirectUrisComponent } from './redirect-uris/redirect-uris.component';
|
||||
HasRoleModule,
|
||||
SidenavModule,
|
||||
MatChipsModule,
|
||||
CreateLayoutModule,
|
||||
ClientKeysModule,
|
||||
HasRolePipeModule,
|
||||
MatIconModule,
|
||||
|
||||
Reference in New Issue
Block a user