mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-21 15:04:25 +00:00
# Which Problems Are Solved This adds the newly added xoauth2 option to the console allowing SMTP Providers to be setup that use xoauth2 instead of plain auth. # How the Problems Are Solved Added the xoauth2 option to the SMTP Provider Settings # Additional Changes Heavily refactored the SMTP Provider page to allow more dynamic configuration and use Tanstack Query for Data Fetching. # Additional Context - Closes #11451 - Backend changes #11239
346 lines
14 KiB
HTML
346 lines
14 KiB
HTML
@let state = this.state();
|
|
@let stepper = this.stepper();
|
|
<cnsl-create-layout
|
|
[title]="
|
|
!state || 'config' in state
|
|
? ('SMTP.DETAIL.TITLE' | translate)
|
|
: ('SMTP.CREATE.STEPS.TITLE' | translate: { value: state.mainForm.controls.description.value })
|
|
"
|
|
[createSteps]="4"
|
|
[currentCreateStep]="stepper ? stepper.selectedIndex + 1 : 1"
|
|
(closed)="location.back()"
|
|
>
|
|
<div class="wizard-header">
|
|
@if (state) {
|
|
@if ('defaults' in state) {
|
|
<img class="smtp-logo" [src]="state.defaults.image" [alt]="state.defaults.description" />
|
|
}
|
|
@if (!('defaults' in state) && !('config' in state)) {
|
|
<div class="smtp-icon">
|
|
<mat-icon class="icon" svgIcon="mdi_smtp" alt="providerDefaultSetting.name" />
|
|
</div>
|
|
}
|
|
}
|
|
|
|
<h2>
|
|
{{
|
|
!state || !('defaults' in state)
|
|
? ('SMTP.CREATE.STEPS.CURRENT_DESC_TITLE' | translate)
|
|
: ('SMTP.CREATE.STEPS.CREATE_DESC_TITLE' | translate: { value: state.defaults.description | titlecase })
|
|
}}
|
|
</h2>
|
|
</div>
|
|
@if (configOrDefaultsQuery.isLoading()) {
|
|
<mat-progress-bar class="progress-bar" color="primary" mode="indeterminate" />
|
|
}
|
|
|
|
@if (state) {
|
|
<mat-horizontal-stepper
|
|
class="stepper {{ 'last-edited-step-' + stepper.selectedIndex }}"
|
|
[selectedIndex]="preselectedStep()"
|
|
linear
|
|
#stepper
|
|
labelPosition="bottom"
|
|
>
|
|
<mat-step [editable]="true">
|
|
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.PROVIDER_SETTINGS' | translate }}</ng-template>
|
|
<form [formGroup]="state.mainForm" autocomplete="off">
|
|
<mat-checkbox class="smtp-checkbox" [formControl]="state.mainForm.controls.tls" data-e2e="tls-checkbox">
|
|
{{ 'SETTING.SMTP.TLS' | translate }}
|
|
</mat-checkbox>
|
|
|
|
<cnsl-form-field class="smtp-form-field" label="Description">
|
|
<cnsl-label>{{ 'SETTING.SMTP.DESCRIPTION' | translate }}</cnsl-label>
|
|
<input
|
|
cnslInput
|
|
name="description"
|
|
[formControl]="state.mainForm.controls.description"
|
|
placeholder="description"
|
|
/>
|
|
</cnsl-form-field>
|
|
|
|
<cnsl-form-field class="smtp-form-field" label="Host And Port">
|
|
<cnsl-label>{{ 'SETTING.SMTP.HOSTANDPORT' | translate }}</cnsl-label>
|
|
<input
|
|
cnslInput
|
|
name="hostAndPort"
|
|
[formControl]="state.mainForm.controls.host"
|
|
placeholder="host:port"
|
|
required
|
|
/>
|
|
</cnsl-form-field>
|
|
|
|
<mat-checkbox class="smtp-checkbox" [formControl]="state.mainForm.controls.xoauth2">XOAUTH2</mat-checkbox>
|
|
|
|
<cnsl-form-field class="smtp-form-field" label="User">
|
|
<cnsl-label>{{ 'SETTING.SMTP.USER' | translate }}</cnsl-label>
|
|
<input
|
|
id="smtp-user"
|
|
cnslInput
|
|
name="smtp-user"
|
|
autocomplete="smtp-user"
|
|
[formControl]="state.mainForm.controls.user"
|
|
required
|
|
/>
|
|
</cnsl-form-field>
|
|
|
|
@if ('tokenEndpoint' in state.authForm.controls) {
|
|
<cnsl-form-field class="smtp-form-field" label="tokenEndpoint">
|
|
<cnsl-label>Token Endpoint</cnsl-label>
|
|
<input cnslInput name="token-endpoint" [formControl]="state.authForm.controls.tokenEndpoint" required />
|
|
</cnsl-form-field>
|
|
<cnsl-form-field class="smtp-form-field" label="scopes">
|
|
<cnsl-label>Scopes comma separated</cnsl-label>
|
|
<input cnslInput name="scopes" [formControl]="state.authForm.controls.scopes" required />
|
|
</cnsl-form-field>
|
|
<cnsl-form-field class="smtp-form-field" label="clientId">
|
|
<cnsl-label>Client ID</cnsl-label>
|
|
<input cnslInput name="client-id" [formControl]="state.authForm.controls.clientId" required />
|
|
</cnsl-form-field>
|
|
<cnsl-form-field class="smtp-form-field" label="clientSecret">
|
|
<cnsl-label>Client Secret</cnsl-label>
|
|
<input
|
|
cnslInput
|
|
type="password"
|
|
name="client-id"
|
|
[formControl]="state.authForm.controls.clientSecret"
|
|
required
|
|
/>
|
|
</cnsl-form-field>
|
|
} @else {
|
|
<cnsl-form-field class="smtp-form-field" label="Password">
|
|
<cnsl-label>{{ 'SETTING.SMTP.PASSWORD' | translate }}</cnsl-label>
|
|
<input
|
|
id="smtp-password"
|
|
cnslInput
|
|
name="smtp-password"
|
|
autocomplete="off webauthn"
|
|
[formControl]="state.authForm.controls.password"
|
|
[placeholder]="
|
|
'defaults' in state && state.defaults.auth.case === 'plain' ? state.defaults.auth.password.placeholder : ''
|
|
"
|
|
type="password"
|
|
/>
|
|
</cnsl-form-field>
|
|
}
|
|
</form>
|
|
|
|
<div class="smtp-create-actions">
|
|
<button
|
|
mat-raised-button
|
|
[disabled]="state.mainForm.invalid || state.authForm.invalid"
|
|
color="primary"
|
|
matStepperNext
|
|
data-e2e="continue-to-2nd-form"
|
|
>
|
|
{{ 'ACTIONS.CONTINUE' | translate }}
|
|
</button>
|
|
</div>
|
|
</mat-step>
|
|
|
|
<mat-step [editable]="true">
|
|
<form [formGroup]="state.senderForm">
|
|
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.SENDER_SETTINGS' | translate }}</ng-template>
|
|
|
|
<cnsl-form-field class="smtp-form-field" label="Sender Address">
|
|
<cnsl-label>{{ 'SETTING.SMTP.SENDERADDRESS' | translate }}</cnsl-label>
|
|
<input
|
|
cnslInput
|
|
name="senderAddress"
|
|
formControlName="senderAddress"
|
|
[placeholder]="state.senderEmailPlaceholder"
|
|
required
|
|
/>
|
|
</cnsl-form-field>
|
|
|
|
<cnsl-form-field class="smtp-form-field" label="Sender Name">
|
|
<cnsl-label>{{ 'SETTING.SMTP.SENDERNAME' | translate }}</cnsl-label>
|
|
<input cnslInput name="senderName" formControlName="senderName" placeholder="Zitadel" required />
|
|
</cnsl-form-field>
|
|
|
|
<cnsl-form-field class="smtp-form-field" label="Reply-To Address">
|
|
<cnsl-label>{{ 'SETTING.SMTP.REPLYTOADDRESS' | translate }}</cnsl-label>
|
|
<input
|
|
cnslInput
|
|
name="senderReplyToAddress"
|
|
formControlName="replyToAddress"
|
|
placeholder="[email protected]"
|
|
/>
|
|
</cnsl-form-field>
|
|
</form>
|
|
|
|
<div class="smtp-create-actions">
|
|
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
|
<button
|
|
mat-raised-button
|
|
[disabled]="state.senderForm.invalid"
|
|
color="primary"
|
|
matStepperNext
|
|
data-e2e="continue-button"
|
|
>
|
|
{{ 'ACTIONS.CONTINUE' | translate }}
|
|
</button>
|
|
</div>
|
|
</mat-step>
|
|
|
|
<mat-step [editable]="true" [completed]="'config' in state">
|
|
<form>
|
|
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.SAVE_SETTINGS' | translate }}</ng-template>
|
|
<cnsl-info-section>
|
|
<div class="title-row">
|
|
<div class="left">
|
|
<h2 class="title">{{ 'SMTP.CREATE.STEPS.TEST.TITLE' | translate }}</h2>
|
|
</div>
|
|
<div class="right">
|
|
<button
|
|
color="primary"
|
|
mat-raised-button
|
|
class="continue-button"
|
|
(click)="testEmailConfigurationMutation.mutate()"
|
|
>
|
|
{{ 'ACTIONS.TEST' | translate }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.TEST.DESCRIPTION' | translate }}</p>
|
|
<cnsl-form-field class="formfield">
|
|
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_EMAIL' | translate }}</cnsl-label>
|
|
<input
|
|
[disabled]="emailQuery.isLoading()"
|
|
cnslInput
|
|
(ngModelChange)="email.set($event)"
|
|
[ngModel]="email()"
|
|
[ngModelOptions]="{ standalone: true }"
|
|
data-e2e="email-test-dialog-input"
|
|
/>
|
|
</cnsl-form-field>
|
|
|
|
<div class="is-loading" *ngIf="testEmailConfigurationMutation.isPending()">
|
|
<mat-spinner diameter="50"></mat-spinner>
|
|
</div>
|
|
|
|
<cnsl-form-field
|
|
class="formfield"
|
|
*ngIf="testEmailConfigurationMutation.isError() || testEmailConfigurationMutation.isSuccess()"
|
|
>
|
|
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_RESULT' | translate }}</cnsl-label>
|
|
@let error = testEmailConfigurationMutation.error();
|
|
<textarea
|
|
cnslInput
|
|
[ngModel]="error ? error.message : ('SMTP.CREATE.STEPS.TEST.RESULT' | translate)"
|
|
[ngModelOptions]="{ standalone: true }"
|
|
></textarea>
|
|
</cnsl-form-field>
|
|
</cnsl-info-section>
|
|
|
|
<div class="smtp-create-actions">
|
|
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
|
<button
|
|
(click)="updateDataMutation.mutate()"
|
|
mat-raised-button
|
|
class="create-button"
|
|
color="primary"
|
|
data-e2e="create-button"
|
|
[disabled]="
|
|
state.mainForm.invalid || state.senderForm.invalid || (['iam.policy.write'] | hasRole | async) === false
|
|
"
|
|
>
|
|
{{ 'config' in state ? ('ACTIONS.SAVE' | translate) : ('ACTIONS.CREATE' | translate) }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</mat-step>
|
|
|
|
<mat-step [editable]="true">
|
|
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.NEXT_STEPS' | translate }}</ng-template>
|
|
@if ('config' in state) {
|
|
<form>
|
|
@if (state.config.state === EmailProviderState.EMAIL_PROVIDER_ACTIVE) {
|
|
<cnsl-info-section>
|
|
<div class="title-row">
|
|
<div class="left">
|
|
<h2 class="title">{{ 'SMTP.CREATE.STEPS.DEACTIVATE.TITLE' | translate }}</h2>
|
|
<div>
|
|
<a
|
|
mat-icon-button
|
|
card-actions
|
|
mat-icon-button
|
|
href="https://zitadel.com/docs/guides/manage/console/default-settings#smtp"
|
|
rel="noreferrer"
|
|
target="_blank"
|
|
>
|
|
<mat-icon class="next-icon">info_outline</mat-icon>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="right">
|
|
<button
|
|
color="primary"
|
|
mat-raised-button
|
|
class="continue-button"
|
|
data-e2e="deactivate-button"
|
|
(click)="deactivateSMTPConfig(state.config.id); $event.stopPropagation()"
|
|
>
|
|
{{ 'ACTIONS.DEACTIVATE' | translate }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.DEACTIVATE.DESCRIPTION' | translate }}</p>
|
|
</cnsl-info-section>
|
|
} @else if (state.config.state === EmailProviderState.EMAIL_PROVIDER_INACTIVE) {
|
|
<cnsl-info-section>
|
|
<div class="title-row">
|
|
<div class="left">
|
|
<h2 class="title">{{ 'SMTP.CREATE.STEPS.ACTIVATE.TITLE' | translate }}</h2>
|
|
<div>
|
|
<a
|
|
mat-icon-button
|
|
card-actions
|
|
mat-icon-button
|
|
href="https://zitadel.com/docs/guides/manage/console/default-settings#smtp"
|
|
rel="noreferrer"
|
|
target="_blank"
|
|
>
|
|
<mat-icon class="next-icon">info_outline</mat-icon>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="right">
|
|
<button
|
|
color="primary"
|
|
mat-raised-button
|
|
class="continue-button"
|
|
data-e2e="activate-button"
|
|
(click)="activateSMTPConfig(state.config.id); $event.stopPropagation()"
|
|
>
|
|
{{ 'ACTIONS.ACTIVATE' | translate }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.ACTIVATE.DESCRIPTION' | translate }}</p>
|
|
</cnsl-info-section>
|
|
}
|
|
|
|
<div class="smtp-create-actions">
|
|
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
|
<button
|
|
mat-raised-button
|
|
class="create-button"
|
|
color="primary"
|
|
data-e2e="close-button"
|
|
(click)="location.back()"
|
|
>
|
|
{{ 'ACTIONS.CLOSE' | translate }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
}
|
|
</mat-step>
|
|
|
|
<ng-template matStepperIcon="edit">
|
|
<mat-icon>check</mat-icon>
|
|
</ng-template>
|
|
</mat-horizontal-stepper>
|
|
}
|
|
</cnsl-create-layout>
|