mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-10 08:05:12 +00:00
feat: SMTP Templates (#6932)
* feat: smtp templates poc * feat: add isActive & ProviderType to SMTP backend * feat: change providertype to uint32 and fix tests * feat: minimal smtp provider component * feat: woking on diiferent providers * feat: keep working on providers * feat: initial stepper for new provider * fix: settings list and working on stepper * feat: step 1 and 2 form inputs * feat: starter for smtp test step * fix: misspelled SMPT * fix: remove tests for now * feat: add tls toggle remove old google provider * feat: working on add smtp and table * fix: duplicated identifiers * fix: settings list * fix: add missing smtp config properties * fix: add configID to smtp config table * fix: working on listproviders * feat: working in listSMTPConfigs * fix: add count to listsmtpconfigs * fix: getting empty results from listSMTPConfigs * feat: table now shows real data * fix: remaining styles for smtp-table * fix: remove old notification-smtp-provider-component * feat: delete smtp configuration * feat: deactivate smtp config * feat: replace isActive with state for smtp config * feat: activate smtp config * fix: remaining errors after main merge * fix: list smtp providers panic and material mdc * feat: refactor to only one provider component * feat: current provider details view * fix: refactor AddSMTPConfig and ChangeSMTPConfig * fix: smtp config reduce issue * fix: recover domain in NewIAMSMTPConfigWriteModel * fix: add code needed by SetUpInstance * fix: go tests and warn about passing context to InstanceAggregateFromWriteModel * fix: i18n and add missing trans for fr, it, zh * fix: add e2e tests * docs: add smtp templates * fix: remove provider_type, add description * fix: remaining error from merge main * fix: add @stebenz change for primary key * fix: inactive placed after removed to prevent deleted configs to show as inactive * fix: smtp provider id can be empty (migrated) * feat: add mailchimp transactional template * feat: add Brevo (Sendinblue) template * feat: change brevo logo, add color to tls icon * fix: queries use resourceowner, id must not be empty * fix: deal with old smtp settings and tests * fix: resourceOwner is the instanceID * fix: remove aggregate_id, rename SMTPConfigByAggregateID with SMTPConfigActive * fix: add tests for multiple configs with different IDs * fix: conflict * fix: remove notification-smtp-provider * fix: add @peintnermax suggestions, rename module and fix e2e tests * fix: remove material legacy modules * fix: remove ctx as parameter for InstanceAggregateFromWriteModel * fix: add Id to SMTPConfigToPb * fix: change InstanceAggregateFromWriteModel to avoid linter errors * fix import * rm unused package-lock * update yarn lock --------- Co-authored-by: Elio Bischof <[email protected]> Co-authored-by: Max Peintner <[email protected]> Co-authored-by: Stefan Benz <[email protected]>
This commit is contained in:
co-authored by
Elio Bischof
Max Peintner
Stefan Benz
parent
e2f0cd034a
commit
d229da6af7
@@ -0,0 +1,278 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { Subject } from 'rxjs';
|
||||
import { StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
import { Options } from 'src/app/proto/generated/zitadel/idp_pb';
|
||||
import { requiredValidator } from '../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
|
||||
import {
|
||||
AddSMTPConfigRequest,
|
||||
AddSMTPConfigResponse,
|
||||
UpdateSMTPConfigRequest,
|
||||
UpdateSMTPConfigResponse,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||
import {
|
||||
AmazonSESDefaultSettings,
|
||||
BrevoDefaultSettings,
|
||||
GenericDefaultSettings,
|
||||
GoogleDefaultSettings,
|
||||
MailchimpDefaultSettings,
|
||||
MailgunDefaultSettings,
|
||||
MailjetDefaultSettings,
|
||||
PostmarkDefaultSettings,
|
||||
ProviderDefaultSettings,
|
||||
SendgridDefaultSettings,
|
||||
} from './known-smtp-providers-settings';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-smtp-provider',
|
||||
templateUrl: './smtp-provider.component.html',
|
||||
styleUrls: ['./smtp-provider.scss'],
|
||||
})
|
||||
export class SMTPProviderComponent {
|
||||
public showOptional: boolean = false;
|
||||
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
|
||||
public id: string = '';
|
||||
public providerDefaultSetting: ProviderDefaultSettings = GenericDefaultSettings;
|
||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
|
||||
|
||||
public smtpLoading: boolean = false;
|
||||
public hasSMTPConfig: boolean = false;
|
||||
|
||||
public updateClientSecret: boolean = false;
|
||||
|
||||
// stepper
|
||||
public currentCreateStep: number = 1;
|
||||
public requestRedirectValuesSubject$: Subject<void> = new Subject();
|
||||
public firstFormGroup!: UntypedFormGroup;
|
||||
public secondFormGroup!: UntypedFormGroup;
|
||||
|
||||
constructor(
|
||||
private service: AdminService,
|
||||
private _location: Location,
|
||||
private fb: UntypedFormBuilder,
|
||||
private toast: ToastService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
this.route.parent?.url.subscribe((urlPath) => {
|
||||
const providerName = urlPath[urlPath.length - 1].path;
|
||||
switch (providerName) {
|
||||
case 'aws-ses':
|
||||
this.providerDefaultSetting = AmazonSESDefaultSettings;
|
||||
break;
|
||||
case 'google':
|
||||
this.providerDefaultSetting = GoogleDefaultSettings;
|
||||
break;
|
||||
case 'mailgun':
|
||||
this.providerDefaultSetting = MailgunDefaultSettings;
|
||||
break;
|
||||
case 'mailjet':
|
||||
this.providerDefaultSetting = MailjetDefaultSettings;
|
||||
break;
|
||||
case 'postmark':
|
||||
this.providerDefaultSetting = PostmarkDefaultSettings;
|
||||
break;
|
||||
case 'sendgrid':
|
||||
this.providerDefaultSetting = SendgridDefaultSettings;
|
||||
break;
|
||||
case 'mailchimp':
|
||||
this.providerDefaultSetting = MailchimpDefaultSettings;
|
||||
break;
|
||||
case 'brevo':
|
||||
this.providerDefaultSetting = BrevoDefaultSettings;
|
||||
break;
|
||||
}
|
||||
|
||||
this.firstFormGroup = this.fb.group({
|
||||
description: [this.providerDefaultSetting.name],
|
||||
tls: [{ value: this.providerDefaultSetting.requiredTls, disabled: this.providerDefaultSetting.requiredTls }],
|
||||
region: [''],
|
||||
hostAndPort: [
|
||||
this.providerDefaultSetting?.host
|
||||
? `${this.providerDefaultSetting?.host}:${this.providerDefaultSetting?.unencryptedPort}`
|
||||
: '',
|
||||
],
|
||||
user: [this.providerDefaultSetting?.user.value || ''],
|
||||
password: [this.providerDefaultSetting?.password.value || ''],
|
||||
});
|
||||
|
||||
this.secondFormGroup = this.fb.group({
|
||||
senderAddress: ['', [requiredValidator]],
|
||||
senderName: ['', [requiredValidator]],
|
||||
replyToAddress: [''],
|
||||
});
|
||||
|
||||
this.region?.valueChanges.subscribe((region: string) => {
|
||||
this.hostAndPort?.setValue(
|
||||
`${region}:${
|
||||
this.tls ? this.providerDefaultSetting?.encryptedPort : this.providerDefaultSetting?.unencryptedPort
|
||||
}`,
|
||||
);
|
||||
});
|
||||
|
||||
if (!this.router.url.endsWith('/create')) {
|
||||
this.id = this.route.snapshot.paramMap.get('id') || '';
|
||||
if (this.id) {
|
||||
this.fetchData(this.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public changeStep(event: StepperSelectionEvent): void {
|
||||
this.currentCreateStep = event.selectedIndex + 1;
|
||||
|
||||
if (event.selectedIndex >= 2) {
|
||||
this.requestRedirectValuesSubject$.next();
|
||||
}
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this._location.back();
|
||||
}
|
||||
|
||||
public toggleTLS(event: MatCheckboxChange) {
|
||||
if (this.providerDefaultSetting.host) {
|
||||
this.hostAndPort?.setValue(
|
||||
`${this.providerDefaultSetting?.host}:${
|
||||
event.checked ? this.providerDefaultSetting?.encryptedPort : this.providerDefaultSetting?.unencryptedPort
|
||||
}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private fetchData(id: string): void {
|
||||
this.smtpLoading = true;
|
||||
this.service
|
||||
.getSMTPConfigById(id)
|
||||
.then((data) => {
|
||||
this.smtpLoading = false;
|
||||
if (data.smtpConfig) {
|
||||
this.hasSMTPConfig = true;
|
||||
this.firstFormGroup.patchValue({
|
||||
['description']: data.smtpConfig.description,
|
||||
['tls']: data.smtpConfig.tls,
|
||||
['hostAndPort']: data.smtpConfig.host,
|
||||
['user']: data.smtpConfig.user,
|
||||
});
|
||||
this.secondFormGroup.patchValue({
|
||||
['senderAddress']: data.smtpConfig.senderAddress,
|
||||
['senderName']: data.smtpConfig.senderName,
|
||||
['replyToAddress']: data.smtpConfig.replyToAddress,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.smtpLoading = false;
|
||||
if (error && error.code === 5) {
|
||||
this.hasSMTPConfig = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private updateData(): Promise<UpdateSMTPConfigResponse.AsObject | AddSMTPConfigResponse> {
|
||||
if (this.hasSMTPConfig) {
|
||||
const req = new UpdateSMTPConfigRequest();
|
||||
req.setId(this.id);
|
||||
req.setDescription(this.description?.value || '');
|
||||
req.setTls(this.tls?.value ?? false);
|
||||
|
||||
if (this.hostAndPort && this.hostAndPort.value) {
|
||||
req.setHost(this.hostAndPort.value);
|
||||
}
|
||||
if (this.user && this.user.value) {
|
||||
req.setUser(this.user.value);
|
||||
}
|
||||
if (this.password && this.password.value) {
|
||||
req.setPassword(this.password.value);
|
||||
}
|
||||
if (this.senderAddress && this.senderAddress.value) {
|
||||
req.setSenderAddress(this.senderAddress.value);
|
||||
}
|
||||
if (this.senderName && this.senderName.value) {
|
||||
req.setSenderName(this.senderName.value);
|
||||
}
|
||||
if (this.replyToAddress && this.replyToAddress.value) {
|
||||
req.setReplyToAddress(this.replyToAddress.value);
|
||||
}
|
||||
return this.service.updateSMTPConfig(req);
|
||||
} else {
|
||||
const req = new AddSMTPConfigRequest();
|
||||
req.setDescription(this.description?.value ?? '');
|
||||
req.setHost(this.hostAndPort?.value ?? '');
|
||||
req.setSenderAddress(this.senderAddress?.value ?? '');
|
||||
req.setSenderName(this.senderName?.value ?? '');
|
||||
req.setReplyToAddress(this.replyToAddress?.value ?? '');
|
||||
req.setTls(this.tls?.value ?? false);
|
||||
req.setUser(this.user?.value ?? '');
|
||||
req.setPassword(this.password?.value ?? '');
|
||||
return this.service.addSMTPConfig(req);
|
||||
}
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
this.updateData()
|
||||
.then(() => {
|
||||
this.toast.showInfo('SETTING.SMTP.SAVED', true);
|
||||
setTimeout(() => {
|
||||
this.close();
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
if (`${error}`.includes('No changes')) {
|
||||
this.toast.showInfo('SETTING.SMTP.NOCHANGES', true);
|
||||
setTimeout(() => {
|
||||
this.close();
|
||||
}, 2000);
|
||||
} else {
|
||||
this.toast.showError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public get description(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('description');
|
||||
}
|
||||
|
||||
public get tls(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('tls');
|
||||
}
|
||||
|
||||
public get region(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('region');
|
||||
}
|
||||
|
||||
public get hostAndPort(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('hostAndPort');
|
||||
}
|
||||
|
||||
public get user(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('user');
|
||||
}
|
||||
|
||||
public get password(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('password');
|
||||
}
|
||||
|
||||
public get senderAddress(): AbstractControl | null {
|
||||
return this.secondFormGroup.get('senderAddress');
|
||||
}
|
||||
|
||||
public get senderName(): AbstractControl | null {
|
||||
return this.secondFormGroup.get('senderName');
|
||||
}
|
||||
|
||||
public get replyToAddress(): AbstractControl | null {
|
||||
return this.secondFormGroup.get('replyToAddress');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user