mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-04 21:32:15 +00:00
278 lines
15 KiB
HTML
278 lines
15 KiB
HTML
<app-meta-layout>
|
|
<div class="enlarged-container">
|
|
<div class="head">
|
|
<a [routerLink]="['/projects', projectId]" mat-icon-button>
|
|
<mat-icon class="icon">arrow_back</mat-icon>
|
|
</a>
|
|
<div class="title-col">
|
|
<h1>{{app?.name}}</h1>
|
|
<span *ngIf="app?.oidcConfig">{{'APP.OIDC.APPTYPE.'+app?.oidcConfig?.appType |
|
|
translate}}</span>
|
|
<span *ngIf="app?.apiConfig">API</span>
|
|
</div>
|
|
<ng-container *ngIf="isZitadel === false">
|
|
<ng-template appHasRole [appHasRole]="['project.app.write:'+projectId, 'project.app.write']">
|
|
<button *ngIf="!editState" matTooltip="{{'ACTIONS.EDIT' | translate}}" mat-icon-button
|
|
(click)="editState = !editState" aria-label="edit app name">
|
|
<i class="las la-edit"></i>
|
|
</button>
|
|
<button *ngIf="editState" (click)="saveApp()" [disabled]="appNameForm.invalid || name?.disabled"
|
|
mat-icon-button>
|
|
<i class="las la-save"></i>
|
|
</button>
|
|
</ng-template>
|
|
|
|
<ng-template appHasRole [appHasRole]="['project.app.delete:'+projectId, 'project.app.delete']">
|
|
<button matTooltip="{{'ACTIONS.DELETE' | translate}}" color="warn" mat-icon-button
|
|
(click)="deleteApp()" aria-label="delete app">
|
|
<i class="las la-trash"></i>
|
|
</button>
|
|
</ng-template>
|
|
</ng-container>
|
|
|
|
<p class="desc">{{ 'APP.PAGES.DESCRIPTION' | translate }}</p>
|
|
<p *ngIf="isZitadel" class="zitadel-warning">{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}</p>
|
|
</div>
|
|
|
|
<span *ngIf="errorMessage" class="err-container">{{errorMessage}}</span>
|
|
|
|
<form *ngIf="app && editState" [formGroup]="appNameForm">
|
|
<div class="name-content">
|
|
<mat-button-toggle-group formControlName="state" class="toggle" (change)="changeState($event)">
|
|
<mat-button-toggle [value]="AppState.APP_STATE_INACTIVE"
|
|
matTooltip="{{ 'ACTIONS.DEACTIVATE' | translate}}">
|
|
{{'APP.PAGES.DETAIL.STATE.'+AppState.APP_STATE_INACTIVE | translate}}
|
|
</mat-button-toggle>
|
|
<mat-button-toggle [value]="AppState.APPSTATE_ACTIVE"
|
|
matTooltip="{{ 'ACTIONS.REACTIVATE' | translate}}">
|
|
{{'APP.PAGES.DETAIL.STATE.'+AppState.APP_STATE_ACTIVE | translate}}
|
|
</mat-button-toggle>
|
|
</mat-button-toggle-group>
|
|
|
|
<cnsl-form-field class="name-field">
|
|
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
|
<input cnslInput formControlName="name" />
|
|
</cnsl-form-field>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="environment-wrapper">
|
|
<div class="environment" *ngIf="app?.oidcConfig?.clientId">
|
|
<span class="key">{{'APP.OIDC.INFO.CLIENTID' | translate}}</span>
|
|
<div class="environment-row">
|
|
<span>{{this.app.oidcConfig?.clientId}}</span>
|
|
<button color="primary" [disabled]="copiedKey == this.app.oidcConfig?.clientId"
|
|
[matTooltip]="(copiedKey != this.app.oidcConfig?.clientId ? 'USER.PAGES.COPY' : 'USER.PAGES.COPIED' ) | translate"
|
|
appCopyToClipboard [valueToCopy]="this.app.oidcConfig?.clientId"
|
|
(copiedValue)="copiedKey = 'clientId'" mat-icon-button>
|
|
<i *ngIf="copiedKey != 'clientId'" class="las la-clipboard"></i>
|
|
<i *ngIf="copiedKey == 'clientId'" class="las la-clipboard-check"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<ng-container *ngFor="let environmentV of (environmentMap | keyvalue)">
|
|
<div *ngIf="environmentV.value" class="environment">
|
|
<span class="key">{{environmentV.key}}</span>
|
|
<div class="environment-row">
|
|
<span>{{environmentV.value}}</span>
|
|
<button color="primary" [disabled]="copiedKey == environmentV.value"
|
|
[matTooltip]="(copiedKey != environmentV.value ? 'USER.PAGES.COPY' : 'USER.PAGES.COPIED' ) | translate"
|
|
appCopyToClipboard [valueToCopy]="environmentV.value"
|
|
(copiedValue)="copiedKey = environmentV.key" mat-icon-button>
|
|
<i *ngIf="copiedKey != environmentV.key" class="las la-clipboard"></i>
|
|
<i *ngIf="copiedKey == environmentV.key" class="las la-clipboard-check"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</ng-container>
|
|
</div>
|
|
|
|
<div class="compliance"
|
|
*ngIf="app?.oidcConfig?.complianceProblemsList && app.oidcConfig?.complianceProblemsList?.length">
|
|
<cnsl-info-section class="problem" type="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="content" *ngIf="app?.oidcConfig">
|
|
<h3 class="full-width section-title">{{'APP.OIDC.REDIRECTSECTIONTITLE' | translate}}</h3>
|
|
|
|
<mat-slide-toggle color="primary" class="devmode" [formControl]="devMode" name="devMode"
|
|
matTooltip="{{'APP.OIDC.DEVMODEDESC' | translate}}">
|
|
{{ 'APP.OIDC.DEVMODE' | translate }}
|
|
</mat-slide-toggle>
|
|
|
|
<cnsl-info-section class="step-description" *ngIf="appType?.value == OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
|
<span>{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</span>
|
|
</cnsl-info-section>
|
|
|
|
<cnsl-info-section class="step-description"
|
|
*ngIf="OIDCAppType?.value == OIDCAppType.OIDC_APP_TYPE_WEB || appType?.value == OIDCAppType.OIDC_APP_TYPE_USER_AGENT">
|
|
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}
|
|
</cnsl-info-section>
|
|
|
|
<div style="margin: .5rem" class="divider"></div>
|
|
<cnsl-redirect-uris *ngIf="appType?.value !== undefined" class="redirect-section" [canWrite]="canWrite"
|
|
[devMode]="devMode?.value" [getValues]="requestRedirectValuesSubject$"
|
|
(changedUris)="redirectUrisList = $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 = $event"
|
|
[urisList]="postLogoutRedirectUrisList" [getValues]="requestRedirectValuesSubject$"
|
|
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}"
|
|
[isNative]="appType?.value == OIDCAppType.OIDC_APP_TYPE_NATIVE">
|
|
</cnsl-redirect-uris>
|
|
</div>
|
|
|
|
<app-auth-method-radio *ngIf="authMethods && initialAuthMethod && (app?.oidcConfig || app?.apiConfig)"
|
|
[authMethods]="authMethods" [selected]="initialAuthMethod" [current]="currentAuthMethod"
|
|
[isOIDC]="app?.oidcConfig !== undefined" (selectedMethod)="setPartialConfigFromAuthMethod($event)">
|
|
</app-auth-method-radio>
|
|
|
|
<app-card *ngIf="currentAuthMethod == 'PK_JWT' && projectId && app?.id" [expanded]="false"
|
|
title="{{ 'USER.MACHINE.KEYSTITLE' | translate }}" description="{{ 'USER.MACHINE.KEYSDESC' | translate }}">
|
|
<app-client-keys [projectId]="projectId" [appId]="app.id"></app-client-keys>
|
|
</app-card>
|
|
|
|
<div *ngIf="oidcForm && app?.apiConfig" class="btn-container">
|
|
<button class="submit-button" (click)="saveAPIApp()" color="primary"
|
|
[disabled]="apiForm.invalid || !canWrite" mat-raised-button>
|
|
{{ 'ACTIONS.SAVE' | translate }}
|
|
</button>
|
|
</div>
|
|
|
|
<div *ngIf="currentAuthMethod == 'BASIC'">
|
|
<button [disabled]="!canWrite" mat-stroked-button
|
|
(click)="regenerateAPIClientSecret()">{{'APP.API.REGENERATESECRET' | translate}}</button>
|
|
</div>
|
|
|
|
|
|
<form *ngIf="oidcForm && app?.oidcConfig" [formGroup]="oidcForm" (ngSubmit)="saveOIDCApp()">
|
|
<app-card title=" {{ 'APP.OIDC.TITLE' | translate }}" *ngIf="app && app.oidcConfig" [expanded]="false">
|
|
<div card-actions *ngIf="currentAuthMethod == 'CODE' || currentAuthMethod == 'POST'">
|
|
<button type="button" [disabled]="!canWrite" mat-stroked-button
|
|
(click)="regenerateOIDCClientSecret()">{{'APP.OIDC.REGENERATESECRET' | translate}}</button>
|
|
</div>
|
|
|
|
<div class="content">
|
|
<cnsl-form-field class="formfield" appearance="outline">
|
|
<cnsl-label>{{ 'APP.OIDC.CLIENTID' | translate }}</cnsl-label>
|
|
<input cnslInput formControlName="clientId" />
|
|
</cnsl-form-field>
|
|
|
|
<cnsl-form-field class="formfield" appearance="outline">
|
|
<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 }}
|
|
</mat-option>
|
|
</mat-select>
|
|
</cnsl-form-field>
|
|
|
|
<cnsl-form-field class="formfield" appearance="outline">
|
|
<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 }}
|
|
</mat-option>
|
|
</mat-select>
|
|
</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 type of oidcAppTypes" [value]="type">
|
|
{{ 'APP.OIDC.APPTYPE.'+type | translate }}
|
|
</mat-option>
|
|
</mat-select>
|
|
</cnsl-form-field>
|
|
|
|
<cnsl-form-field appearance="outline" class="formfield">
|
|
<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 }}
|
|
</mat-option>
|
|
</mat-select>
|
|
</cnsl-form-field>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<p class="full-width section-title">{{'APP.OIDC.TOKENSECTIONTITLE' | translate}}</p>
|
|
|
|
<cnsl-form-field appearance="outline" class="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.OIDCTOKENTYPE_JWT" class="full-width"
|
|
formControlName="accessTokenRoleAssertion" color="primary">
|
|
{{'APP.OIDC.ACCESSTOKENROLEASSERTION' | translate}}</mat-checkbox>
|
|
|
|
<cnsl-info-section class="full-width desc">
|
|
<span>{{'APP.OIDC.ACCESSTOKENROLEASSERTION_DESCRIPTION' | translate}}</span>
|
|
</cnsl-info-section>
|
|
<mat-checkbox class="full-width" style="margin-bottom: .5rem" formControlName="idTokenRoleAssertion"
|
|
color="primary">
|
|
{{'APP.OIDC.IDTOKENROLEASSERTION' | translate}}</mat-checkbox>
|
|
<cnsl-info-section class="full-width desc">
|
|
<span>{{'APP.OIDC.IDTOKENROLEASSERTION_DESCRIPTION' | translate}}</span>
|
|
</cnsl-info-section>
|
|
|
|
<mat-checkbox class="full-width" style="margin-bottom: .5rem"
|
|
formControlName="idTokenUserinfoAssertion" color="primary">
|
|
{{'APP.OIDC.IDTOKENUSERINFOASSERTION' | translate}}</mat-checkbox>
|
|
<cnsl-info-section class="full-width desc">
|
|
<span>{{'APP.OIDC.IDTOKENUSERINFOASSERTION_DESCRIPTION' | translate}}</span>
|
|
</cnsl-info-section>
|
|
|
|
<p class="clockskew-title">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 desc">
|
|
<span>{{'APP.OIDC.CLOCKSKEW' | translate}}</span>
|
|
</cnsl-info-section>
|
|
</div>
|
|
</app-card>
|
|
|
|
<div class="btn-container">
|
|
<button class="submit-button" type="submit" color="primary" [disabled]="oidcForm.invalid || !canWrite"
|
|
mat-raised-button>
|
|
{{ 'ACTIONS.SAVE' | translate }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<cnsl-links [links]="nextLinks"></cnsl-links>
|
|
</div>
|
|
|
|
|
|
<div class="side" metainfo>
|
|
<div class="meta-details">
|
|
<div class="meta-row">
|
|
<span class="first">{{'RESOURCEID' | translate}}:</span>
|
|
<span *ngIf="app?.id" class="second">{{ app.id }}</span>
|
|
</div>
|
|
<div class="meta-row">
|
|
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
|
|
<span *ngIf="app && app.state !== undefined"
|
|
[ngClass]="{'active': app.state === AppState.APP_STATE_ACTIVE, 'inactive': app.state === AppState.APP_STATE_INACTIVE}"
|
|
class="state">{{'APP.PAGES.DETAIL.STATE.'+app.state | translate}}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<app-changes *ngIf="app" [changeType]="ChangeType.APP" [id]="app.id" [secId]="projectId"></app-changes>
|
|
</div>
|
|
</app-meta-layout> |