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 <elio@zitadel.com> Co-authored-by: Max Peintner <max@caos.ch> Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
@ -159,6 +159,8 @@ export class AppComponent implements OnDestroy {
|
||||
|
||||
this.matIconRegistry.addSvgIcon('mdi_jwt', this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/jwt.svg'));
|
||||
|
||||
this.matIconRegistry.addSvgIcon('mdi_smtp', this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/mail.svg'));
|
||||
|
||||
this.matIconRegistry.addSvgIcon('mdi_symbol', this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/symbol.svg'));
|
||||
|
||||
this.matIconRegistry.addSvgIcon(
|
||||
|
@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { DialogAddSMSProviderComponent } from './dialog-add-sms-provider.component';
|
||||
|
||||
describe('PasswordDialogComponent', () => {
|
||||
let component: DialogAddSMSProviderComponent;
|
||||
let fixture: ComponentFixture<DialogAddSMSProviderComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [DialogAddSMSProviderComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DialogAddSMSProviderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -10,7 +10,7 @@ import {
|
||||
import { SMSProvider, TwilioConfig } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { PasswordDialogComponent } from '../password-dialog/password-dialog.component';
|
||||
import { PasswordDialogSMSProviderComponent } from '../password-dialog-sms-provider/password-dialog-sms-provider.component';
|
||||
|
||||
enum SMSProviderType {
|
||||
Twilio = 1,
|
||||
@ -73,7 +73,7 @@ export class DialogAddSMSProviderComponent {
|
||||
}
|
||||
|
||||
public changeToken(): void {
|
||||
const dialogRef = this.dialog.open(PasswordDialogComponent, {
|
||||
const dialogRef = this.dialog.open(PasswordDialogSMSProviderComponent, {
|
||||
width: '400px',
|
||||
data: {
|
||||
i18nTitle: 'SETTING.SMS.TWILIO.SETTOKEN',
|
||||
|
@ -6,6 +6,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
@ -16,10 +17,11 @@ import { InputModule } from '../../input/input.module';
|
||||
import { WarnDialogModule } from '../../warn-dialog/warn-dialog.module';
|
||||
import { DialogAddSMSProviderComponent } from './dialog-add-sms-provider/dialog-add-sms-provider.component';
|
||||
import { NotificationSMSProviderComponent } from './notification-sms-provider.component';
|
||||
import { PasswordDialogSMSProviderComponent } from './password-dialog-sms-provider/password-dialog-sms-provider.component';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
|
||||
@NgModule({
|
||||
declarations: [NotificationSMSProviderComponent, DialogAddSMSProviderComponent],
|
||||
declarations: [NotificationSMSProviderComponent, DialogAddSMSProviderComponent, PasswordDialogSMSProviderComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
@ -34,9 +36,9 @@ import { MatDialogModule } from '@angular/material/dialog';
|
||||
FormFieldModule,
|
||||
WarnDialogModule,
|
||||
MatSelectModule,
|
||||
MatDialogModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
MatDialogModule,
|
||||
TranslateModule,
|
||||
],
|
||||
exports: [NotificationSMSProviderComponent],
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { PasswordDialogComponent } from './password-dialog.component';
|
||||
import { PasswordDialogComponent } from './password-dialog-sms-provider.component';
|
||||
|
||||
describe('PasswordDialogComponent', () => {
|
||||
let component: PasswordDialogComponent;
|
@ -2,14 +2,14 @@ import { Component, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-password-dialog',
|
||||
templateUrl: './password-dialog.component.html',
|
||||
styleUrls: ['./password-dialog.component.scss'],
|
||||
selector: 'cnsl-password-dialog-sms-provider',
|
||||
templateUrl: './password-dialog-sms-provider.component.html',
|
||||
styleUrls: ['./password-dialog-sms-provider.component.scss'],
|
||||
})
|
||||
export class PasswordDialogComponent {
|
||||
export class PasswordDialogSMSProviderComponent {
|
||||
public password: string = '';
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<PasswordDialogComponent>,
|
||||
public dialogRef: MatDialogRef<PasswordDialogSMSProviderComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {}
|
||||
|
@ -1,70 +1,37 @@
|
||||
<h2>{{ 'DESCRIPTIONS.SETTINGS.SMTP_PROVIDER.TITLE' | translate }}</h2>
|
||||
<p class="cnsl-secondary-text">{{ 'DESCRIPTIONS.SETTINGS.SMTP_PROVIDER.DESCRIPTION' | translate }}</p>
|
||||
<h2>{{ 'SMTP.LIST.TITLE' | translate }}</h2>
|
||||
<p class="cnsl-secondary-text">{{ 'SMTP.LIST.DESCRIPTION' | translate }}</p>
|
||||
|
||||
<div class="spinner-wr">
|
||||
<mat-spinner diameter="30" *ngIf="smtpLoading" color="primary"></mat-spinner>
|
||||
<div class="cnsl-snmp-table-wrapper">
|
||||
<cnsl-smtp-table></cnsl-smtp-table>
|
||||
</div>
|
||||
|
||||
<cnsl-info-section
|
||||
*ngIf="!smtpLoading && !form.valid"
|
||||
class="info-section-warn"
|
||||
[fitWidth]="true"
|
||||
[type]="InfoSectionType.ALERT"
|
||||
>{{ 'SETTING.SMTP.REQUIREDWARN' | translate }}</cnsl-info-section
|
||||
>
|
||||
<h2>{{ 'SMTP.CREATE.TITLE' | translate }}</h2>
|
||||
<p class="cnsl-secondary-text">{{ 'SMTP.CREATE.DESCRIPTION' | translate }}</p>
|
||||
|
||||
<form (ngSubmit)="savePolicy()" [formGroup]="form" autocomplete="off">
|
||||
<cnsl-form-field class="smtp-form-field" label="Sender Address" required="true">
|
||||
<cnsl-label>{{ 'SETTING.SMTP.SENDERADDRESS' | translate }}</cnsl-label>
|
||||
<input cnslInput name="senderAddress" formControlName="senderAddress" required />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="smtp-form-field" label="Sender Name" required="true">
|
||||
<cnsl-label>{{ 'SETTING.SMTP.SENDERNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput name="senderName" formControlName="senderName" 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" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-checkbox class="smtp-checkbox" formControlName="tls">
|
||||
{{ 'SETTING.SMTP.TLS' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<cnsl-form-field class="smtp-form-field" label="Host And Port" required="true">
|
||||
<cnsl-label>{{ 'SETTING.SMTP.HOSTANDPORT' | translate }}</cnsl-label>
|
||||
<input cnslInput name="hostAndPort" formControlName="hostAndPort" placeholder="smtp.mailtrap.io:2525" required />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="smtp-form-field" label="User" required="true">
|
||||
<cnsl-label>{{ 'SETTING.SMTP.USER' | translate }}</cnsl-label>
|
||||
<input id="smtp-user" cnslInput name="smtp-user" autocomplete="smtp-user" formControlName="user" required />
|
||||
</cnsl-form-field>
|
||||
|
||||
<button
|
||||
class="set-password-btn"
|
||||
[disabled]="(['iam.write'] | hasRole | async) === false || !hasSMTPConfig"
|
||||
(click)="setSMTPPassword()"
|
||||
type="button"
|
||||
mat-stroked-button
|
||||
data-e2e="add-smtp-password-button"
|
||||
>
|
||||
{{ 'SETTING.SMTP.SETPASSWORD' | translate }}
|
||||
</button>
|
||||
|
||||
<div class="general-btn-container">
|
||||
<button
|
||||
class="save-button"
|
||||
[disabled]="form.disabled"
|
||||
(click)="savePolicy()"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
data-e2e="save-smtp-settings-button"
|
||||
<div class="new-smtp-wrapper">
|
||||
<div *ngFor="let provider of providers">
|
||||
<a
|
||||
class="item card"
|
||||
[routerLink]="['/instance', 'smtpprovider', provider.routerLinkElement, 'create']"
|
||||
*ngIf="provider.name !== 'generic'"
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
<img class="smtp-logo" src="{{ provider.image }}" alt="{{ provider.name }}" />
|
||||
<div class="text-container">
|
||||
<span class="title">{{ provider.name | titlecase }} </span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="item card"
|
||||
[routerLink]="['/instance', 'smtpprovider', provider.routerLinkElement, 'create']"
|
||||
*ngIf="provider.name === 'generic'"
|
||||
>
|
||||
<div class="smtp-icon">
|
||||
<mat-icon class="icon" svgIcon="mdi_smtp" />
|
||||
</div>
|
||||
<div class="text-container">
|
||||
<span class="title">Generic SMTP</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,32 +1,113 @@
|
||||
.spinner-wr {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
@use '@angular/material' as mat;
|
||||
|
||||
.smtp-form-field,
|
||||
.info-section-warn {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
}
|
||||
@mixin smtp-settings-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$primary-color: mat.get-color-from-palette($primary, 500);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.info-section-warn {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.smtp-checkbox {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.set-password-btn {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.general-btn-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
.save-button {
|
||||
.cnsl-smtp-table-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.new-smtp-wrapper {
|
||||
display: grid;
|
||||
row-gap: 1.5rem;
|
||||
column-gap: 1.5rem;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
@media only screen and (min-width: 700px) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1000px) {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1300px) {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
padding-top: 1rem;
|
||||
padding-right: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
padding-left: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
box-sizing: border-box;
|
||||
transition: box-shadow 0.1s ease-in;
|
||||
align-items: center;
|
||||
color: map-get($foreground, text);
|
||||
|
||||
.coming-soon-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 1rem;
|
||||
transform: translateY(-50%);
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.smtp-logo {
|
||||
margin-right: 1rem;
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
|
||||
&.apple {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
}
|
||||
}
|
||||
|
||||
.smtp-icon {
|
||||
margin-right: 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
|
||||
.icon {
|
||||
font-size: 2.25rem;
|
||||
height: 2.25rem;
|
||||
width: 2.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.text-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.title {
|
||||
}
|
||||
}
|
||||
|
||||
&.coming-soon {
|
||||
filter: grayscale(1);
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NotificationSMTPProviderComponent } from './notification-smtp-provider.component';
|
||||
|
||||
describe('NotificationSMTPProviderComponent', () => {
|
||||
describe('IdpSettingsComponent', () => {
|
||||
let component: NotificationSMTPProviderComponent;
|
||||
let fixture: ComponentFixture<NotificationSMTPProviderComponent>;
|
||||
|
||||
|
@ -1,22 +1,9 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { take } from 'rxjs';
|
||||
import {
|
||||
AddSMTPConfigRequest,
|
||||
AddSMTPConfigResponse,
|
||||
UpdateSMTPConfigPasswordRequest,
|
||||
UpdateSMTPConfigRequest,
|
||||
UpdateSMTPConfigResponse,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { requiredValidator } from '../../form-field/validators/validators';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
|
||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { PasswordDialogComponent } from '../notification-sms-provider/password-dialog/password-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { SMTPKnownProviders } from '../../smtp-provider/known-smtp-providers-settings';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-notification-smtp-provider',
|
||||
@ -25,151 +12,21 @@ import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
})
|
||||
export class NotificationSMTPProviderComponent implements OnInit {
|
||||
@Input() public serviceType!: PolicyComponentServiceType;
|
||||
public service!: ManagementService | AdminService;
|
||||
|
||||
public smtpLoading: boolean = false;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public providers = SMTPKnownProviders;
|
||||
|
||||
public form!: UntypedFormGroup;
|
||||
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
|
||||
public hasSMTPConfig: boolean = false;
|
||||
|
||||
// show available providers
|
||||
|
||||
constructor(
|
||||
private service: AdminService,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
private fb: UntypedFormBuilder,
|
||||
private authService: GrpcAuthService,
|
||||
) {
|
||||
this.form = this.fb.group({
|
||||
senderAddress: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
senderName: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
replyToAddress: [{ disabled: true, value: '' }],
|
||||
tls: [{ disabled: true, value: true }, [requiredValidator]],
|
||||
hostAndPort: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
user: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
});
|
||||
}
|
||||
constructor(private injector: Injector) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.fetchData();
|
||||
this.authService
|
||||
.isAllowed(['iam.write'])
|
||||
.pipe(take(1))
|
||||
.subscribe((allowed) => {
|
||||
if (allowed) {
|
||||
this.form.enable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private fetchData(): void {
|
||||
this.smtpLoading = true;
|
||||
this.service
|
||||
.getSMTPConfig()
|
||||
.then((smtpConfig) => {
|
||||
this.smtpLoading = false;
|
||||
if (smtpConfig.smtpConfig) {
|
||||
this.hasSMTPConfig = true;
|
||||
this.form.patchValue(smtpConfig.smtpConfig);
|
||||
this.form.patchValue({ ['hostAndPort']: smtpConfig.smtpConfig.host });
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.smtpLoading = false;
|
||||
if (error && error.code === 5) {
|
||||
console.log(error);
|
||||
this.hasSMTPConfig = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private updateData(): Promise<UpdateSMTPConfigResponse.AsObject | AddSMTPConfigResponse> {
|
||||
if (this.hasSMTPConfig) {
|
||||
const req = new UpdateSMTPConfigRequest();
|
||||
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 ?? '');
|
||||
|
||||
return this.service.updateSMTPConfig(req);
|
||||
} else {
|
||||
const req = new AddSMTPConfigRequest();
|
||||
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 ?? '');
|
||||
|
||||
return this.service.addSMTPConfig(req);
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
this.updateData()
|
||||
.then(() => {
|
||||
this.toast.showInfo('SETTING.SMTP.SAVED', true);
|
||||
setTimeout(() => {
|
||||
this.fetchData();
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public setSMTPPassword(): void {
|
||||
const dialogRef = this.dialog.open(PasswordDialogComponent, {
|
||||
width: '400px',
|
||||
data: {
|
||||
i18nTitle: 'SETTING.SMTP.SETPASSWORD',
|
||||
i18nLabel: 'SETTING.SMTP.PASSWORD',
|
||||
},
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((password: string) => {
|
||||
if (password) {
|
||||
const passwordReq = new UpdateSMTPConfigPasswordRequest();
|
||||
passwordReq.setPassword(password);
|
||||
|
||||
this.service
|
||||
.updateSMTPConfigPassword(passwordReq)
|
||||
.then(() => {
|
||||
this.toast.showInfo('SETTING.SMTP.PASSWORDSET', true);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public get senderAddress(): AbstractControl | null {
|
||||
return this.form.get('senderAddress');
|
||||
}
|
||||
|
||||
public get senderName(): AbstractControl | null {
|
||||
return this.form.get('senderName');
|
||||
}
|
||||
|
||||
public get replyToAddress(): AbstractControl | null {
|
||||
return this.form.get('replyToAddress');
|
||||
}
|
||||
|
||||
public get tls(): AbstractControl | null {
|
||||
return this.form.get('tls');
|
||||
}
|
||||
|
||||
public get user(): AbstractControl | null {
|
||||
return this.form.get('user');
|
||||
}
|
||||
|
||||
public get hostAndPort(): AbstractControl | null {
|
||||
return this.form.get('hostAndPort');
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +1,32 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { CardModule } from '../../card/card.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { InputModule } from '../../input/input.module';
|
||||
import { WarnDialogModule } from '../../warn-dialog/warn-dialog.module';
|
||||
import { PasswordDialogComponent } from '../notification-sms-provider/password-dialog/password-dialog.component';
|
||||
import { NotificationSMTPProviderComponent } from './notification-smtp-provider.component';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { InputModule } from '../../input/input.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { SMTPTableModule } from '../../smtp-table/smtp-table.module';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
|
||||
@NgModule({
|
||||
declarations: [NotificationSMTPProviderComponent, PasswordDialogComponent],
|
||||
declarations: [NotificationSMTPProviderComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
InfoSectionModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HasRolePipeModule,
|
||||
MatButtonModule,
|
||||
MatCheckboxModule,
|
||||
InputModule,
|
||||
MatIconModule,
|
||||
FormFieldModule,
|
||||
WarnDialogModule,
|
||||
MatSelectModule,
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
CardModule,
|
||||
MatIconModule,
|
||||
SMTPTableModule,
|
||||
RouterModule,
|
||||
HasRolePipeModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
TranslateModule,
|
||||
MatDialogModule,
|
||||
],
|
||||
exports: [NotificationSMTPProviderComponent],
|
||||
})
|
||||
|
@ -14,7 +14,6 @@ import { LoginTextsPolicyModule } from '../policies/login-texts/login-texts.modu
|
||||
import { MessageTextsPolicyModule } from '../policies/message-texts/message-texts.module';
|
||||
import { NotificationPolicyModule } from '../policies/notification-policy/notification-policy.module';
|
||||
import { NotificationSMSProviderModule } from '../policies/notification-sms-provider/notification-sms-provider.module';
|
||||
import { NotificationSMTPProviderModule } from '../policies/notification-smtp-provider/notification-smtp-provider.module';
|
||||
import { OIDCConfigurationModule } from '../policies/oidc-configuration/oidc-configuration.module';
|
||||
import { PasswordComplexityPolicyModule } from '../policies/password-complexity-policy/password-complexity-policy.module';
|
||||
import { PasswordLockoutPolicyModule } from '../policies/password-lockout-policy/password-lockout-policy.module';
|
||||
@ -28,7 +27,9 @@ import FailedEventsModule from '../failed-events/failed-events.module';
|
||||
import IamViewsModule from '../iam-views/iam-views.module';
|
||||
import EventsModule from '../events/events.module';
|
||||
import { OrgTableModule } from '../org-table/org-table.module';
|
||||
import { NotificationSMTPProviderModule } from '../policies/notification-smtp-provider/notification-smtp-provider.module';
|
||||
import { FeaturesComponent } from 'src/app/components/features/features.component';
|
||||
import OrgListModule from 'src/app/pages/org-list/org-list.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SettingsListComponent],
|
||||
@ -44,12 +45,14 @@ import { FeaturesComponent } from 'src/app/components/features/features.componen
|
||||
LanguageSettingsModule,
|
||||
NotificationPolicyModule,
|
||||
IdpSettingsModule,
|
||||
NotificationSMTPProviderModule,
|
||||
PrivacyPolicyModule,
|
||||
MessageTextsPolicyModule,
|
||||
SecurityPolicyModule,
|
||||
DomainsModule,
|
||||
LoginTextsPolicyModule,
|
||||
OrgTableModule,
|
||||
OrgListModule,
|
||||
DomainPolicyModule,
|
||||
TranslateModule,
|
||||
HasRolePipeModule,
|
||||
|
@ -0,0 +1,174 @@
|
||||
export interface AmazonRegionsEndpoints {
|
||||
'US East (Ohio)': string;
|
||||
'US East (N. Virginia)': string;
|
||||
'US West (N. California)': string;
|
||||
'US West (Oregon)': string;
|
||||
'Asia Pacific (Mumbai)': string;
|
||||
'Asia Pacific (Osaka)': string;
|
||||
'Asia Pacific (Seoul)': string;
|
||||
'Asia Pacific (Singapore)': string;
|
||||
'Asia Pacific (Sydney)': string;
|
||||
'Asia Pacific (Tokyo)': string;
|
||||
'Canada (Central)': string;
|
||||
'Europe (Frankfurt)': string;
|
||||
'Europe (London)': string;
|
||||
'Europe (Paris)': string;
|
||||
'Europe (Stockholm)': string;
|
||||
'South America (São Paulo)': string;
|
||||
}
|
||||
|
||||
const amazonEndpoints = {
|
||||
'US East (Ohio)': 'email-smtp.us-east-2.amazonaws.com',
|
||||
'US East (N. Virginia)': 'email-smtp.us-east-1.amazonaws.com',
|
||||
'US West (N. California)': 'email-smtp.us-west-1.amazonaws.com',
|
||||
'US West (Oregon)': 'email-smtp.us-west-2.amazonaws.com',
|
||||
'Asia Pacific (Mumbai)': 'email-smtp.ap-south-1.amazonaws.com',
|
||||
'Asia Pacific (Osaka)': 'email-smtp.ap-northeast-3.amazonaws.com',
|
||||
'Asia Pacific (Seoul)': 'email-smtp.ap-northeast-2.amazonaws.com',
|
||||
'Asia Pacific (Singapore)': 'email-smtp.ap-southeast-1.amazonaws.com',
|
||||
'Asia Pacific (Sydney)': 'email-smtp.ap-southeast-2.amazonaws.com',
|
||||
'Asia Pacific (Tokyo)': 'email-smtp.ap-northeast-1.amazonaws.com',
|
||||
'Canada (Central)': 'email-smtp.ca-central-1.amazonaws.com',
|
||||
'Europe (Frankfurt)': 'email-smtp.eu-central-1.amazonaws.com',
|
||||
'Europe (Ireland)': 'email-smtp.eu-west-1.amazonaws.com',
|
||||
'Europe (London)': 'email-smtp.eu-west-2.amazonaws.com',
|
||||
'Europe (Paris)': 'email-smtp.eu-west-3.amazonaws.com',
|
||||
'Europe (Stockholm)': 'email-smtp.eu-north-1.amazonaws.com',
|
||||
'South America (São Paulo)': 'email-smtp.sa-east-1.amazonaws.com',
|
||||
};
|
||||
|
||||
export interface ProviderDefaultSettings {
|
||||
name: string;
|
||||
regions?: AmazonRegionsEndpoints;
|
||||
multiHostsLabel?: string;
|
||||
requiredTls: boolean;
|
||||
host?: string;
|
||||
unencryptedPort?: number;
|
||||
encryptedPort?: number;
|
||||
user: {
|
||||
value: string;
|
||||
placeholder: string;
|
||||
};
|
||||
password: {
|
||||
value: string;
|
||||
placeholder: string;
|
||||
};
|
||||
image?: string;
|
||||
routerLinkElement: string;
|
||||
}
|
||||
|
||||
export const AmazonSESDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'amazon SES',
|
||||
regions: amazonEndpoints,
|
||||
multiHostsLabel: 'Choose your region',
|
||||
requiredTls: true,
|
||||
encryptedPort: 587,
|
||||
user: { value: '', placeholder: 'your Amazon SES credentials for this region' },
|
||||
password: { value: '', placeholder: 'your Amazon SES credentials for this region' },
|
||||
image: './assets/images/smtp/aws-ses.svg',
|
||||
routerLinkElement: 'aws-ses',
|
||||
};
|
||||
|
||||
export const GoogleDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'google',
|
||||
requiredTls: true,
|
||||
host: 'smtp.gmail.com',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 587,
|
||||
user: { value: '', placeholder: 'your complete Google Workspace email address' },
|
||||
password: { value: '', placeholder: 'your complete Google Workspace password' },
|
||||
image: './assets/images/smtp/google.png',
|
||||
routerLinkElement: 'google',
|
||||
};
|
||||
|
||||
export const MailgunDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'mailgun',
|
||||
requiredTls: false,
|
||||
host: 'smtp.mailgun.org',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 465,
|
||||
user: { value: '', placeholder: 'postmaster@YOURDOMAIN' },
|
||||
password: { value: '', placeholder: 'Your mailgun smtp password' },
|
||||
image: './assets/images/smtp/mailgun.svg',
|
||||
routerLinkElement: 'mailgun',
|
||||
};
|
||||
|
||||
export const MailjetDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'mailjet',
|
||||
requiredTls: false,
|
||||
host: 'in-v3.mailjet.com',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 465,
|
||||
user: { value: '', placeholder: 'Your Mailjet API key' },
|
||||
password: { value: '', placeholder: 'Your Mailjet Secret key' },
|
||||
image: './assets/images/smtp/mailjet.svg',
|
||||
routerLinkElement: 'mailjet',
|
||||
};
|
||||
|
||||
export const PostmarkDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'postmark',
|
||||
requiredTls: false,
|
||||
host: 'smtp.postmarkapp.com',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 587,
|
||||
user: { value: '', placeholder: 'Your Server API token' },
|
||||
password: { value: '', placeholder: 'Your Server API token' },
|
||||
image: './assets/images/smtp/postmark.png',
|
||||
routerLinkElement: 'postmark',
|
||||
};
|
||||
|
||||
export const SendgridDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'sendgrid',
|
||||
requiredTls: false,
|
||||
host: 'smtp.sendgrid.net',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 465,
|
||||
user: { value: 'apikey', placeholder: '' },
|
||||
password: { value: '', placeholder: ' Your SendGrid API Key' },
|
||||
image: './assets/images/smtp/sendgrid.png',
|
||||
routerLinkElement: 'sendgrid',
|
||||
};
|
||||
|
||||
export const MailchimpDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'mailchimp',
|
||||
requiredTls: false,
|
||||
host: 'smtp.mandrillapp.com',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 465,
|
||||
user: { value: '', placeholder: 'Your Mailchimp primary contact email' },
|
||||
password: { value: '', placeholder: 'Your Mailchimp Transactional API key' },
|
||||
image: './assets/images/smtp/mailchimp.svg',
|
||||
routerLinkElement: 'mailchimp',
|
||||
};
|
||||
|
||||
export const BrevoDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'brevo',
|
||||
requiredTls: false,
|
||||
host: 'smtp-relay.sendinblue.com',
|
||||
unencryptedPort: 587,
|
||||
encryptedPort: 465,
|
||||
user: { value: '', placeholder: 'Your SMTP login email address' },
|
||||
password: { value: '', placeholder: 'Your SMTP key' },
|
||||
image: './assets/images/smtp/brevo.svg',
|
||||
routerLinkElement: 'brevo',
|
||||
};
|
||||
|
||||
export const GenericDefaultSettings: ProviderDefaultSettings = {
|
||||
name: 'generic',
|
||||
requiredTls: false,
|
||||
user: { value: '', placeholder: 'your SMTP user' },
|
||||
password: { value: '', placeholder: 'your SMTP password' },
|
||||
routerLinkElement: 'generic',
|
||||
};
|
||||
|
||||
export const SMTPKnownProviders = [
|
||||
AmazonSESDefaultSettings,
|
||||
BrevoDefaultSettings,
|
||||
// GoogleDefaultSettings,
|
||||
MailgunDefaultSettings,
|
||||
MailchimpDefaultSettings,
|
||||
MailjetDefaultSettings,
|
||||
PostmarkDefaultSettings,
|
||||
SendgridDefaultSettings,
|
||||
GenericDefaultSettings,
|
||||
];
|
@ -0,0 +1,39 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { SMTPProviderComponent } from './smtp-provider.component';
|
||||
|
||||
const types = [
|
||||
{ path: 'aws-ses', component: SMTPProviderComponent },
|
||||
{ path: 'generic', component: SMTPProviderComponent },
|
||||
{ path: 'google', component: SMTPProviderComponent },
|
||||
{ path: 'mailgun', component: SMTPProviderComponent },
|
||||
{ path: 'postmark', component: SMTPProviderComponent },
|
||||
{ path: 'sendgrid', component: SMTPProviderComponent },
|
||||
{ path: 'mailjet', component: SMTPProviderComponent },
|
||||
{ path: 'mailchimp', component: SMTPProviderComponent },
|
||||
{ path: 'brevo', component: SMTPProviderComponent },
|
||||
];
|
||||
|
||||
const routes: Routes = types.map((value) => {
|
||||
return {
|
||||
path: value.path,
|
||||
children: [
|
||||
{
|
||||
path: 'create',
|
||||
component: value.component,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
routes.push({
|
||||
path: ':id',
|
||||
component: SMTPProviderComponent,
|
||||
});
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class SMTPProvidersRoutingModule {}
|
@ -0,0 +1,144 @@
|
||||
<cnsl-create-layout
|
||||
title="{{
|
||||
id ? ('SMTP.DETAIL.TITLE' | translate) : ('SMTP.CREATE.STEPS.TITLE' | translate: { value: providerDefaultSetting.name })
|
||||
}}"
|
||||
[createSteps]="2"
|
||||
[currentCreateStep]="currentCreateStep"
|
||||
(closed)="close()"
|
||||
>
|
||||
<div class="wizard-header">
|
||||
<img
|
||||
class="smtp-logo"
|
||||
src="{{ providerDefaultSetting.image }}"
|
||||
alt="{{ providerDefaultSetting.name }}"
|
||||
*ngIf="providerDefaultSetting.name !== 'generic'"
|
||||
/>
|
||||
<div class="smtp-icon" *ngIf="providerDefaultSetting.name === 'generic'">
|
||||
<mat-icon class="icon" svgIcon="mdi_smtp" alt="providerDefaultSetting.name" />
|
||||
</div>
|
||||
<h2>
|
||||
{{
|
||||
!id
|
||||
? ('SMTP.CREATE.STEPS.CREATE_DESC_TITLE' | translate: { value: providerDefaultSetting.name | titlecase })
|
||||
: ('SMTP.CREATE.STEPS.CURRENT_DESC_TITLE' | translate)
|
||||
}}
|
||||
</h2>
|
||||
</div>
|
||||
<mat-progress-bar class="progress-bar" color="primary" *ngIf="smtpLoading" mode="indeterminate"></mat-progress-bar>
|
||||
|
||||
<mat-horizontal-stepper
|
||||
class="stepper {{ 'last-edited-step-' + stepper.selectedIndex }}"
|
||||
linear
|
||||
#stepper
|
||||
labelPosition="bottom"
|
||||
(selectionChange)="changeStep($event)"
|
||||
>
|
||||
<mat-step [editable]="true">
|
||||
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.PROVIDER_SETTINGS' | translate }}</ng-template>
|
||||
<form [formGroup]="firstFormGroup" autocomplete="off">
|
||||
<mat-checkbox class="smtp-checkbox" formControlName="tls" (change)="toggleTLS($event)" data-e2e="tls-checkbox">
|
||||
{{ 'SETTING.SMTP.TLS' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<cnsl-form-field class="smtp-form-field" *ngIf="providerDefaultSetting.regions">
|
||||
<cnsl-label>{{ providerDefaultSetting.multiHostsLabel }}</cnsl-label>
|
||||
<mat-select formControlName="region">
|
||||
<mat-option *ngFor="let region of providerDefaultSetting.regions | keyvalue" [value]="region.value">
|
||||
{{ region.key }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="smtp-form-field" label="Description">
|
||||
<cnsl-label>{{ 'SETTING.SMTP.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput name="description" formControlName="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" formControlName="hostAndPort" placeholder="host:port" required />
|
||||
</cnsl-form-field>
|
||||
|
||||
<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"
|
||||
formControlName="user"
|
||||
placeholder="{{ providerDefaultSetting.user.placeholder }}"
|
||||
required
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
|
||||
<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"
|
||||
formControlName="password"
|
||||
placeholder="{{ hasSMTPConfig ? '****************' : providerDefaultSetting.password.placeholder }}"
|
||||
type="password"
|
||||
required="{{ !hasSMTPConfig }}"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</form>
|
||||
|
||||
<div class="smtp-create-actions">
|
||||
<button
|
||||
mat-raised-button
|
||||
[disabled]="firstFormGroup.invalid"
|
||||
color="primary"
|
||||
matStepperNext
|
||||
data-e2e="continue-button"
|
||||
>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [editable]="true">
|
||||
<form [formGroup]="secondFormGroup">
|
||||
<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="sender@example.com" 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="replyto@example.com" />
|
||||
</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
|
||||
class="create-button"
|
||||
color="primary"
|
||||
data-e2e="create-button"
|
||||
(click)="savePolicy()"
|
||||
[disabled]="
|
||||
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
|
||||
"
|
||||
>
|
||||
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<ng-template matStepperIcon="edit">
|
||||
<mat-icon>check</mat-icon>
|
||||
</ng-template>
|
||||
</mat-horizontal-stepper>
|
||||
</cnsl-create-layout>
|
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { SMTPProviderComponent } from './smtp-provider.component';
|
||||
|
||||
describe('SMTPProviderSendgridComponent', () => {
|
||||
let component: SMTPProviderComponent;
|
||||
let fixture: ComponentFixture<SMTPProviderComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SMTPProviderComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SMTPProviderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
278
console/src/app/modules/smtp-provider/smtp-provider.component.ts
Normal file
@ -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');
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import { CommonModule, TitleCasePipe } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { MatStepperModule } from '@angular/material/stepper';
|
||||
import { CardModule } from '../card/card.module';
|
||||
import { CreateLayoutModule } from '../create-layout/create-layout.module';
|
||||
import { InfoSectionModule } from '../info-section/info-section.module';
|
||||
import { ProviderOptionsModule } from '../provider-options/provider-options.module';
|
||||
import { StringListModule } from '../string-list/string-list.module';
|
||||
import { SMTPProvidersRoutingModule } from './smtp-provider-routing.module';
|
||||
import { SMTPProviderComponent } from './smtp-provider.component';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SMTPProviderComponent],
|
||||
imports: [
|
||||
SMTPProvidersRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
CreateLayoutModule,
|
||||
StringListModule,
|
||||
InfoSectionModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatProgressBarModule,
|
||||
MatSelectModule,
|
||||
MatIconModule,
|
||||
MatChipsModule,
|
||||
CardModule,
|
||||
MatCheckboxModule,
|
||||
MatTooltipModule,
|
||||
MatStepperModule,
|
||||
TranslateModule,
|
||||
ProviderOptionsModule,
|
||||
HasRolePipeModule,
|
||||
MatProgressSpinnerModule,
|
||||
],
|
||||
})
|
||||
export default class SMTPProviderModule {}
|
71
console/src/app/modules/smtp-provider/smtp-provider.scss
Normal file
@ -0,0 +1,71 @@
|
||||
@use '@angular/material' as mat;
|
||||
|
||||
@mixin smtp-provider-theme($theme) {
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.stepper {
|
||||
background: inherit !important;
|
||||
margin: 0 -1.5rem;
|
||||
}
|
||||
|
||||
.smtp-create-actions {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.bck-button {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.create-button {
|
||||
padding: 0.5rem 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.smtp-form-field,
|
||||
.info-section-warn {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wizard-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.smtp-logo {
|
||||
margin-right: 1rem;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.smtp-icon {
|
||||
margin-right: 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
|
||||
.icon {
|
||||
font-size: 2.25rem;
|
||||
height: 2.25rem;
|
||||
width: 2.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
129
console/src/app/modules/smtp-table/smtp-table.component.html
Normal file
@ -0,0 +1,129 @@
|
||||
<cnsl-refresh-table
|
||||
[loading]="loading$ | async"
|
||||
(refreshed)="refreshPage()"
|
||||
[dataSize]="dataSource.data.length"
|
||||
[emitRefreshOnPreviousRoutes]="[
|
||||
'/instance/smtpprovider/aws-ses/create',
|
||||
'/instance/smtpprovider/generic/create',
|
||||
'/instance/smtpprovider/google/create',
|
||||
'/instance/smtpprovider/mailgun/create',
|
||||
'/instance/smtpprovider/mailjet/create',
|
||||
'/instance/smtpprovider/postmark/create',
|
||||
'/instance/smtpprovider/sendgrid/create',
|
||||
'/instance/smtpprovider/mailchimp/create',
|
||||
'/instance/smtpprovider/brevo/create'
|
||||
]"
|
||||
[timestamp]="configsResult?.details?.viewTimestamp"
|
||||
[selection]="selection"
|
||||
[hideRefresh]="true"
|
||||
>
|
||||
<div class="table-wrapper">
|
||||
<table class="table" mat-table [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="activated">
|
||||
<th class="availability" mat-header-cell *matHeaderCellDef>
|
||||
<span>{{ 'SMTP.LIST.ACTIVATED' | translate }}</span>
|
||||
</th>
|
||||
<td class="pointer availability" mat-cell *matCellDef="let config">
|
||||
<i
|
||||
matTooltip="{{ 'SMTP.LIST.ACTIVATED' | translate }}"
|
||||
*ngIf="isActive(config.state)"
|
||||
class="smtp-available las la-check-circle"
|
||||
data-e2e="active-provider"
|
||||
></i>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="description">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'SETTING.SMTP.DESCRIPTION' | translate }}</th>
|
||||
<td class="pointer" mat-cell *matCellDef="let config">
|
||||
<span>{{ config?.description }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="tls">
|
||||
<th class="availability" mat-header-cell *matHeaderCellDef>
|
||||
<span>TLS</span>
|
||||
</th>
|
||||
<td class="pointer availability" mat-cell *matCellDef="let config">
|
||||
<i *ngIf="config.tls" class="las la-lock"></i>
|
||||
<i *ngIf="!config.tls" class="las la-unlock"></i>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="host">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'SETTING.SMTP.HOSTANDPORT' | translate }}</th>
|
||||
<td class="pointer" mat-cell *matCellDef="let config">
|
||||
<span>{{ config?.host }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="senderAddress">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'SETTING.SMTP.SENDERADDRESS' | translate }}</th>
|
||||
<td class="pointer" mat-cell *matCellDef="let config">
|
||||
<span>{{ config?.senderAddress }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions" stickyEnd>
|
||||
<th class="smtp-table-actions" mat-header-cell *matHeaderCellDef></th>
|
||||
<td class="smtp-table-actions" mat-cell *matCellDef="let config">
|
||||
<cnsl-table-actions>
|
||||
<button
|
||||
actions
|
||||
*ngIf="!isActive(config.state)"
|
||||
[disabled]="(['iam.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'SMTP.LIST.ACTIVATE' | translate }}"
|
||||
data-e2e="activate-provider-button"
|
||||
(click)="activateSMTPConfig(config.id); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-check-circle"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
actions
|
||||
*ngIf="isActive(config.state)"
|
||||
[disabled]="(['iam.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'SMTP.LIST.DEACTIVATE' | translate }}"
|
||||
data-e2e="deactivate-provider-button"
|
||||
(click)="deactivateSMTPConfig(config.id); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-times-circle"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
actions
|
||||
[disabled]="(['iam.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
data-e2e="delete-provider-button"
|
||||
(click)="deleteSMTPConfig(config.id, config.senderName); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</cnsl-table-actions>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" (click)="navigateToProvider(row)" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div *ngIf="(loading$ | async) === false && !dataSource?.data?.length" class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'SMTP.LIST.EMPTY' | translate }}</span>
|
||||
</div>
|
||||
|
||||
<cnsl-paginator
|
||||
#paginator
|
||||
class="paginator"
|
||||
[timestamp]="configsResult?.details?.viewTimestamp"
|
||||
[length]="configsResult?.details?.totalResult || 0"
|
||||
[pageSize]="10"
|
||||
[pageSizeOptions]="[10, 20, 50, 100]"
|
||||
(page)="changePage($event)"
|
||||
></cnsl-paginator>
|
||||
</cnsl-refresh-table>
|
81
console/src/app/modules/smtp-table/smtp-table.component.scss
Normal file
@ -0,0 +1,81 @@
|
||||
@mixin smtp-table-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$warn: map-get($theme, warn);
|
||||
$background: map-get($theme, background);
|
||||
$accent: map-get($theme, accent);
|
||||
$primary-color: map-get($primary, 500);
|
||||
$warn-color: map-get($warn, 500);
|
||||
$accent-color: map-get($accent, 500);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$back: map-get($background, background);
|
||||
|
||||
.smtp-table-provider-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.smtp-logo {
|
||||
margin-right: 1rem;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
}
|
||||
}
|
||||
|
||||
.smtp-icon {
|
||||
font-size: 1.75rem;
|
||||
height: 1.75rem;
|
||||
width: 1.75rem;
|
||||
margin-right: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.smtp-margin-right {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
td {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
tr {
|
||||
outline: none;
|
||||
|
||||
&.disabled,
|
||||
&.disabled * {
|
||||
opacity: 0.8;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.availability {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.smtp-available {
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.smtp-not-available {
|
||||
color: var(--warn);
|
||||
}
|
||||
|
||||
.smtp-table-actions {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.la-unlock {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
.la-lock {
|
||||
color: darkorange;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { IdpTableComponent } from './smtp-table.component';
|
||||
|
||||
describe('UserTableComponent', () => {
|
||||
let component: IdpTableComponent;
|
||||
let fixture: ComponentFixture<IdpTableComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [IdpTableComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(IdpTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
194
console/src/app/modules/smtp-table/smtp-table.component.ts
Normal file
@ -0,0 +1,194 @@
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { SMTPConfigState } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
import { ListQuery } from 'src/app/proto/generated/zitadel/object_pb';
|
||||
import { LoginPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
|
||||
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
|
||||
import { ListSMTPConfigsRequest, ListSMTPConfigsResponse } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { SMTPConfig } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-smtp-table',
|
||||
templateUrl: './smtp-table.component.html',
|
||||
styleUrls: ['./smtp-table.component.scss'],
|
||||
})
|
||||
export class SMTPTableComponent implements OnInit {
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
public dataSource: MatTableDataSource<SMTPConfig.AsObject> = new MatTableDataSource<SMTPConfig.AsObject>();
|
||||
public selection: SelectionModel<SMTPConfig.AsObject> = new SelectionModel<SMTPConfig.AsObject>(true, []);
|
||||
public configsResult?: ListSMTPConfigsResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public displayedColumns: string[] = ['activated', 'description', 'tls', 'host', 'senderAddress', 'actions'];
|
||||
@Output() public changedSelection: EventEmitter<Array<SMTPConfig.AsObject>> = new EventEmitter();
|
||||
|
||||
public loginPolicy!: LoginPolicy.AsObject;
|
||||
|
||||
constructor(
|
||||
private adminService: AdminService,
|
||||
public translate: TranslateService,
|
||||
private toast: ToastService,
|
||||
private dialog: MatDialog,
|
||||
private router: Router,
|
||||
) {
|
||||
this.selection.changed.subscribe(() => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getData(10, 0);
|
||||
}
|
||||
|
||||
public isActive(state: number) {
|
||||
return state === SMTPConfigState.SMTP_CONFIG_ACTIVE;
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.data.length;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach((row) => this.selection.select(row));
|
||||
}
|
||||
|
||||
public changePage(event: PageEvent): void {
|
||||
this.getData(event.pageSize, event.pageIndex * event.pageSize);
|
||||
}
|
||||
|
||||
public activateSMTPConfig(id: string): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.CONTINUE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'SMTP.LIST.DIALOG.ACTIVATE_WARN_TITLE',
|
||||
descriptionKey: 'SMTP.LIST.DIALOG.ACTIVATE_WARN_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
this.adminService
|
||||
.activateSMTPConfig(id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('SMTP.LIST.DIALOG.ACTIVATED', true);
|
||||
this.refreshPage();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public deactivateSMTPConfig(id: string): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.CONTINUE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'SMTP.LIST.DIALOG.DEACTIVATE_WARN_TITLE',
|
||||
descriptionKey: 'SMTP.LIST.DIALOG.DEACTIVATE_WARN_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
this.adminService
|
||||
.deactivateSMTPConfig(id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('SMTP.LIST.DIALOG.DEACTIVATED', true);
|
||||
this.refreshPage();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public deleteSMTPConfig(id: string, senderName: string): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'SMTP.LIST.DIALOG.DELETE_TITLE',
|
||||
descriptionKey: 'SMTP.LIST.DIALOG.DELETE_DESCRIPTION',
|
||||
confirmationKey: 'SMTP.LIST.DIALOG.SENDER',
|
||||
confirmation: senderName,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
this.adminService
|
||||
.removeSMTPConfig(id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('SMTP.LIST.DIALOG.DELETED', true);
|
||||
this.refreshPage();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getData(limit: number, offset: number): Promise<void> {
|
||||
this.loadingSubject.next(true);
|
||||
|
||||
const req = new ListSMTPConfigsRequest();
|
||||
const lq = new ListQuery();
|
||||
lq.setOffset(offset);
|
||||
lq.setLimit(limit);
|
||||
req.setQuery(lq);
|
||||
this.adminService
|
||||
.listSMTPConfigs()
|
||||
.then((resp) => {
|
||||
this.configsResult = resp;
|
||||
if (resp.resultList) {
|
||||
this.dataSource.data = resp.resultList;
|
||||
}
|
||||
this.loadingSubject.next(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
}
|
||||
|
||||
public refreshPage(): void {
|
||||
this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
|
||||
}
|
||||
|
||||
public get createRouterLink(): RouterLink | any {
|
||||
return ['/instance', 'idp', 'create'];
|
||||
}
|
||||
|
||||
public routerLinkForRow(row: SMTPConfig.AsObject): any {
|
||||
return ['/instance', 'smtpprovider', row.id];
|
||||
}
|
||||
|
||||
public get displayedColumnsWithActions(): string[] {
|
||||
return ['actions', ...this.displayedColumns];
|
||||
}
|
||||
|
||||
public navigateToProvider(row: SMTPConfig.AsObject) {
|
||||
this.router.navigate(this.routerLinkForRow(row));
|
||||
}
|
||||
}
|
46
console/src/app/modules/smtp-table/smtp-table.module.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
import { TruncatePipeModule } from 'src/app/pipes/truncate-pipe/truncate-pipe.module';
|
||||
|
||||
import { PaginatorModule } from '../paginator/paginator.module';
|
||||
import { TableActionsModule } from '../table-actions/table-actions.module';
|
||||
import { SMTPTableComponent } from './smtp-table.component';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SMTPTableComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatButtonModule,
|
||||
TableActionsModule,
|
||||
MatCheckboxModule,
|
||||
MatIconModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
LocalizedDatePipeModule,
|
||||
TimestampToDatePipeModule,
|
||||
MatTableModule,
|
||||
PaginatorModule,
|
||||
RouterModule,
|
||||
RefreshTableModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
TruncatePipeModule,
|
||||
],
|
||||
exports: [SMTPTableComponent],
|
||||
})
|
||||
export class SMTPTableModule {}
|
@ -32,6 +32,15 @@ const routes: Routes = [
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'smtpprovider',
|
||||
canActivate: [AuthGuard, RoleGuard],
|
||||
loadChildren: () => import('src/app/modules/smtp-provider/smtp-provider.module'),
|
||||
data: {
|
||||
roles: ['iam.idp.read'],
|
||||
serviceType: PolicyComponentServiceType.ADMIN,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -6,6 +6,8 @@ import {
|
||||
ActivateLabelPolicyResponse,
|
||||
ActivateSMSProviderRequest,
|
||||
ActivateSMSProviderResponse,
|
||||
ActivateSMTPConfigRequest,
|
||||
ActivateSMTPConfigResponse,
|
||||
AddAppleProviderRequest,
|
||||
AddAppleProviderResponse,
|
||||
AddAzureADProviderRequest,
|
||||
@ -52,6 +54,8 @@ import {
|
||||
DeactivateIDPResponse,
|
||||
DeactivateSMSProviderRequest,
|
||||
DeactivateSMSProviderResponse,
|
||||
DeactivateSMTPConfigRequest,
|
||||
DeactivateSMTPConfigResponse,
|
||||
DeleteProviderRequest,
|
||||
DeleteProviderResponse,
|
||||
GetAllowedLanguagesRequest,
|
||||
@ -135,6 +139,8 @@ import {
|
||||
GetSecurityPolicyResponse,
|
||||
GetSMSProviderRequest,
|
||||
GetSMSProviderResponse,
|
||||
GetSMTPConfigByIdRequest,
|
||||
GetSMTPConfigByIdResponse,
|
||||
GetSMTPConfigRequest,
|
||||
GetSMTPConfigResponse,
|
||||
GetSupportedLanguagesRequest,
|
||||
@ -167,6 +173,8 @@ import {
|
||||
ListSecretGeneratorsResponse,
|
||||
ListSMSProvidersRequest,
|
||||
ListSMSProvidersResponse,
|
||||
ListSMTPConfigsRequest,
|
||||
ListSMTPConfigsResponse,
|
||||
ListViewsRequest,
|
||||
ListViewsResponse,
|
||||
ReactivateIDPRequest,
|
||||
@ -193,6 +201,8 @@ import {
|
||||
RemoveSecondFactorFromLoginPolicyResponse,
|
||||
RemoveSMSProviderRequest,
|
||||
RemoveSMSProviderResponse,
|
||||
RemoveSMTPConfigRequest,
|
||||
RemoveSMTPConfigResponse,
|
||||
ResetCustomDomainPolicyToDefaultRequest,
|
||||
ResetCustomDomainPolicyToDefaultResponse,
|
||||
ResetCustomLoginTextsToDefaultRequest,
|
||||
@ -894,6 +904,17 @@ export class AdminService {
|
||||
return this.grpcService.admin.getSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public getSMTPConfigById(id: string): Promise<GetSMTPConfigByIdResponse.AsObject> {
|
||||
const req = new GetSMTPConfigByIdRequest();
|
||||
req.setId(id);
|
||||
return this.grpcService.admin.getSMTPConfigById(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public listSMTPConfigs(): Promise<ListSMTPConfigsResponse.AsObject> {
|
||||
const req = new ListSMTPConfigsRequest();
|
||||
return this.grpcService.admin.listSMTPConfigs(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public addSMTPConfig(req: AddSMTPConfigRequest): Promise<AddSMTPConfigResponse.AsObject> {
|
||||
return this.grpcService.admin.addSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
@ -906,6 +927,24 @@ export class AdminService {
|
||||
return this.grpcService.admin.updateSMTPConfigPassword(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public activateSMTPConfig(id: string): Promise<ActivateSMTPConfigResponse.AsObject> {
|
||||
const req = new ActivateSMTPConfigRequest();
|
||||
req.setId(id);
|
||||
return this.grpcService.admin.activateSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public deactivateSMTPConfig(id: string): Promise<DeactivateSMTPConfigResponse.AsObject> {
|
||||
const req = new DeactivateSMTPConfigRequest();
|
||||
req.setId(id);
|
||||
return this.grpcService.admin.deactivateSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public removeSMTPConfig(id: string): Promise<RemoveSMTPConfigResponse.AsObject> {
|
||||
const req = new RemoveSMTPConfigRequest();
|
||||
req.setId(id);
|
||||
return this.grpcService.admin.removeSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
/* sms */
|
||||
|
||||
public listSMSProviders(): Promise<ListSMSProvidersResponse.AsObject> {
|
||||
|
@ -1374,6 +1374,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP настройки",
|
||||
"DESCRIPTION": "Описание",
|
||||
"SENDERADDRESS": "Имейл адрес на изпращача",
|
||||
"SENDERNAME": "Име на изпращача",
|
||||
"REPLYTOADDRESS": "Reply-to адрес",
|
||||
@ -1384,6 +1386,7 @@
|
||||
"PASSWORDSET": "Паролата за SMTP бе зададена успешно.",
|
||||
"TLS": "Сигурност на транспортния слой (TLS)",
|
||||
"SAVED": "Запазено успешно!",
|
||||
"NOCHANGES": "Без промени!",
|
||||
"REQUIREDWARN": "За да изпращате известия от вашия домейн, трябва да въведете своите SMTP данни."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2208,6 +2211,48 @@
|
||||
"1": "Позволен"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP доставчик",
|
||||
"DESCRIPTION": "Това са SMTP доставчиците за вашето копие на Zitadel. Активирайте този, който искате да използвате, за да изпращате известия до вашите потребители.",
|
||||
"EMPTY": "Няма наличен SMTP доставчик",
|
||||
"ACTIVATED": "Активиран",
|
||||
"ACTIVATE": "Активирайте доставчика",
|
||||
"DEACTIVATE": "Деактивирайте доставчика",
|
||||
"TYPE": "Тип",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP конфигурацията е активирана",
|
||||
"ACTIVATE_WARN_TITLE": "Активирайте SMTP конфигурацията",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "На път сте да активирате SMTP конфигурация. Първо ще деактивираме текущия активен доставчик и след това ще активираме тази конфигурация. Сигурен ли си?",
|
||||
"DEACTIVATE_WARN_TITLE": "Деактивирайте SMTP конфигурацията",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "На път сте да деактивирате SMTP конфигурация. Сигурен ли си?",
|
||||
"DEACTIVATED": "SMTP конфигурацията е деактивирана",
|
||||
"DELETE_TITLE": "Изтриване на SMTP конфигурация",
|
||||
"DELETE_DESCRIPTION": "На път сте да изтриете конфигурация. Потвърдете това действие, като въведете името на подателя",
|
||||
"DELETED": "SMTP конфигурацията е изтрита",
|
||||
"SENDER": "Въведете {{ value }}, за да изтриете тази SMTP конфигурация."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Добавете SMTP доставчик",
|
||||
"DESCRIPTION": "Изберете един или повече от следните доставчици.",
|
||||
"STEPS": {
|
||||
"TITLE": "Добавете {{ value }} SMTP доставчик",
|
||||
"CREATE_DESC_TITLE": "Въведете своите {{ value }} SMTP настройки стъпка по стъпка",
|
||||
"CURRENT_DESC_TITLE": "Това са вашите SMTP настройки",
|
||||
"PROVIDER_SETTINGS": "Настройки на SMTP доставчик",
|
||||
"SENDER_SETTINGS": "Настройки на изпращача",
|
||||
"TEST_SETTINGS": "Тествайте настройките на SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Настройки на SMTP доставчик"
|
||||
},
|
||||
"EMPTY": "Няма наличен SMTP доставчик",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Приложения",
|
||||
"COMPLIANCE": "Съответствие с OIDC",
|
||||
|
@ -1381,6 +1381,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Nastavení SMTP",
|
||||
"DESCRIPTION": "Popis",
|
||||
"SENDERADDRESS": "E-mailová adresa odesílatele",
|
||||
"SENDERNAME": "Jméno odesílatele",
|
||||
"REPLYTOADDRESS": "Adresa pro odpovědi",
|
||||
@ -1391,6 +1393,7 @@
|
||||
"PASSWORDSET": "SMTP heslo bylo úspěšně nastaveno.",
|
||||
"TLS": "Zabezpečení transportní vrstvy (TLS)",
|
||||
"SAVED": "Úspěšně uloženo!",
|
||||
"NOCHANGES": "Žádné změny!",
|
||||
"REQUIREDWARN": "Pro odesílání oznámení z vaší domény musíte zadat vaše SMTP údaje."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2227,6 +2230,48 @@
|
||||
"1": "Povoleno"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "Poskytovatel SMTP",
|
||||
"DESCRIPTION": "Toto jsou poskytovatelé SMTP pro vaši instanci Zitadel. Aktivujte ten, který chcete používat k odesílání upozornění svým uživatelům.",
|
||||
"EMPTY": "Není k dispozici žádný poskytovatel SMTP",
|
||||
"ACTIVATED": "Aktivováno",
|
||||
"ACTIVATE": "Aktivujte poskytovatele",
|
||||
"DEACTIVATE": "Deaktivovat poskytovatele",
|
||||
"TYPE": "Typ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Konfigurace SMTP byla aktivována",
|
||||
"ACTIVATE_WARN_TITLE": "Aktivujte konfiguraci SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Chystáte se aktivovat konfiguraci SMTP. Nejprve deaktivujeme aktuálního aktivního poskytovatele a poté aktivujeme tuto konfiguraci. Jsi si jistá?",
|
||||
"DEACTIVATE_WARN_TITLE": "Deaktivujte konfiguraci SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Chystáte se deaktivovat konfiguraci SMTP. Jsi si jistá?",
|
||||
"DEACTIVATED": "Konfigurace SMTP byla deaktivována",
|
||||
"DELETE_TITLE": "Smazat konfiguraci SMTP",
|
||||
"DELETE_DESCRIPTION": "Chystáte se smazat konfiguraci. Potvrďte tuto akci zadáním jména odesílatele",
|
||||
"DELETED": "Konfigurace SMTP byla smazána",
|
||||
"SENDER": "Chcete-li smazat tuto konfiguraci SMTP, zadejte {{ value }}."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Přidat poskytovatele SMTP",
|
||||
"DESCRIPTION": "Vyberte jednoho nebo více z následujících poskytovatelů.",
|
||||
"STEPS": {
|
||||
"TITLE": "Přidejte {{ value }} poskytovatele SMTP",
|
||||
"CREATE_DESC_TITLE": "Krok za krokem zadejte nastavení SMTP {{ value }}",
|
||||
"CURRENT_DESC_TITLE": "Toto jsou vaše nastavení SMTP",
|
||||
"PROVIDER_SETTINGS": "Nastavení poskytovatele SMTP",
|
||||
"SENDER_SETTINGS": "Nastavení odesílatele",
|
||||
"TEST_SETTINGS": "Otestujte nastavení SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Nastavení poskytovatele SMTP"
|
||||
},
|
||||
"EMPTY": "Není k dispozici žádný poskytovatel SMTP",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Aplikace",
|
||||
"COMPLIANCE": "OIDC Kompatibilita",
|
||||
|
@ -1380,6 +1380,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP Einstellungen",
|
||||
"DESCRIPTION": "Beschreibung",
|
||||
"SENDERADDRESS": "Sender Email-Adresse",
|
||||
"SENDERNAME": "Sender Name",
|
||||
"REPLYTOADDRESS": "Reply-to-Adresse",
|
||||
@ -1390,6 +1392,7 @@
|
||||
"PASSWORDSET": "SMTP Passwort erfolgreich gesetzt.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "Erfolgreich gespeichert.",
|
||||
"NOCHANGES": "Keine Änderungen!",
|
||||
"REQUIREDWARN": "Damit Mails von Ihrer Domain verschickt werden können, müssen Sie Ihre SMTP Einstellungen konfigurieren."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2217,6 +2220,48 @@
|
||||
"1": "Erlaubt"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP-Anbieter",
|
||||
"DESCRIPTION": "Dies sind die SMTP-Anbieter für Ihre Zitadel-Instanz. Aktivieren Sie diejenige, die Sie zum Senden von Benachrichtigungen an Ihre Benutzer verwenden möchten.",
|
||||
"EMPTY": "Kein SMTP-Anbieter verfügbar",
|
||||
"ACTIVATED": "Aktiviert",
|
||||
"ACTIVATE": "Anbieter aktivieren",
|
||||
"DEACTIVATE": "Anbieter deaktivieren",
|
||||
"TYPE": "Typ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Die SMTP-Konfiguration wurde aktiviert",
|
||||
"ACTIVATE_WARN_TITLE": "Aktivieren Sie die SMTP-Konfiguration",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Sie sind dabei, eine SMTP-Konfiguration zu aktivieren. Zuerst deaktivieren wir den aktuell aktiven Anbieter und aktivieren dann diese Konfiguration. Bist du sicher?",
|
||||
"DEACTIVATE_WARN_TITLE": "Deaktivieren Sie die SMTP-Konfiguration",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Sie sind dabei, eine SMTP-Konfiguration zu deaktivieren. Bist du sicher?",
|
||||
"DEACTIVATED": "Die SMTP-Konfiguration wurde deaktiviert",
|
||||
"DELETE_TITLE": "SMTP-Konfiguration löschen",
|
||||
"DELETE_DESCRIPTION": "Sie sind dabei, eine Konfiguration zu löschen. Bestätigen Sie diese Aktion, indem Sie den Absendernamen eingeben",
|
||||
"DELETED": "SMTP-Konfiguration wurde gelöscht",
|
||||
"SENDER": "Geben Sie {{ value }} ein, um diese SMTP-Konfiguration zu löschen."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "SMTP-Anbieter hinzufügen",
|
||||
"DESCRIPTION": "Wählen Sie einen oder mehrere der folgenden Anbieter aus.",
|
||||
"STEPS": {
|
||||
"TITLE": "Fügen Sie {{ value }} SMTP-Anbieter hinzu",
|
||||
"CREATE_DESC_TITLE": "Geben Sie Schritt für Schritt Ihre {{ value }} SMTP-Einstellungen ein",
|
||||
"CURRENT_DESC_TITLE": "Dies sind Ihre SMTP-Einstellungen",
|
||||
"PROVIDER_SETTINGS": "SMTP-Anbietereinstellungen",
|
||||
"SENDER_SETTINGS": "Absendereinstellungen",
|
||||
"TEST_SETTINGS": "Testen Sie die SMTP-Einstellungen"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "SMTP-Anbietereinstellungen"
|
||||
},
|
||||
"EMPTY": "Kein SMTP-Anbieter verfügbar",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Apps",
|
||||
"COMPLIANCE": "OIDC Einhaltung",
|
||||
|
@ -1381,6 +1381,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP Provider",
|
||||
"DESCRIPTION": "Description",
|
||||
"SENDERADDRESS": "Sender Email Address",
|
||||
"SENDERNAME": "Sender Name",
|
||||
"REPLYTOADDRESS": "Reply-to Address",
|
||||
@ -1391,6 +1393,7 @@
|
||||
"PASSWORDSET": "SMTP Password was set successfully.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "Saved successfully!",
|
||||
"NOCHANGES": "No changes!",
|
||||
"REQUIREDWARN": "To send notifications from your domain, you have to enter your SMTP data."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2236,6 +2239,48 @@
|
||||
"1": "Allowed"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP Provider",
|
||||
"DESCRIPTION": "These are the SMTP providers for your Zitadel instance. Activate the one you want to use to send notifications to your users.",
|
||||
"EMPTY": "No SMTP Provider available",
|
||||
"ACTIVATED": "Activated",
|
||||
"ACTIVATE": "Activate provider",
|
||||
"DEACTIVATE": "Deactivate provider",
|
||||
"TYPE": "Type",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP config has been activated",
|
||||
"ACTIVATE_WARN_TITLE": "Activate SMTP config",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "You are about to activate an SMTP configuration. First we'll deactivate the current active provider and then activate this configuration. Are you sure?",
|
||||
"DEACTIVATE_WARN_TITLE": "Deactivate SMTP config",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "You are about to deactivate an SMTP configuration. Are you sure?",
|
||||
"DEACTIVATED": "SMTP config has been deactivated",
|
||||
"DELETE_TITLE": "Delete SMTP config",
|
||||
"DELETE_DESCRIPTION": "You are about to delete a configuration. Confirm this action typing the sender name",
|
||||
"DELETED": "SMTP config has been deleted",
|
||||
"SENDER": "Type {{value}}, to delete this SMTP configuration."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Add SMTP provider",
|
||||
"DESCRIPTION": "Select one ore more of the following providers.",
|
||||
"STEPS": {
|
||||
"TITLE": "Add {{ value }} SMTP Provider",
|
||||
"CREATE_DESC_TITLE": "Enter your {{ value }} SMTP settings step by step",
|
||||
"CURRENT_DESC_TITLE": "These are your SMTP settings",
|
||||
"PROVIDER_SETTINGS": "SMTP Provider Settings",
|
||||
"SENDER_SETTINGS": "Sender Settings",
|
||||
"TEST_SETTINGS": "Test SMTP Settings"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "SMTP Provider Settings"
|
||||
},
|
||||
"EMPTY": "No SMTP provider available",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Applications",
|
||||
"COMPLIANCE": "OIDC Compliance",
|
||||
|
@ -1382,6 +1382,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Ajustes SMTP",
|
||||
"DESCRIPTION": "Descripción",
|
||||
"SENDERADDRESS": "Dirección email del emisor",
|
||||
"SENDERNAME": "Nombre del emisor",
|
||||
"REPLYTOADDRESS": "Dirección Reply-To",
|
||||
@ -1392,6 +1394,7 @@
|
||||
"PASSWORDSET": "La contraseña SMTP se estableció con éxito.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "¡Se guardó con éxito!",
|
||||
"NOCHANGES": "¡Sin cambios!",
|
||||
"REQUIREDWARN": "Para enviar notificaciones para tu dominio, debes introducir tus datos SMTP."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2215,6 +2218,48 @@
|
||||
"1": "Permitido"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "Proveedor SMTP",
|
||||
"DESCRIPTION": "Estos son los proveedores SMTP para tu instancia de Zitadel. Activa el que quieras utilizar para enviar notificaciones a tus usuarios.",
|
||||
"EMPTY": "No hay ningún proveedor SMTP disponible",
|
||||
"ACTIVATED": "Activado",
|
||||
"ACTIVATE": "Activar proveedor",
|
||||
"DEACTIVATE": "Desactivar proveedor",
|
||||
"TYPE": "Tipo",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Tu configuración SMTP ha sido activada",
|
||||
"ACTIVATE_WARN_TITLE": "Activar configuración SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Estás a punto de activar una configuración SMTP. Primero desactivaremos la configuración de tu proveedor actual y después activaremos esta configuración. ¿Estás seguro?",
|
||||
"DEACTIVATE_WARN_TITLE": "Desactivar configuración SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Estás a punto de desactivar una configuración SMTP. ¿Está seguro?",
|
||||
"DEACTIVATED": "La configuración SMTP ha sido desactivada",
|
||||
"DELETE_TITLE": "Eliminar configuración SMTP",
|
||||
"DELETE_DESCRIPTION": "Estás a punto de eliminar una configuración. Confirma esta acción escribiendo el nombre del remitente",
|
||||
"DELETED": "La configuración SMTP ha sido eliminada",
|
||||
"SENDER": "Escribe {{ value }} para eliminar esta configuración SMTP."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Agrega un proveedor SMTP",
|
||||
"DESCRIPTION": "Selecciona uno o más de los siguientes proveedores.",
|
||||
"STEPS": {
|
||||
"TITLE": "Agrega un proveedor SMTP {{ value }} ",
|
||||
"CREATE_DESC_TITLE": "Introduce tu configuración SMTP de {{ value }} paso a paso",
|
||||
"CURRENT_DESC_TITLE": "Estas son tus configuraciones SMTP",
|
||||
"PROVIDER_SETTINGS": "Configuración del proveedor SMTP",
|
||||
"SENDER_SETTINGS": "Configuración del remitente",
|
||||
"TEST_SETTINGS": "Probar la configuración SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Configuración del proveedor SMTP"
|
||||
},
|
||||
"EMPTY": "No hay ningún proveedor SMTP disponible",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Aplicaciones",
|
||||
"COMPLIANCE": "Cumplimiento OIDC",
|
||||
|
@ -1380,6 +1380,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Paramètres SMTP",
|
||||
"DESCRIPTION": "Description",
|
||||
"SENDERADDRESS": "Adresse e-mail de l'expéditeur",
|
||||
"SENDERNAME": "Nom de l'expéditeur",
|
||||
"REPLYTOADDRESS": "Adresse Reply-to",
|
||||
@ -1390,6 +1392,7 @@
|
||||
"PASSWORDSET": "Le mot de passe SMTP a été défini avec succès.",
|
||||
"TLS": "Sécurité de la couche de transport (TLS)",
|
||||
"SAVED": "Enregistré avec succès!",
|
||||
"NOCHANGES": "Aucun changement!",
|
||||
"REQUIREDWARN": "Pour envoyer des notifications depuis votre domaine, vous devez entrer vos données SMTP."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2218,6 +2221,48 @@
|
||||
"1": "Autorisée"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "Fournisseur SMTP",
|
||||
"DESCRIPTION": "Ce sont les fournisseurs SMTP de votre instance Zitadel. Activez celui que vous souhaitez utiliser pour envoyer des notifications à vos utilisateurs.",
|
||||
"EMPTY": "Aucun fournisseur SMTP disponible",
|
||||
"ACTIVATED": "Activé",
|
||||
"ACTIVATE": "Activer le fournisseur",
|
||||
"DEACTIVATE": "Désactiver le fournisseur",
|
||||
"TYPE": "Taper",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "La configuration SMTP a été activée",
|
||||
"ACTIVATE_WARN_TITLE": "Activer la configuration SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Vous êtes sur le point d'activer une configuration SMTP. Nous allons d’abord désactiver le fournisseur actif actuel, puis activer cette configuration. Es-tu sûr?",
|
||||
"DEACTIVATE_WARN_TITLE": "Désactiver la configuration SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Vous êtes sur le point de désactiver une configuration SMTP. Es-tu sûr?",
|
||||
"DEACTIVATED": "La configuration SMTP a été désactivée",
|
||||
"DELETE_TITLE": "Supprimer la configuration SMTP",
|
||||
"DELETE_DESCRIPTION": "Vous êtes sur le point de supprimer une configuration. Confirmez cette action en tapant le nom de l'expéditeur",
|
||||
"DELETED": "La configuration SMTP a été supprimée",
|
||||
"SENDER": "Tapez {{ value }} pour supprimer cette configuration SMTP."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Ajouter un fournisseur SMTP",
|
||||
"DESCRIPTION": "Sélectionnez un ou plusieurs des fournisseurs suivants.",
|
||||
"STEPS": {
|
||||
"TITLE": "Ajouter {{ value }} fournisseur SMTP",
|
||||
"CREATE_DESC_TITLE": "Entrez vos paramètres SMTP {{ value }} étape par étape",
|
||||
"CURRENT_DESC_TITLE": "Ce sont vos paramètres SMTP",
|
||||
"PROVIDER_SETTINGS": "Paramètres du fournisseur SMTP",
|
||||
"SENDER_SETTINGS": "Paramètres de l'expéditeur",
|
||||
"TEST_SETTINGS": "Tester les paramètres SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Paramètres du fournisseur SMTP"
|
||||
},
|
||||
"EMPTY": "Aucun fournisseur SMTP disponible",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Applications",
|
||||
"COMPLIANCE": "Conformité à l'OIDC",
|
||||
|
@ -1380,6 +1380,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Impostazioni SMTP",
|
||||
"DESCRIPTION": "Descrizione",
|
||||
"SENDERADDRESS": "Indirizzo email del mittente",
|
||||
"SENDERNAME": "Nome del mittente",
|
||||
"REPLYTOADDRESS": "Indirizzo Reply-to",
|
||||
@ -1390,6 +1392,7 @@
|
||||
"PASSWORDSET": "SMTP Password impostata con successo.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "Salvato con successo!",
|
||||
"NOCHANGES": "Nessun cambiamento!",
|
||||
"REQUIREDWARN": "Per inviare notifiche dal tuo dominio, devi inserire i tuoi dati SMTP."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2218,6 +2221,48 @@
|
||||
"1": "Consentito"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "Fornitore SMTP",
|
||||
"DESCRIPTION": "Questi sono i provider SMTP per la tua istanza Zitadel. Attiva quello che desideri utilizzare per inviare notifiche ai tuoi utenti.",
|
||||
"EMPTY": "Nessun provider SMTP disponibile",
|
||||
"ACTIVATED": "Attivato",
|
||||
"ACTIVATE": "Attiva fornitore",
|
||||
"DEACTIVATE": "Disattiva fornitore",
|
||||
"TYPE": "Tipo",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "La configurazione SMTP è stata attivata",
|
||||
"ACTIVATE_WARN_TITLE": "Attiva la configurazione SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Stai per attivare una configurazione SMTP. Per prima cosa disattiveremo il provider attualmente attivo e poi attiveremo questa configurazione. Sei sicuro?",
|
||||
"DEACTIVATE_WARN_TITLE": "Disattiva la configurazione SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Stai per disattivare una configurazione SMTP. Sei sicuro?",
|
||||
"DEACTIVATED": "La configurazione SMTP è stata disattivata",
|
||||
"DELETE_TITLE": "Elimina configurazione SMTP",
|
||||
"DELETE_DESCRIPTION": "Stai per eliminare una configurazione. Conferma questa azione digitando il nome del mittente",
|
||||
"DELETED": "La configurazione SMTP è stata eliminata",
|
||||
"SENDER": "Digita {{ value }} per eliminare questa configurazione SMTP."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Aggiungi provider SMTP",
|
||||
"DESCRIPTION": "Seleziona uno o più dei seguenti fornitori.",
|
||||
"STEPS": {
|
||||
"TITLE": "Aggiungi {{ value }} provider SMTP",
|
||||
"CREATE_DESC_TITLE": "Inserisci le tue impostazioni SMTP {{ value }} passo dopo passo",
|
||||
"CURRENT_DESC_TITLE": "Queste sono le tue impostazioni SMTP",
|
||||
"PROVIDER_SETTINGS": "Impostazioni del provider SMTP",
|
||||
"SENDER_SETTINGS": "Impostazioni mittente",
|
||||
"TEST_SETTINGS": "Testare le impostazioni SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Impostazioni del provider SMTP"
|
||||
},
|
||||
"EMPTY": "Nessun provider SMTP disponibile",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Applicazioni",
|
||||
"COMPLIANCE": "Conformità con OIDC",
|
||||
|
@ -1381,6 +1381,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP設定",
|
||||
"DESCRIPTION": "説明",
|
||||
"SENDERADDRESS": "送信者のメールアドレス",
|
||||
"SENDERNAME": "送信者名",
|
||||
"REPLYTOADDRESS": "返信先アドレス",
|
||||
@ -1391,6 +1393,7 @@
|
||||
"PASSWORDSET": "SMTPパスワードは正常に設定されました。",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "正常に保存されました!",
|
||||
"NOCHANGES": "変更はありません!",
|
||||
"REQUIREDWARN": "ドメインから通知を送信するには、SMTP情報を入力する必要があります。"
|
||||
},
|
||||
"SMS": {
|
||||
@ -2209,6 +2212,48 @@
|
||||
"1": "有効"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTPプロバイダー",
|
||||
"DESCRIPTION": "これらは、Zitadel インスタンスの SMTP プロバイダーです。ユーザーに通知を送信するために使用するものをアクティブにします。",
|
||||
"EMPTY": "使用可能な SMTP プロバイダーがありません",
|
||||
"ACTIVATED": "アクティブ化された",
|
||||
"ACTIVATE": "プロバイダーをアクティブ化する",
|
||||
"DEACTIVATE": "プロバイダーを非アクティブ化する",
|
||||
"TYPE": "タイプ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP設定が有効化されました",
|
||||
"ACTIVATE_WARN_TITLE": "SMTP設定を有効にする",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "SMTP 構成をアクティブにしようとしています。まず、現在アクティブなプロバイダーを非アクティブ化してから、この構成をアクティブ化します。本気ですか?",
|
||||
"DEACTIVATE_WARN_TITLE": "SMTP設定を無効にする",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "SMTP 構成を非アクティブ化しようとしています。本気ですか?",
|
||||
"DEACTIVATED": "SMTP設定が無効化されました",
|
||||
"DELETE_TITLE": "SMTP設定を削除する",
|
||||
"DELETE_DESCRIPTION": "構成を削除しようとしています。送信者名を入力してこのアクションを確認します",
|
||||
"DELETED": "SMTP設定が削除されました",
|
||||
"SENDER": "この SMTP 構成を削除するには、「{{ value }}」と入力します。"
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "SMTPプロバイダーの追加",
|
||||
"DESCRIPTION": "次のプロバイダーから 1 つ以上を選択します。",
|
||||
"STEPS": {
|
||||
"TITLE": "{{ value }} SMTP プロバイダーを追加",
|
||||
"CREATE_DESC_TITLE": "{{ value }} SMTP 設定をステップごとに入力します",
|
||||
"CURRENT_DESC_TITLE": "これらは SMTP 設定です",
|
||||
"PROVIDER_SETTINGS": "SMTPプロバイダーの設定",
|
||||
"SENDER_SETTINGS": "送信者の設定",
|
||||
"TEST_SETTINGS": "SMTP設定をテストする"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "SMTPプロバイダーの設定"
|
||||
},
|
||||
"EMPTY": "使用可能な SMTP プロバイダーがありません",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "アプリケーション",
|
||||
"COMPLIANCE": "OIDCコンプライアンス",
|
||||
|
@ -1382,6 +1382,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP подесувања",
|
||||
"DESCRIPTION": "Опис",
|
||||
"SENDERADDRESS": "Адреса на испраќачот",
|
||||
"SENDERNAME": "Име на испраќачот",
|
||||
"REPLYTOADDRESS": "Reply-to адреса",
|
||||
@ -1392,6 +1394,7 @@
|
||||
"PASSWORDSET": "SMTP лозинката е успешно поставена.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "Успешно зачувано!",
|
||||
"NOCHANGES": "Нема промени!",
|
||||
"REQUIREDWARN": "За да испраќате известувања од вашиот домен, мора да ги внесете вашите SMTP податоци."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2215,6 +2218,48 @@
|
||||
"1": "Дозволено"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP провајдер",
|
||||
"DESCRIPTION": "Ова се давателите на SMTP за вашиот пример Zitadel. Активирајте го оној што сакате да го користите за испраќање известувања до вашите корисници.",
|
||||
"EMPTY": "Нема достапен SMTP провајдер",
|
||||
"ACTIVATED": "Активиран",
|
||||
"ACTIVATE": "Активирајте го провајдерот",
|
||||
"DEACTIVATE": "Деактивирајте го провајдерот",
|
||||
"TYPE": "Тип",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP конфигурацијата е активирана",
|
||||
"ACTIVATE_WARN_TITLE": "Активирајте SMTP конфигурација",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Ќе активирате SMTP конфигурација. Прво ќе го деактивираме тековниот активен провајдер, а потоа ќе ја активираме оваа конфигурација. Дали си сигурен?",
|
||||
"DEACTIVATE_WARN_TITLE": "Деактивирајте ја конфигурацијата SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Ќе деактивирате SMTP конфигурација. Дали си сигурен?",
|
||||
"DEACTIVATED": "SMTP конфигурацијата е деактивирана",
|
||||
"DELETE_TITLE": "Избришете ја конфигурацијата SMTP",
|
||||
"DELETE_DESCRIPTION": "Ќе избришете конфигурација. Потврдете го ова дејство со внесување на името на испраќачот",
|
||||
"DELETED": "SMTP конфигурацијата е избришана",
|
||||
"SENDER": "Внесете {{ value }}, за да ја избришете оваа SMTP конфигурација."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Додадете SMTP провајдер",
|
||||
"DESCRIPTION": "Изберете еден или повеќе од следните провајдери.",
|
||||
"STEPS": {
|
||||
"TITLE": "Додадете {{ value }} SMTP провајдер",
|
||||
"CREATE_DESC_TITLE": "Внесете ги вашите поставки за {{ value }} SMTP чекор по чекор",
|
||||
"CURRENT_DESC_TITLE": "Ова се вашите поставки за SMTP",
|
||||
"PROVIDER_SETTINGS": "Поставки на провајдерот SMTP",
|
||||
"SENDER_SETTINGS": "Поставки на испраќачот",
|
||||
"TEST_SETTINGS": "Тестирајте ги поставките за SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Поставки на провајдерот SMTP"
|
||||
},
|
||||
"EMPTY": "Нема достапен SMTP провајдер",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Апликации",
|
||||
"COMPLIANCE": "OIDC Соодветност",
|
||||
|
@ -1381,6 +1381,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP Instellingen",
|
||||
"DESCRIPTION": "Beschrijving",
|
||||
"SENDERADDRESS": "Afzender Email Adres",
|
||||
"SENDERNAME": "Afzender Naam",
|
||||
"REPLYTOADDRESS": "Antwoord-naar Adres",
|
||||
@ -1391,6 +1393,7 @@
|
||||
"PASSWORDSET": "SMTP Wachtwoord is succesvol ingesteld.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "Succesvol opgeslagen!",
|
||||
"NOCHANGES": "Geen veranderingen!",
|
||||
"REQUIREDWARN": "Om notificaties te kunnen versturen vanaf uw domein, moet u uw SMTP-gegevens invoeren."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2236,6 +2239,48 @@
|
||||
"1": "Toegestaan"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP-provider",
|
||||
"DESCRIPTION": "Dit zijn de SMTP-providers voor uw Zitadel-instantie. Activeer degene die u wilt gebruiken om meldingen naar uw gebruikers te sturen.",
|
||||
"EMPTY": "Geen SMTP-provider beschikbaar",
|
||||
"ACTIVATED": "Geactiveerd",
|
||||
"ACTIVATE": "Aanbieder activeren",
|
||||
"DEACTIVATE": "Aanbieder deactiveren",
|
||||
"TYPE": "Type",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP-configuratie is geactiveerd",
|
||||
"ACTIVATE_WARN_TITLE": "Activeer SMTP-configuratie",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "U staat op het punt een SMTP-configuratie te activeren. Eerst deactiveren we de huidige actieve provider en activeren vervolgens deze configuratie. Weet je het zeker?",
|
||||
"DEACTIVATE_WARN_TITLE": "Deactiveer SMTP-configuratie",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "U staat op het punt een SMTP-configuratie te deactiveren. Weet je het zeker?",
|
||||
"DEACTIVATED": "SMTP-configuratie is gedeactiveerd",
|
||||
"DELETE_TITLE": "SMTP-configuratie verwijderen",
|
||||
"DELETE_DESCRIPTION": "U staat op het punt een configuratie te verwijderen. Bevestig deze actie door de naam van de afzender te typen",
|
||||
"DELETED": "SMTP-configuratie is verwijderd",
|
||||
"SENDER": "Typ {{ value }} om deze SMTP-configuratie te verwijderen."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "SMTP-provider toevoegen",
|
||||
"DESCRIPTION": "Selecteer één of meer van de volgende aanbieders.",
|
||||
"STEPS": {
|
||||
"TITLE": "Voeg {{ value }} SMTP-provider toe",
|
||||
"CREATE_DESC_TITLE": "Voer stap voor stap uw {{ value }} SMTP-instellingen in",
|
||||
"CURRENT_DESC_TITLE": "Dit zijn uw SMTP-instellingen",
|
||||
"PROVIDER_SETTINGS": "SMTP-providerinstellingen",
|
||||
"SENDER_SETTINGS": "Afzenderinstellingen",
|
||||
"TEST_SETTINGS": "SMTP-instellingen testen"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "SMTP-providerinstellingen"
|
||||
},
|
||||
"EMPTY": "Geen SMTP-provider beschikbaar",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Toepassingen",
|
||||
"COMPLIANCE": "OIDC Conformiteit",
|
||||
|
@ -1380,6 +1380,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Ustawienia SMTP",
|
||||
"DESCRIPTION": "Opis",
|
||||
"SENDERADDRESS": "Adres e-mail nadawcy",
|
||||
"SENDERNAME": "Nazwa nadawcy",
|
||||
"REPLYTOADDRESS": "Adres Reply-to",
|
||||
@ -1390,6 +1392,7 @@
|
||||
"PASSWORDSET": "Hasło SMTP zostało pomyślnie ustawione.",
|
||||
"TLS": "Bezpieczeństwo warstwy transportu (TLS)",
|
||||
"SAVED": "Pomyślnie zapisano!",
|
||||
"NOCHANGES": "Bez zmian!",
|
||||
"REQUIREDWARN": "Aby wysyłać powiadomienia z twojej domeny, musisz podać dane SMTP."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2218,6 +2221,48 @@
|
||||
"1": "Dozwolone"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "Dostawca SMTP",
|
||||
"DESCRIPTION": "To są dostawcy SMTP dla Twojej instancji Zitadel. Aktywuj ten, którego chcesz używać do wysyłania powiadomień do użytkowników.",
|
||||
"EMPTY": "Brak dostępnego dostawcy SMTP",
|
||||
"ACTIVATED": "Aktywowany",
|
||||
"ACTIVATE": "Aktywuj dostawcę",
|
||||
"DEACTIVATE": "Dezaktywuj dostawcę",
|
||||
"TYPE": "Typ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Konfiguracja SMTP została aktywowana",
|
||||
"ACTIVATE_WARN_TITLE": "Aktywuj konfigurację SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Zamierzasz aktywować konfigurację SMTP. Najpierw dezaktywujemy bieżącego aktywnego dostawcę, a następnie aktywujemy tę konfigurację. Jesteś pewny?",
|
||||
"DEACTIVATE_WARN_TITLE": "Dezaktywuj konfigurację SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Zamierzasz dezaktywować konfigurację SMTP. Jesteś pewny?",
|
||||
"DEACTIVATED": "Konfiguracja SMTP została dezaktywowana",
|
||||
"DELETE_TITLE": "Usuń konfigurację SMTP",
|
||||
"DELETE_DESCRIPTION": "Zamierzasz usunąć konfigurację. Potwierdź tę czynność, wpisując nazwę nadawcy",
|
||||
"DELETED": "Konfiguracja SMTP została usunięta",
|
||||
"SENDER": "Wpisz {{ value }}, aby usunąć tę konfigurację SMTP."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Dodaj dostawcę SMTP",
|
||||
"DESCRIPTION": "Wybierz jednego lub więcej z poniższych dostawców.",
|
||||
"STEPS": {
|
||||
"TITLE": "Dodaj {{ value }} dostawcę SMTP",
|
||||
"CREATE_DESC_TITLE": "Wprowadź krok po kroku ustawienia SMTP {{ value }}",
|
||||
"CURRENT_DESC_TITLE": "To są Twoje ustawienia SMTP",
|
||||
"PROVIDER_SETTINGS": "Ustawienia dostawcy SMTP",
|
||||
"SENDER_SETTINGS": "Ustawienia nadawcy",
|
||||
"TEST_SETTINGS": "Przetestuj ustawienia SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Ustawienia dostawcy SMTP"
|
||||
},
|
||||
"EMPTY": "Brak dostępnego dostawcy SMTP",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Aplikacje",
|
||||
"COMPLIANCE": "Zgodność OIDC",
|
||||
|
@ -1382,6 +1382,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Configurações SMTP",
|
||||
"DESCRIPTION": "Descrição",
|
||||
"SENDERADDRESS": "Endereço de e-mail do remetente",
|
||||
"SENDERNAME": "Nome do remetente",
|
||||
"REPLYTOADDRESS": "Endereço Reply-To",
|
||||
@ -1392,6 +1394,7 @@
|
||||
"PASSWORDSET": "Senha do SMTP definida com sucesso.",
|
||||
"TLS": "Transport Layer Security (TLS)",
|
||||
"SAVED": "Salvo com sucesso!",
|
||||
"NOCHANGES": "Sem alterações!",
|
||||
"REQUIREDWARN": "Para enviar notificações do seu domínio, você precisa inserir seus dados SMTP."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2213,6 +2216,48 @@
|
||||
"1": "Permitido"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "Provedor SMTP",
|
||||
"DESCRIPTION": "Estes são os provedores SMTP para sua instância Zitadel. Ative aquele que deseja usar para enviar notificações aos seus usuários.",
|
||||
"EMPTY": "Nenhum provedor SMTP disponível",
|
||||
"ACTIVATED": "Ativado",
|
||||
"ACTIVATE": "Ativar provedor",
|
||||
"DEACTIVATE": "Desativar provedor",
|
||||
"TYPE": "Tipo",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "A configuração SMTP foi ativada",
|
||||
"ACTIVATE_WARN_TITLE": "Ativar configuração SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Você está prestes a ativar uma configuração SMTP. Primeiro, desativaremos o provedor ativo atual e depois ativaremos esta configuração. Tem certeza?",
|
||||
"DEACTIVATE_WARN_TITLE": "Desativar configuração SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Você está prestes a desativar uma configuração SMTP. Tem certeza?",
|
||||
"DEACTIVATED": "A configuração SMTP foi desativada",
|
||||
"DELETE_TITLE": "Excluir configuração SMTP",
|
||||
"DELETE_DESCRIPTION": "Você está prestes a excluir uma configuração. Confirme esta ação digitando o nome do remetente",
|
||||
"DELETED": "A configuração SMTP foi excluída",
|
||||
"SENDER": "Digite {{ value }} para excluir esta configuração SMTP."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Adicionar provedor SMTP",
|
||||
"DESCRIPTION": "Selecione um ou mais dos seguintes fornecedores.",
|
||||
"STEPS": {
|
||||
"TITLE": "Adicionar {{ value }} provedor SMTP",
|
||||
"CREATE_DESC_TITLE": "Insira suas configurações SMTP de {{ value }} passo a passo",
|
||||
"CURRENT_DESC_TITLE": "Estas são suas configurações de SMTP",
|
||||
"PROVIDER_SETTINGS": "Configurações do provedor SMTP",
|
||||
"SENDER_SETTINGS": "Configurações do remetente",
|
||||
"TEST_SETTINGS": "Testar configurações de SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Configurações do provedor SMTP"
|
||||
},
|
||||
"EMPTY": "Nenhum provedor SMTP disponível",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Aplicações",
|
||||
"COMPLIANCE": "Conformidade OIDC",
|
||||
|
@ -1425,6 +1425,7 @@
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Настройки SMTP",
|
||||
"DESCRIPTION": "Описание",
|
||||
"SENDERADDRESS": "Адрес электронной почты отправителя",
|
||||
"SENDERNAME": "Имя отправителя",
|
||||
"HOSTANDPORT": "Хост и порт",
|
||||
@ -1434,6 +1435,7 @@
|
||||
"PASSWORDSET": "Пароль SMTP был успешно установлен.",
|
||||
"TLS": "Безопасность транспортного уровня (TLS)",
|
||||
"SAVED": "Успешно сохранено!",
|
||||
"NOCHANGES": "Без изменений!",
|
||||
"REQUIREDWARN": "Для того, чтобы отправлять уведомления с вашего домена, вам необходимо ввести свои данные SMTP."
|
||||
},
|
||||
"SMS": {
|
||||
@ -2331,6 +2333,48 @@
|
||||
"1": "Разрешён"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP-провайдер",
|
||||
"DESCRIPTION": "Это поставщики SMTP для вашего экземпляра Zitadel. Активируйте тот, который вы хотите использовать для отправки уведомлений вашим пользователям.",
|
||||
"EMPTY": "SMTP-провайдер не доступен",
|
||||
"ACTIVATED": "Активировано",
|
||||
"ACTIVATE": "Активировать провайдера",
|
||||
"DEACTIVATE": "Деактивировать провайдера",
|
||||
"TYPE": "Тип",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Конфигурация SMTP активирована",
|
||||
"ACTIVATE_WARN_TITLE": "Активируйте конфигурацию SMTP",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "Вы собираетесь активировать конфигурацию SMTP. Сначала мы деактивируем текущего активного провайдера, а затем активируем эту конфигурацию. Вы уверены?",
|
||||
"DEACTIVATE_WARN_TITLE": "Деактивировать конфигурацию SMTP",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "Вы собираетесь деактивировать конфигурацию SMTP. Вы уверены?",
|
||||
"DEACTIVATED": "Конфигурация SMTP деактивирована",
|
||||
"DELETE_TITLE": "Удалить конфигурацию SMTP",
|
||||
"DELETE_DESCRIPTION": "Вы собираетесь удалить конфигурацию. Подтвердите это действие, введя имя отправителя.",
|
||||
"DELETED": "Конфигурация SMTP удалена.",
|
||||
"SENDER": "Введите {{ value }}, чтобы удалить эту конфигурацию SMTP."
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "Добавить SMTP-провайдера",
|
||||
"DESCRIPTION": "Выберите одного или нескольких из следующих поставщиков.",
|
||||
"STEPS": {
|
||||
"TITLE": "Добавить {{ value }} SMTP-провайдера",
|
||||
"CREATE_DESC_TITLE": "Введите {{ value }} настройки SMTP шаг за шагом.",
|
||||
"CURRENT_DESC_TITLE": "Это ваши настройки SMTP",
|
||||
"PROVIDER_SETTINGS": "Настройки SMTP-провайдера",
|
||||
"SENDER_SETTINGS": "Настройки отправителя",
|
||||
"TEST_SETTINGS": "Проверка настроек SMTP"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "Настройки SMTP-провайдера"
|
||||
},
|
||||
"EMPTY": "Нет доступного поставщика SMTP",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "Приложения",
|
||||
"COMPLIANCE": "Соответствие OIDC",
|
||||
|
@ -1380,6 +1380,8 @@
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP 设置",
|
||||
"DESCRIPTION": "描述",
|
||||
"SENDERADDRESS": "发件人地址",
|
||||
"SENDERNAME": "发件人名称",
|
||||
"REPLYTOADDRESS": "Reply-to 地址",
|
||||
@ -1390,6 +1392,7 @@
|
||||
"PASSWORDSET": "SMTP 密码设置成功。",
|
||||
"TLS": "使用安全传输层 (TLS)",
|
||||
"SAVED": "保存成功!",
|
||||
"NOCHANGES": "没有变化!",
|
||||
"REQUIREDWARN": "要从您的域发送通知,您必须输入您的 SMTP 数据。"
|
||||
},
|
||||
"SMS": {
|
||||
@ -2217,6 +2220,48 @@
|
||||
"1": "允许"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"LIST": {
|
||||
"TITLE": "SMTP 提供商",
|
||||
"DESCRIPTION": "这些是您的 Zitadel 实例的 SMTP 提供商。激活您想要用来向用户发送通知的通知。",
|
||||
"EMPTY": "没有可用的 SMTP 提供商",
|
||||
"ACTIVATED": "活性",
|
||||
"ACTIVATE": "激活提供商",
|
||||
"DEACTIVATE": "停用提供商",
|
||||
"TYPE": "类型",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP 配置已激活",
|
||||
"ACTIVATE_WARN_TITLE": "激活 SMTP 配置",
|
||||
"ACTIVATE_WARN_DESCRIPTION": "您即将激活 SMTP 配置。首先,我们将停用当前活动的提供程序,然后激活此配置。你确定吗?",
|
||||
"DEACTIVATE_WARN_TITLE": "停用 SMTP 配置",
|
||||
"DEACTIVATE_WARN_DESCRIPTION": "您即将停用 SMTP 配置。你确定吗?",
|
||||
"DEACTIVATED": "SMTP 配置已停用",
|
||||
"DELETE_TITLE": "删除 SMTP 配置",
|
||||
"DELETE_DESCRIPTION": "您将要删除一个配置。输入发件人姓名确认此操作",
|
||||
"DELETED": "SMTP 配置已被删除",
|
||||
"SENDER": "输入 {{ value }},删除此 SMTP 配置。"
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
"TITLE": "添加 SMTP 提供商",
|
||||
"DESCRIPTION": "选择以下一个或多个提供商。",
|
||||
"STEPS": {
|
||||
"TITLE": "添加 {{ value }} SMTP 提供商",
|
||||
"CREATE_DESC_TITLE": "逐步输入您的 {{ value }} SMTP 设置",
|
||||
"CURRENT_DESC_TITLE": "这些是您的 SMTP 设置",
|
||||
"PROVIDER_SETTINGS": "SMTP 提供商设置",
|
||||
"SENDER_SETTINGS": "发件人设置",
|
||||
"TEST_SETTINGS": "测试 SMTP 设置"
|
||||
}
|
||||
},
|
||||
"DETAIL": {
|
||||
"TITLE": "SMTP 提供商设置"
|
||||
},
|
||||
"EMPTY": "没有可用的 SMTP 提供商",
|
||||
"STEPS": {
|
||||
"SENDGRID": {}
|
||||
}
|
||||
},
|
||||
"APP": {
|
||||
"LIST": "应用",
|
||||
"COMPLIANCE": "OIDC 兼容性",
|
||||
|
10
console/src/assets/images/smtp/aws-ses.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="256px" height="299px" viewBox="0 0 256 299" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path d="M60.556,47.602 L0,144.01 L60.556,240.434 L61.612,239.681 L60.837,47.8 L60.556,47.602" fill="#876929"></path>
|
||||
<path d="M128.187,223.105 L60.556,240.434 L60.556,47.602 L128.187,64.927 L128.187,223.105" fill="#D9A741"></path>
|
||||
<path d="M255.979,71.868 L223.379,77.259 L148.538,0 L111.331,16.292 L116.239,25.445 L89.906,35.971 L89.906,279.399 L128.186,298.552 L128.823,298.053 L128.234,47.818 L209.376,170.786 L255.979,71.868" fill="#876929"></path>
|
||||
<path d="M148.538,0 L248.217,49.837 L208.8,121.357 L148.538,0" fill="#D9A741"></path>
|
||||
<path d="M255.975,71.868 L256,234.596 L128.187,298.552 L128.17,20.683 L208.8,166.974 L255.975,71.868" fill="#D9A741"></path>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 927 B |
3
console/src/assets/images/smtp/brevo.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="1000" height="295" viewBox="0 0 1000 295" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M820.28 182.338C820.28 137.755 848.604 106.4 888.892 106.4C929.18 106.4 957.956 137.737 957.956 182.338C957.956 226.939 929.187 256.5 888.892 256.5C848.598 256.5 820.28 225.588 820.28 182.338ZM778.224 182.338C778.224 248.12 824.262 294.479 888.886 294.479C953.51 294.479 1000 248.12 1000 182.338C1000 116.556 953.962 68.4399 888.886 68.4399C823.81 68.4399 778.224 115.686 778.224 182.338ZM563.521 71.0853L650.292 291.821H691.025L777.791 71.0853H733.966L671.104 241.498H670.214L607.352 71.0853H563.521ZM394.856 174.383C397.508 133.76 424.515 106.4 461.261 106.4C493.128 106.4 517.037 126.712 520.58 157.179H447.089C420.973 157.179 406.801 160.269 396.191 174.402H394.856V174.39V174.383ZM352.805 181.006C352.805 246.788 399.289 294.46 463.468 294.46C506.854 294.46 544.916 272.391 561.295 237.502L525.885 219.835C513.494 242.792 489.585 256.482 463.468 256.482C432.028 256.482 403.704 232.637 403.704 209.679C403.704 197.766 411.673 192.457 423.18 192.457H563.502V180.544C563.502 114.317 521.007 68.4029 459.925 68.4029C398.844 68.4029 352.799 115.649 352.799 180.988M232.399 291.796H272.242V156.285C272.242 127.149 290.382 106.394 315.627 106.394C326.256 106.394 337.311 109.927 342.635 114.774C346.623 104.174 352.818 93.5923 362.111 82.9924C351.482 74.1684 333.342 68.4153 315.627 68.4153C266.937 68.4153 232.399 104.618 232.399 156.267V291.809V291.796ZM39.843 145.698V37.9598H105.358C127.486 37.9598 142.103 50.7611 142.103 70.185C142.103 92.2542 123.072 109.033 84.1191 121.834C57.5571 130.214 45.6116 137.281 41.1785 145.679L39.843 145.692V145.698ZM39.843 253.861V208.835C39.843 188.967 56.6668 169.543 80.1311 162.032C100.943 154.966 118.193 147.899 132.81 140.407C152.286 151.895 164.232 171.744 164.232 192.5C164.232 227.814 130.584 253.861 84.9909 253.861H39.843ZM0 291.821H88.5337C155.829 291.821 206.282 249.884 206.282 194.257C206.282 163.79 190.794 136.43 163.341 118.763C177.513 104.63 184.153 88.2955 184.153 68.4276C184.153 27.3784 154.493 0 109.791 0H0V291.821Z" fill="#0B996E"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
BIN
console/src/assets/images/smtp/google.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
1
console/src/assets/images/smtp/mailchimp.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><rect fill="#ffe01b" height="512" rx="15%" width="512"/><path d="m418 306-6-17s25-38-37-51c0 0 4-47-18-69 48-47 37-118-72-72-56-107-272 144-182 184-9 12-9 72 53 78 42 90 144 96 203 69s93-113 59-122zm-263 40c-51-5-56-75-12-82s55 86 12 82zm-15-95c-14 0-31 19-31 19-68-33 123-252 164-167 0 0-100 48-133 148zm200 85c0-4-21 6-59-7 3-21 48 18 123-33l6 21c28-5 0 90-90 89-73-1-96-76-56-117 8-8-29-24-22-59 3-15 16-37 49-31s40-24 62-13 9 53 12 59 35 7 41 24-41 54-114 44c-17-2-27 20-16 34 22 32 112 11 127-20-38 29-116 40-122 9 22 10 59 4 59 0zm-131-158c22-27 51-43 51-43l-6 15s21-16 44-16l-8 8c26 1 37 11 37 11s-61-18-118 25zm135 39c13-1 9 29 9 29h-8s-14-28-1-29zm-59 33c-9 1-19 6-18 2 4-16 41-12 40 2s-9-6-22-4zm21 12c1 2-7 0-13 1s-12 4-12 2 23-11 25-3zm20 3c3-6 15 0 12 6s-15 0-12-6zm25 2c-6 0-6-13 0-13s6 14 0 14zm-180 53c3 3-6 9-13 4s8-29-10-35-13 17-18 14 7-35 28-22-6 33 6 39 5-2 7 0z" fill="#1e1e1e"/></svg>
|
After Width: | Height: | Size: 969 B |
15
console/src/assets/images/smtp/mailgun.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1000 1000" style="enable-background:new 0 0 1000 1000;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#C12126;}
|
||||
</style>
|
||||
<path class="st0" d="M493,305.7c-88.9,0-161,72.1-161,161c0,88.9,72.1,161,161,161c88.9,0,161-72.1,161-161
|
||||
C654,377.8,582,305.7,493,305.7z M242,466.7c0-138.7,112.4-251,251-251c138.7,0,251.1,112.4,251.1,251c0,9.2-0.5,18.2-1.4,27.1
|
||||
c-1.9,24.5,16.1,43.2,40.4,43.2c41.3,0,45.7-53.2,45.7-70.3c0-185.4-150.3-335.6-335.6-335.6S157.4,281.4,157.4,466.7
|
||||
c0,185.4,150.3,335.6,335.6,335.6c98.4,0,187-42.4,248.4-109.9l69,57.9c-77.9,87.1-191.3,142-317.4,142
|
||||
c-235.1,0-425.7-190.6-425.7-425.7S257.9,41,493,41c235.1,0,425.7,190.6,425.7,425.7c0,94.5-45,171.2-135.4,171.2
|
||||
c-39.8,0-64-18.2-77.2-38.6C661.9,670.5,583,717.8,493,717.8C354.4,717.8,242,605.4,242,466.7z M493,393.1c40.7,0,73.7,33,73.7,73.7
|
||||
c0,40.7-33,73.7-73.7,73.7c-40.7,0-73.7-33-73.7-73.7S452.3,393.1,493,393.1z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
7
console/src/assets/images/smtp/mailjet.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="256px" height="255px" viewBox="0 0 256 255" version="1.1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid">
|
||||
<title>Mailjet</title>
|
||||
<g>
|
||||
<polygon fill="#9585F4" points="1.42108547e-14 97.9914749 93.4083546 140.330776 112.177323 121.670929 64.3819267 99.9556692 212.56948 43.2122762 155.607843 190.745098 134.001705 143.386189 115.123615 162.155158 116.105712 164.337596 157.462916 255.017903 256 -7.10542736e-15"></polygon>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 522 B |
BIN
console/src/assets/images/smtp/postmark.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
console/src/assets/images/smtp/sendgrid.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
1
console/src/assets/mdi/mail.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm320-280L160-640v400h640v-400L480-440Zm0-80 320-200H160l320 200ZM160-640v-80 480-400Z"/></svg>
|
After Width: | Height: | Size: 309 B |
@ -72,6 +72,9 @@
|
||||
@import 'src/app/modules/info-overlay/info-overlay.component.scss';
|
||||
@import 'src/app/modules/create-layout/create-layout.component.scss';
|
||||
@import 'src/app/modules/domains/domain-verification/domain-verification.component.scss';
|
||||
@import 'src/app/modules/smtp-table/smtp-table.component.scss';
|
||||
@import 'src/app/modules/smtp-provider/smtp-provider.scss';
|
||||
@import 'src/app/modules/policies/notification-smtp-provider/notification-smtp-provider.component.scss';
|
||||
@import './styles/codemirror.scss';
|
||||
@import 'src/app/components/copy-row/copy-row.component.scss';
|
||||
@import 'src/app/modules/providers/provider-next/provider-next.component.scss';
|
||||
@ -85,6 +88,8 @@
|
||||
@include header-theme($theme);
|
||||
@include app-type-radio-theme($theme);
|
||||
@include idp-table-theme($theme);
|
||||
@include smtp-table-theme($theme);
|
||||
@include smtp-provider-theme($theme);
|
||||
@include events-theme($theme);
|
||||
@include projects-theme($theme);
|
||||
@include grants-theme($theme);
|
||||
@ -153,4 +158,5 @@
|
||||
@include domain-verification-theme($theme);
|
||||
@include copy-row-theme($theme);
|
||||
@include provider-next-theme($theme);
|
||||
@include smtp-settings-theme($theme);
|
||||
}
|
||||
|
@ -37,12 +37,12 @@ We recommend setting your Branding and SMTP settings initially as it will comfor
|
||||
|
||||
In the Branding settings, you can upload you Logo for the login interface, set your own colors for buttons, background, links, and choose between multiple behavours. You don't need to be an expert as those settings can all be set without any knowledge of CSS.
|
||||
|
||||
| Setting | Description |
|
||||
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Logo | Upload your logo for the light and the dark design. This is used mainly in the login interface. |
|
||||
| Icon | Upload your icon for the light and the dark design. Icons are used for smaller components. For example in console on the top left as the home button. |
|
||||
| Colors | You can set four different colors to design your login page and email. (Background-, Primary-, Warn- and Font Color) |
|
||||
| Font | Upload your custom font |
|
||||
| Setting | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Logo | Upload your logo for the light and the dark design. This is used mainly in the login interface. |
|
||||
| Icon | Upload your icon for the light and the dark design. Icons are used for smaller components. For example in console on the top left as the home button. |
|
||||
| Colors | You can set four different colors to design your login page and email. (Background-, Primary-, Warn- and Font Color) |
|
||||
| Font | Upload your custom font |
|
||||
| Advanced Behavior | **Hide Loginname suffix**: If enabled, your loginname suffix (Domain) will not be shown in the login page. **Disable Watermark**: If you disable the watermark you will not see the "Powered by ZITADEL" in the login page |
|
||||
|
||||
Make sure you click the "Apply configuration" button after you finish your configuration. This will ensure your design is visible for your customers.
|
||||
@ -66,7 +66,14 @@ You can configure on which changes the users will be notified. The text of the m
|
||||
|
||||
### SMTP
|
||||
|
||||
On each instance we configure our default SMTP provider. To make sure, that you only send some E-Mails from domains you own. You need to add a custom domain on your instance.
|
||||
On each instance we configure our default SMTP provider. To make sure, that you only send some E-Mails from domains you own, you need to add a custom domain on your instance.
|
||||
|
||||
You can configure many SMTP providers using templates for popular providers. The templates will add known settings like host, port or default user and will suggest values for user and/or password.
|
||||
|
||||
:::important
|
||||
You have to activate your SMTP provider so Zitadel can use it to send your emails. Only one provider can be active.
|
||||
:::
|
||||
|
||||
Go to the ZITADEL [customer portal](https://zitadel.cloud) to configure a custom domain.
|
||||
|
||||
To configure your custom SMTP please fill the following fields:
|
||||
@ -90,16 +97,16 @@ No default provider is configured to send some SMS to your users. If you like to
|
||||
|
||||
The Login Policy defines how the login process should look like and which authentication options a user has to authenticate.
|
||||
|
||||
| Setting | Description |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Username Password allowed | Possibility to login with username and password. If this is disabled only login with external identity providers will be allowed |
|
||||
| Register allowed | Enable self register possibility in the login ui, this enables username password registration as well as registration with configured external identity providers |
|
||||
| External IDP allowed | Possibility to login with an external identity (e.g Google, Microsoft, Apple, etc), If you like to allow external Identity providers add them to the providers list |
|
||||
| Hide password reset | Disable the self-service option for users to reset their password. |
|
||||
| Domain discovery allowed | If this setting is enabled, the user does't not mandatory have to exist when entering the username. It is required to have verified domains on the organization. Example: ZITADEL is registered as organization with the domain zitadel.com and Entra ID as identity provider. A user enters john@zitadel.com in the login but the user doesn't exist. The domain can be mapped to the organization and therefore the user can be redirected to the Entra ID.
|
||||
| Ignore unknown usernames | This setting can be enabled, if no error message should be shown if the user doesn't exist. Example: A user enters the login name john@zitadel.com, the user doesn't exist, but will be redirected to the password screen. After entering a password, the user will get an error that either username or password are wrong. |
|
||||
| Disable login with email address | By default users can additionally [login with the email attribute](/docs/guides/solution-scenarios/configurations#use-an-email-address-as-username) of their user. Check this option to disable. |
|
||||
| Disable login with phone number | By default users can additionally [login with the phonenumber attribute](/docs/guides/solution-scenarios/configurations#use-a-phone-number-as-username) of their user. Check this option to disable. |
|
||||
| Setting | Description |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Username Password allowed | Possibility to login with username and password. If this is disabled only login with external identity providers will be allowed |
|
||||
| Register allowed | Enable self register possibility in the login ui, this enables username password registration as well as registration with configured external identity providers |
|
||||
| External IDP allowed | Possibility to login with an external identity (e.g Google, Microsoft, Apple, etc), If you like to allow external Identity providers add them to the providers list |
|
||||
| Hide password reset | Disable the self-service option for users to reset their password. |
|
||||
| Domain discovery allowed | If this setting is enabled, the user does't not mandatory have to exist when entering the username. It is required to have verified domains on the organization. Example: ZITADEL is registered as organization with the domain zitadel.com and Entra ID as identity provider. A user enters john@zitadel.com in the login but the user doesn't exist. The domain can be mapped to the organization and therefore the user can be redirected to the Entra ID. |
|
||||
| Ignore unknown usernames | This setting can be enabled, if no error message should be shown if the user doesn't exist. Example: A user enters the login name john@zitadel.com, the user doesn't exist, but will be redirected to the password screen. After entering a password, the user will get an error that either username or password are wrong. |
|
||||
| Disable login with email address | By default users can additionally [login with the email attribute](/docs/guides/solution-scenarios/configurations#use-an-email-address-as-username) of their user. Check this option to disable. |
|
||||
| Disable login with phone number | By default users can additionally [login with the phonenumber attribute](/docs/guides/solution-scenarios/configurations#use-a-phone-number-as-username) of their user. Check this option to disable. |
|
||||
|
||||
<img
|
||||
src="/docs/img/guides/console/loginpolicy.png"
|
||||
@ -115,6 +122,7 @@ The auth request contains a client-id and a redirect uri, that must match the co
|
||||
If there is no [auth request](https://zitadel.com/docs/apis/openidoauth/authrequest), users will be redirected to the Default Redirect URI, which is by default https://<custom_domain>/ui/console/
|
||||
|
||||
Reasons why ZITADEL doesn't have a redirect URI:
|
||||
|
||||
- The login has not been called with an OIDC authorize request
|
||||
- The user landed on the login through an email link, e.g. Password Reset, Initialize User
|
||||
|
||||
|
BIN
docs/static/img/guides/console/smtp.png
vendored
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 48 KiB |
@ -17,27 +17,118 @@ describe('instance notifications', () => {
|
||||
describe('smtp settings', () => {
|
||||
it(`should show SMTP provider settings`, () => {
|
||||
cy.visit(smtpPath);
|
||||
cy.contains('SMTP Settings');
|
||||
cy.contains('SMTP Provider');
|
||||
});
|
||||
it(`should add SMTP provider settings`, () => {
|
||||
it(`should add Mailgun SMTP provider settings`, () => {
|
||||
let rowSelector = `a:contains('Mailgun')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get('[formcontrolname="senderAddress"]').clear().type('sender@example.com');
|
||||
cy.get('[formcontrolname="senderName"]').clear().type('Zitadel');
|
||||
cy.get('[formcontrolname="hostAndPort"]').clear().type('smtp.mailtrap.io:2525');
|
||||
cy.get(rowSelector).click();
|
||||
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org:587');
|
||||
cy.get('[formcontrolname="user"]').clear().type('user@example.com');
|
||||
cy.get('[data-e2e="save-smtp-settings-button"]').click();
|
||||
cy.get('[formcontrolname="password"]').clear().type('password');
|
||||
cy.get('[data-e2e="continue-button"]').click();
|
||||
cy.get('[formcontrolname="senderAddress"]').clear().type('sender1@example.com');
|
||||
cy.get('[formcontrolname="senderName"]').clear().type('Test1');
|
||||
cy.get('[formcontrolname="replyToAddress"]').clear().type('replyto1@example.com');
|
||||
cy.get('[data-e2e="create-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
cy.get('[formcontrolname="senderAddress"]').should('have.value', 'sender@example.com');
|
||||
cy.get('[formcontrolname="senderName"]').should('have.value', 'Zitadel');
|
||||
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailtrap.io:2525');
|
||||
cy.get('[formcontrolname="user"]').should('have.value', 'user@example.com');
|
||||
cy.get('tr').contains('mailgun');
|
||||
cy.get('tr').contains('smtp.mailgun.org:587');
|
||||
cy.get('tr').contains('sender1@example.com');
|
||||
});
|
||||
it(`should add SMTP provider password`, () => {
|
||||
it(`should change Mailgun SMTP provider settings`, () => {
|
||||
let rowSelector = `tr:contains('mailgun')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get('[data-e2e="add-smtp-password-button"]').click();
|
||||
cy.get('[data-e2e="notification-setting-password"]').clear().type('dummy@example.com');
|
||||
cy.get('[data-e2e="save-notification-setting-password-button"]').click();
|
||||
cy.get(rowSelector).click();
|
||||
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org:587');
|
||||
cy.get('[formcontrolname="user"]').should('have.value', 'user@example.com');
|
||||
cy.get('[formcontrolname="user"]').clear().type('change@example.com');
|
||||
cy.get('[data-e2e="continue-button"]').click();
|
||||
cy.get('[formcontrolname="senderAddress"]').should('have.value', 'sender1@example.com');
|
||||
cy.get('[formcontrolname="senderName"]').should('have.value', 'Test1');
|
||||
cy.get('[formcontrolname="replyToAddress"]').should('have.value', 'replyto1@example.com');
|
||||
cy.get('[formcontrolname="senderAddress"]').clear().type('senderchange1@example.com');
|
||||
cy.get('[formcontrolname="senderName"]').clear().type('Change1');
|
||||
cy.get('[data-e2e="create-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
rowSelector = `tr:contains('mailgun')`;
|
||||
cy.get(rowSelector).contains('mailgun');
|
||||
cy.get(rowSelector).contains('smtp.mailgun.org:587');
|
||||
cy.get(rowSelector).contains('senderchange1@example.com');
|
||||
});
|
||||
it(`should activate Mailgun SMTP provider settings`, () => {
|
||||
let rowSelector = `tr:contains('smtp.mailgun.org:587')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get(rowSelector).find('[data-e2e="activate-provider-button"]').click({ force: true });
|
||||
cy.get('[data-e2e="confirm-dialog-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
rowSelector = `tr:contains('smtp.mailgun.org:587')`;
|
||||
cy.get(rowSelector).find('[data-e2e="active-provider"]');
|
||||
cy.get(rowSelector).contains('mailgun');
|
||||
cy.get(rowSelector).contains('smtp.mailgun.org:587');
|
||||
cy.get(rowSelector).contains('senderchange1@example.com');
|
||||
});
|
||||
it(`should add Mailjet SMTP provider settings`, () => {
|
||||
let rowSelector = `a:contains('Mailjet')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get(rowSelector).click();
|
||||
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'in-v3.mailjet.com:587');
|
||||
cy.get('[formcontrolname="user"]').clear().type('user@example.com');
|
||||
cy.get('[formcontrolname="password"]').clear().type('password');
|
||||
cy.get('[data-e2e="continue-button"]').click();
|
||||
cy.get('[formcontrolname="senderAddress"]').clear().type('sender2@example.com');
|
||||
cy.get('[formcontrolname="senderName"]').clear().type('Test2');
|
||||
cy.get('[formcontrolname="replyToAddress"]').clear().type('replyto2@example.com');
|
||||
cy.get('[data-e2e="create-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
rowSelector = `tr:contains('mailjet')`;
|
||||
cy.get(rowSelector).contains('mailjet');
|
||||
cy.get(rowSelector).contains('in-v3.mailjet.com:587');
|
||||
cy.get(rowSelector).contains('sender2@example.com');
|
||||
});
|
||||
it(`should activate Mailjet SMTP provider settings an disable Mailgun`, () => {
|
||||
let rowSelector = `tr:contains('in-v3.mailjet.com:587')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get(rowSelector).find('[data-e2e="activate-provider-button"]').click({ force: true });
|
||||
cy.get('[data-e2e="confirm-dialog-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
cy.get(rowSelector).find('[data-e2e="active-provider"]');
|
||||
cy.get(rowSelector).contains('mailjet');
|
||||
cy.get(rowSelector).contains('in-v3.mailjet.com:587');
|
||||
cy.get(rowSelector).contains('sender2@example.com');
|
||||
rowSelector = `tr:contains('mailgun')`;
|
||||
cy.get(rowSelector).find('[data-e2e="active-provider"]').should('not.exist');
|
||||
});
|
||||
it(`should deactivate Mailjet SMTP provider`, () => {
|
||||
let rowSelector = `tr:contains('mailjet')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get(rowSelector).find('[data-e2e="deactivate-provider-button"]').click({ force: true });
|
||||
cy.get('[data-e2e="confirm-dialog-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
rowSelector = `tr:contains('mailjet')`;
|
||||
cy.get(rowSelector).find('[data-e2e="active-provider"]').should('not.exist');
|
||||
rowSelector = `tr:contains('mailgun')`;
|
||||
cy.get(rowSelector).find('[data-e2e="active-provider"]').should('not.exist');
|
||||
});
|
||||
it(`should delete Mailjet SMTP provider`, () => {
|
||||
let rowSelector = `tr:contains('mailjet')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get(rowSelector).find('[data-e2e="delete-provider-button"]').click({ force: true });
|
||||
cy.get('[data-e2e="confirm-dialog-input"]').focus().type('Test2');
|
||||
cy.get('[data-e2e="confirm-dialog-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
rowSelector = `tr:contains('mailjet')`;
|
||||
cy.get(rowSelector).should('not.exist');
|
||||
});
|
||||
it(`should delete Mailgun SMTP provider`, () => {
|
||||
let rowSelector = `tr:contains('mailgun')`;
|
||||
cy.visit(smtpPath);
|
||||
cy.get(rowSelector).find('[data-e2e="delete-provider-button"]').click({ force: true });
|
||||
cy.get('[data-e2e="confirm-dialog-input"]').focus().type('Change1');
|
||||
cy.get('[data-e2e="confirm-dialog-button"]').click();
|
||||
cy.shouldConfirmSuccess();
|
||||
rowSelector = `tr:contains('mailgun')`;
|
||||
cy.get(rowSelector).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
|
5366
e2e/package-lock.json
generated
1729
e2e/yarn.lock
Normal file
@ -3,7 +3,6 @@ package admin
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
@ -46,68 +45,6 @@ func (s *Server) UpdateSecretGenerator(ctx context.Context, req *admin_pb.Update
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigRequest) (*admin_pb.GetSMTPConfigResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigByAggregateID(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetSMTPConfigResponse{
|
||||
SmtpConfig: SMTPConfigToPb(smtp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddSMTPConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) (*admin_pb.AddSMTPConfigResponse, error) {
|
||||
details, err := s.command.AddSMTPConfig(ctx, AddSMTPToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.AddSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfig(ctx, UpdateSMTPToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveSMTPConfig(ctx context.Context, _ *admin_pb.RemoveSMTPConfigRequest) (*admin_pb.RemoveSMTPConfigResponse, error) {
|
||||
details, err := s.command.RemoveSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.RemoveSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfigPassword(ctx, req.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigPasswordResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetSecurityPolicy(ctx context.Context, req *admin_pb.GetSecurityPolicyRequest) (*admin_pb.GetSecurityPolicyResponse, error) {
|
||||
policy, err := s.query.SecurityPolicy(ctx)
|
||||
if err != nil {
|
||||
|
@ -133,6 +133,7 @@ func SecretGeneratorTypeToDomain(generatorType settings_pb.SecretGeneratorType)
|
||||
|
||||
func AddSMTPToConfig(req *admin_pb.AddSMTPConfigRequest) *smtp.Config {
|
||||
return &smtp.Config{
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
@ -147,26 +148,30 @@ func AddSMTPToConfig(req *admin_pb.AddSMTPConfigRequest) *smtp.Config {
|
||||
|
||||
func UpdateSMTPToConfig(req *admin_pb.UpdateSMTPConfigRequest) *smtp.Config {
|
||||
return &smtp.Config{
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigToPb(smtp *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
mapped := &settings_pb.SMTPConfig{
|
||||
Description: smtp.Description,
|
||||
Tls: smtp.TLS,
|
||||
SenderAddress: smtp.SenderAddress,
|
||||
SenderName: smtp.SenderName,
|
||||
ReplyToAddress: smtp.ReplyToAddress,
|
||||
Host: smtp.Host,
|
||||
User: smtp.User,
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.AggregateID),
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.ResourceOwner),
|
||||
Id: smtp.ID,
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
|
130
internal/api/grpc/admin/smtp.go
Normal file
@ -0,0 +1,130 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigRequest) (*admin_pb.GetSMTPConfigResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetSMTPConfigResponse{
|
||||
SmtpConfig: SMTPConfigToPb(smtp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetSMTPConfigById(ctx context.Context, req *admin_pb.GetSMTPConfigByIdRequest) (*admin_pb.GetSMTPConfigByIdResponse, error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
resourceOwner := instanceID // Will be replaced when orgs have smtp configs
|
||||
|
||||
smtp, err := s.query.SMTPConfigByID(ctx, instanceID, resourceOwner, req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetSMTPConfigByIdResponse{
|
||||
SmtpConfig: SMTPConfigToPb(smtp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddSMTPConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) (*admin_pb.AddSMTPConfigResponse, error) {
|
||||
id, details, err := s.command.AddSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), AddSMTPToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.AddSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
Id: id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, UpdateSMTPToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveSMTPConfig(ctx context.Context, req *admin_pb.RemoveSMTPConfigRequest) (*admin_pb.RemoveSMTPConfigResponse, error) {
|
||||
details, err := s.command.RemoveSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.RemoveSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfigPassword(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigPasswordResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ListSMTPConfigs(ctx context.Context, req *admin_pb.ListSMTPConfigsRequest) (*admin_pb.ListSMTPConfigsResponse, error) {
|
||||
queries, err := listSMTPConfigsToModel(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := s.query.SearchSMTPConfigs(ctx, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.ListSMTPConfigsResponse{
|
||||
Details: object.ToListDetails(result.Count, result.Sequence, result.LastRun),
|
||||
Result: SMTPConfigsToPb(result.Configs),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ActivateSMTPConfig(ctx context.Context, req *admin_pb.ActivateSMTPConfigRequest) (*admin_pb.ActivateSMTPConfigResponse, error) {
|
||||
// Get the ID of current SMTP active provider if any
|
||||
currentActiveProviderID := ""
|
||||
smtp, err := s.query.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err == nil {
|
||||
currentActiveProviderID = smtp.ID
|
||||
}
|
||||
|
||||
result, err := s.command.ActivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, currentActiveProviderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
return &admin_pb.ActivateSMTPConfigResponse{
|
||||
Details: object.DomainToAddDetailsPb(result),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) DeactivateSMTPConfig(ctx context.Context, req *admin_pb.DeactivateSMTPConfigRequest) (*admin_pb.DeactivateSMTPConfigResponse, error) {
|
||||
result, err := s.command.DeactivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
return &admin_pb.DeactivateSMTPConfigResponse{
|
||||
Details: object.DomainToAddDetailsPb(result),
|
||||
}, nil
|
||||
}
|
41
internal/api/grpc/admin/smtp_converters.go
Normal file
@ -0,0 +1,41 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
settings_pb "github.com/zitadel/zitadel/pkg/grpc/settings"
|
||||
)
|
||||
|
||||
func listSMTPConfigsToModel(req *admin_pb.ListSMTPConfigsRequest) (*query.SMTPConfigsSearchQueries, error) {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
return &query.SMTPConfigsSearchQueries{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SMTPConfigToProviderPb(config *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
return &settings_pb.SMTPConfig{
|
||||
Details: object.ToViewDetailsPb(config.Sequence, config.CreationDate, config.ChangeDate, config.ResourceOwner),
|
||||
Id: config.ID,
|
||||
Description: config.Description,
|
||||
Tls: config.TLS,
|
||||
Host: config.Host,
|
||||
User: config.User,
|
||||
State: settings_pb.SMTPConfigState(config.State),
|
||||
SenderAddress: config.SenderAddress,
|
||||
SenderName: config.SenderName,
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigsToPb(configs []*query.SMTPConfig) []*settings_pb.SMTPConfig {
|
||||
c := make([]*settings_pb.SMTPConfig, len(configs))
|
||||
for i, config := range configs {
|
||||
c[i] = SMTPConfigToProviderPb(config)
|
||||
}
|
||||
return c
|
||||
}
|
@ -391,6 +391,7 @@ func setupSMTPSettings(commands *Commands, validations *[]preparation.Validation
|
||||
*validations = append(*validations,
|
||||
commands.prepareAddSMTPConfig(
|
||||
instanceAgg,
|
||||
smtpConfig.Description,
|
||||
smtpConfig.From,
|
||||
smtpConfig.FromName,
|
||||
smtpConfig.ReplyToAddress,
|
||||
|
@ -82,5 +82,11 @@ func (wm *InstanceWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
}
|
||||
|
||||
func InstanceAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return eventstore.AggregateFromWriteModel(wm, instance.AggregateType, instance.AggregateVersion)
|
||||
return &eventstore.Aggregate{
|
||||
ID: wm.AggregateID,
|
||||
Type: instance.AggregateType,
|
||||
ResourceOwner: wm.ResourceOwner,
|
||||
InstanceID: wm.InstanceID,
|
||||
Version: instance.AggregateVersion,
|
||||
}
|
||||
}
|
||||
|
@ -9,16 +9,18 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
type InstanceSMTPConfigWriteModel struct {
|
||||
type IAMSMTPConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
ReplyToAddress string
|
||||
ID string
|
||||
Description string
|
||||
TLS bool
|
||||
Host string
|
||||
User string
|
||||
Password *crypto.CryptoValue
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
ReplyToAddress string
|
||||
State domain.SMTPConfigState
|
||||
|
||||
domain string
|
||||
@ -26,17 +28,19 @@ type InstanceSMTPConfigWriteModel struct {
|
||||
smtpSenderAddressMatchesInstanceDomain bool
|
||||
}
|
||||
|
||||
func NewInstanceSMTPConfigWriteModel(instanceID, domain string) *InstanceSMTPConfigWriteModel {
|
||||
return &InstanceSMTPConfigWriteModel{
|
||||
func NewIAMSMTPConfigWriteModel(instanceID, id, domain string) *IAMSMTPConfigWriteModel {
|
||||
return &IAMSMTPConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: instanceID,
|
||||
ResourceOwner: instanceID,
|
||||
InstanceID: instanceID,
|
||||
},
|
||||
ID: id,
|
||||
domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *InstanceSMTPConfigWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
func (wm *IAMSMTPConfigWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *instance.DomainAddedEvent:
|
||||
@ -56,46 +60,34 @@ func (wm *InstanceSMTPConfigWriteModel) AppendEvents(events ...eventstore.Event)
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *InstanceSMTPConfigWriteModel) Reduce() error {
|
||||
func (wm *IAMSMTPConfigWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *instance.SMTPConfigAddedEvent:
|
||||
wm.TLS = e.TLS
|
||||
wm.SenderAddress = e.SenderAddress
|
||||
wm.SenderName = e.SenderName
|
||||
wm.ReplyToAddress = e.ReplyToAddress
|
||||
wm.Host = e.Host
|
||||
wm.User = e.User
|
||||
wm.Password = e.Password
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.reduceSMTPConfigAddedEvent(e)
|
||||
case *instance.SMTPConfigChangedEvent:
|
||||
if e.TLS != nil {
|
||||
wm.TLS = *e.TLS
|
||||
}
|
||||
if e.FromAddress != nil {
|
||||
wm.SenderAddress = *e.FromAddress
|
||||
}
|
||||
if e.FromName != nil {
|
||||
wm.SenderName = *e.FromName
|
||||
}
|
||||
if e.ReplyToAddress != nil {
|
||||
wm.ReplyToAddress = *e.ReplyToAddress
|
||||
}
|
||||
if e.Host != nil {
|
||||
wm.Host = *e.Host
|
||||
}
|
||||
if e.User != nil {
|
||||
wm.User = *e.User
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.reduceSMTPConfigChangedEvent(e)
|
||||
case *instance.SMTPConfigRemovedEvent:
|
||||
wm.State = domain.SMTPConfigStateRemoved
|
||||
wm.TLS = false
|
||||
wm.SenderName = ""
|
||||
wm.SenderAddress = ""
|
||||
wm.ReplyToAddress = ""
|
||||
wm.Host = ""
|
||||
wm.User = ""
|
||||
wm.Password = nil
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.reduceSMTPConfigRemovedEvent(e)
|
||||
case *instance.SMTPConfigActivatedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
case *instance.SMTPConfigDeactivatedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.SMTPConfigStateInactive
|
||||
case *instance.DomainAddedEvent:
|
||||
wm.domainState = domain.InstanceDomainStateActive
|
||||
case *instance.DomainRemovedEvent:
|
||||
@ -111,7 +103,13 @@ func (wm *InstanceSMTPConfigWriteModel) Reduce() error {
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *InstanceSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
func (wm *IAMSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
// If ID equals ResourceOwner we're dealing with the old and unique smtp settings
|
||||
// Let's set the empty ID for the query
|
||||
if wm.ID == wm.ResourceOwner {
|
||||
wm.ID = ""
|
||||
}
|
||||
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
@ -122,6 +120,9 @@ func (wm *InstanceSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
instance.SMTPConfigRemovedEventType,
|
||||
instance.SMTPConfigChangedEventType,
|
||||
instance.SMTPConfigPasswordChangedEventType,
|
||||
instance.SMTPConfigActivatedEventType,
|
||||
instance.SMTPConfigDeactivatedEventType,
|
||||
instance.SMTPConfigRemovedEventType,
|
||||
instance.InstanceDomainAddedEventType,
|
||||
instance.InstanceDomainRemovedEventType,
|
||||
instance.DomainPolicyAddedEventType,
|
||||
@ -129,10 +130,16 @@ func (wm *InstanceSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *InstanceSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregate *eventstore.Aggregate, tls bool, fromAddress, fromName, replyToAddress, smtpHost, smtpUser string) (*instance.SMTPConfigChangedEvent, bool, error) {
|
||||
func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregate *eventstore.Aggregate, id, description string, tls bool, fromAddress, fromName, replyToAddress, smtpHost, smtpUser string, smtpPassword *crypto.CryptoValue) (*instance.SMTPConfigChangedEvent, bool, error) {
|
||||
changes := make([]instance.SMTPConfigChanges, 0)
|
||||
var err error
|
||||
|
||||
if wm.ID != id {
|
||||
changes = append(changes, instance.ChangeSMTPConfigID(id))
|
||||
}
|
||||
if wm.Description != description {
|
||||
changes = append(changes, instance.ChangeSMTPConfigDescription(description))
|
||||
}
|
||||
if wm.TLS != tls {
|
||||
changes = append(changes, instance.ChangeSMTPConfigTLS(tls))
|
||||
}
|
||||
@ -151,13 +158,87 @@ func (wm *InstanceSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, agg
|
||||
if wm.User != smtpUser {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPUser(smtpUser))
|
||||
}
|
||||
|
||||
if smtpPassword != nil {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPPassword(smtpPassword))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := instance.NewSMTPConfigChangeEvent(ctx, aggregate, changes)
|
||||
changeEvent, err := instance.NewSMTPConfigChangeEvent(ctx, aggregate, id, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigAddedEvent(e *instance.SMTPConfigAddedEvent) {
|
||||
wm.Description = e.Description
|
||||
wm.TLS = e.TLS
|
||||
wm.Host = e.Host
|
||||
wm.User = e.User
|
||||
wm.Password = e.Password
|
||||
wm.SenderAddress = e.SenderAddress
|
||||
wm.SenderName = e.SenderName
|
||||
wm.ReplyToAddress = e.ReplyToAddress
|
||||
wm.State = domain.SMTPConfigStateInactive
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
if e.ID == "" {
|
||||
wm.Description = "generic"
|
||||
wm.ID = e.Aggregate().ResourceOwner
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigChangedEvent(e *instance.SMTPConfigChangedEvent) {
|
||||
if e.Description != nil {
|
||||
wm.Description = *e.Description
|
||||
}
|
||||
if e.TLS != nil {
|
||||
wm.TLS = *e.TLS
|
||||
}
|
||||
if e.Host != nil {
|
||||
wm.Host = *e.Host
|
||||
}
|
||||
if e.User != nil {
|
||||
wm.User = *e.User
|
||||
}
|
||||
if e.Password != nil {
|
||||
wm.Password = e.Password
|
||||
}
|
||||
if e.FromAddress != nil {
|
||||
wm.SenderAddress = *e.FromAddress
|
||||
}
|
||||
if e.FromName != nil {
|
||||
wm.SenderName = *e.FromName
|
||||
}
|
||||
if e.ReplyToAddress != nil {
|
||||
wm.ReplyToAddress = *e.ReplyToAddress
|
||||
}
|
||||
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
if e.ID == "" {
|
||||
wm.Description = "generic"
|
||||
wm.ID = e.Aggregate().ResourceOwner
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigRemovedEvent(e *instance.SMTPConfigRemovedEvent) {
|
||||
wm.Description = ""
|
||||
wm.TLS = false
|
||||
wm.SenderName = ""
|
||||
wm.SenderAddress = ""
|
||||
wm.ReplyToAddress = ""
|
||||
wm.Host = ""
|
||||
wm.User = ""
|
||||
wm.Password = nil
|
||||
wm.State = domain.SMTPConfigStateRemoved
|
||||
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
if e.ID == "" {
|
||||
wm.ID = e.Aggregate().ResourceOwner
|
||||
}
|
||||
}
|
||||
|
@ -15,51 +15,153 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func (c *Commands) AddSMTPConfig(ctx context.Context, config *smtp.Config) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.prepareAddSMTPConfig(instanceAgg, config.From, config.FromName, config.ReplyToAddress, config.SMTP.Host, config.SMTP.User, []byte(config.SMTP.Password), config.Tls)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
func (c *Commands) AddSMTPConfig(ctx context.Context, instanceID string, config *smtp.Config) (string, *domain.ObjectDetails, error) {
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", nil, err
|
||||
}
|
||||
events, err := c.eventstore.Push(ctx, cmds...)
|
||||
|
||||
from := strings.TrimSpace(config.From)
|
||||
if from == "" {
|
||||
return "", nil, zerrors.ThrowInvalidArgument(nil, "INST-ASv2d", "Errors.Invalid.Argument")
|
||||
}
|
||||
fromSplitted := strings.Split(from, "@")
|
||||
senderDomain := fromSplitted[len(fromSplitted)-1]
|
||||
description := strings.TrimSpace(config.Description)
|
||||
replyTo := strings.TrimSpace(config.ReplyToAddress)
|
||||
hostAndPort := strings.TrimSpace(config.SMTP.Host)
|
||||
|
||||
if _, _, err := net.SplitHostPort(hostAndPort); err != nil {
|
||||
return "", nil, zerrors.ThrowInvalidArgument(nil, "INST-9JdRe", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
if config.SMTP.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.SMTP.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, senderDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", nil, err
|
||||
}
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: events[len(events)-1].Sequence(),
|
||||
EventDate: events[len(events)-1].CreatedAt(),
|
||||
ResourceOwner: events[len(events)-1].Aggregate().InstanceID,
|
||||
}, nil
|
||||
|
||||
err = checkSenderAddress(smtpConfigWriteModel)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id,
|
||||
description,
|
||||
config.Tls,
|
||||
config.From,
|
||||
config.FromName,
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.SMTP.User,
|
||||
smtpPassword,
|
||||
))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
return id, writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *smtp.Config) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.prepareChangeSMTPConfig(instanceAgg, config.From, config.FromName, config.ReplyToAddress, config.SMTP.Host, config.SMTP.User, config.Tls)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
func (c *Commands) ChangeSMTPConfig(ctx context.Context, instanceID string, id string, config *smtp.Config) (*domain.ObjectDetails, error) {
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-x8vo9", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
from := strings.TrimSpace(config.From)
|
||||
if from == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-HSv2d", "Errors.Invalid.Argument")
|
||||
}
|
||||
fromSplitted := strings.Split(from, "@")
|
||||
senderDomain := fromSplitted[len(fromSplitted)-1]
|
||||
description := strings.TrimSpace(config.Description)
|
||||
replyTo := strings.TrimSpace(config.ReplyToAddress)
|
||||
hostAndPort := strings.TrimSpace(config.SMTP.Host)
|
||||
if _, _, err := net.SplitHostPort(hostAndPort); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-Kv875", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
var err error
|
||||
if config.SMTP.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.SMTP.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, senderDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := c.eventstore.Push(ctx, cmds...)
|
||||
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-7j8gv", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
err = checkSenderAddress(smtpConfigWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: events[len(events)-1].Sequence(),
|
||||
EventDate: events[len(events)-1].CreatedAt(),
|
||||
ResourceOwner: events[len(events)-1].Aggregate().InstanceID,
|
||||
}, nil
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
|
||||
changedEvent, hasChanged, err := smtpConfigWriteModel.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id,
|
||||
description,
|
||||
config.Tls,
|
||||
from,
|
||||
config.FromName,
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.SMTP.User,
|
||||
smtpPassword,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-lh3op", "Errors.NoChangesFound")
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, instanceID, id string, password string) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
smtpConfigWriteModel, err := getSMTPConfigWriteModel(ctx, c.eventstore.Filter, "")
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if smtpConfigWriteModel.State != domain.SMTPConfigStateActive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
if password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(password), c.smtpEncryption)
|
||||
@ -67,39 +169,144 @@ func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
events, err := c.eventstore.Push(ctx, instance.NewSMTPConfigPasswordChangedEvent(
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigPasswordChangedEvent(
|
||||
ctx,
|
||||
&instanceAgg.Aggregate,
|
||||
id,
|
||||
smtpPassword))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: events[len(events)-1].Sequence(),
|
||||
EventDate: events[len(events)-1].CreatedAt(),
|
||||
ResourceOwner: events[len(events)-1].Aggregate().InstanceID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveSMTPConfig(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.prepareRemoveSMTPConfig(instanceAgg)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := c.eventstore.Push(ctx, cmds...)
|
||||
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ActivateSMTPConfig(ctx context.Context, instanceID, id, activatedId string) (*domain.ObjectDetails, error) {
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-nm56k", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
if len(activatedId) > 0 {
|
||||
_, err := c.DeactivateSMTPConfig(ctx, instanceID, activatedId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: events[len(events)-1].Sequence(),
|
||||
EventDate: events[len(events)-1].CreatedAt(),
|
||||
ResourceOwner: events[len(events)-1].Aggregate().InstanceID,
|
||||
}, nil
|
||||
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-kg8yr", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateActive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-ed3lr", "Errors.SMTPConfig.AlreadyActive")
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigActivatedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, replyTo, hostAndPort, user string, password []byte, tls bool) preparation.Validation {
|
||||
func (c *Commands) DeactivateSMTPConfig(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-98ikl", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-k39PJ", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateInactive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-km8g3", "Errors.SMTPConfig.AlreadyDeactivated")
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigDeactivatedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveSMTPConfig(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-7f5cv", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-kg8rt", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigRemovedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func checkSenderAddress(writeModel *IAMSMTPConfigWriteModel) error {
|
||||
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
|
||||
return nil
|
||||
}
|
||||
if !writeModel.domainState.Exists() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "INST-83nl8", "Errors.SMTPConfig.SenderAdressNotCustomDomain")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) getSMTPConfig(ctx context.Context, instanceID, id, domain string) (writeModel *IAMSMTPConfigWriteModel, err error) {
|
||||
writeModel = NewIAMSMTPConfigWriteModel(instanceID, id, domain)
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
||||
|
||||
// TODO: SetUpInstance still uses this and would be removed as soon as deprecated PrepareCommands is removed
|
||||
func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, description, from, name, replyTo, hostAndPort, user string, password []byte, tls bool) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if from = strings.TrimSpace(from); from == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-mruNY", "Errors.Invalid.Argument")
|
||||
@ -112,9 +319,14 @@ func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, reply
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-9JdRe", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(nil, "INST-9JdRe", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
fromSplitted := strings.Split(from, "@")
|
||||
senderDomain := fromSplitted[len(fromSplitted)-1]
|
||||
writeModel, err := getSMTPConfigWriteModel(ctx, filter, senderDomain)
|
||||
writeModel, err := getSMTPConfigWriteModel(ctx, filter, id, senderDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -136,6 +348,8 @@ func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, reply
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
description,
|
||||
tls,
|
||||
from,
|
||||
name,
|
||||
@ -149,83 +363,8 @@ func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, reply
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareChangeSMTPConfig(a *instance.Aggregate, from, name, replyTo, hostAndPort, user string, tls bool) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if from = strings.TrimSpace(from); from == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-ASv2d", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
replyTo = strings.TrimSpace(replyTo)
|
||||
hostAndPort = strings.TrimSpace(hostAndPort)
|
||||
if _, _, err := net.SplitHostPort(hostAndPort); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-Kv875", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
fromSplitted := strings.Split(from, "@")
|
||||
senderDomain := fromSplitted[len(fromSplitted)-1]
|
||||
writeModel, err := getSMTPConfigWriteModel(ctx, filter, senderDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if writeModel.State != domain.SMTPConfigStateActive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "INST-Svq1a", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
err = checkSenderAddress(writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changedEvent, hasChanged, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
tls,
|
||||
from,
|
||||
name,
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
user,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-m0o3f", "Errors.NoChangesFound")
|
||||
}
|
||||
return []eventstore.Command{
|
||||
changedEvent,
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareRemoveSMTPConfig(a *instance.Aggregate) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel, err := getSMTPConfigWriteModel(ctx, filter, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if writeModel.State != domain.SMTPConfigStateActive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "INST-Sfefg", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
return []eventstore.Command{
|
||||
instance.NewSMTPConfigRemovedEvent(ctx, &a.Aggregate),
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func checkSenderAddress(writeModel *InstanceSMTPConfigWriteModel) error {
|
||||
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
|
||||
return nil
|
||||
}
|
||||
if !writeModel.domainState.Exists() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "INST-83nl8", "Errors.SMTPConfig.SenderAdressNotCustomDomain")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSMTPConfigWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer, domain string) (_ *InstanceSMTPConfigWriteModel, err error) {
|
||||
writeModel := NewInstanceSMTPConfigWriteModel(authz.GetInstance(ctx).InstanceID(), domain)
|
||||
func getSMTPConfigWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer, id, domain string) (_ *IAMSMTPConfigWriteModel, err error) {
|
||||
writeModel := NewIAMSMTPConfigWriteModel(authz.GetInstance(ctx).InstanceID(), id, domain)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
id_mock "github.com/zitadel/zitadel/internal/id/mock"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
@ -18,12 +20,14 @@ import (
|
||||
|
||||
func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
alg crypto.EncryptionAlgorithm
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
smtp *smtp.Config
|
||||
ctx context.Context
|
||||
instanceID string
|
||||
smtp *smtp.Config
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -51,13 +55,13 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
From: "from@domain.ch",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
@ -69,58 +73,6 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "smtp config, error already exists",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"domain.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true, true, false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
ReplyToAddress: "",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add smtp config, ok",
|
||||
fields: fields{
|
||||
@ -145,6 +97,8 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"configid",
|
||||
"test",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -160,14 +114,16 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
@ -205,6 +161,8 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"configid",
|
||||
"test",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -220,11 +178,13 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
@ -245,14 +205,17 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
{
|
||||
name: "smtp config, port is missing",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
@ -267,14 +230,17 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
{
|
||||
name: "smtp config, host is empty",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: " ",
|
||||
User: "user",
|
||||
@ -310,6 +276,8 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"configid",
|
||||
"test",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -325,14 +293,16 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "[2001:db8::1]:2525",
|
||||
User: "user",
|
||||
@ -351,9 +321,10 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
smtpEncryption: tt.fields.alg,
|
||||
}
|
||||
got, err := r.AddSMTPConfig(tt.args.ctx, tt.args.smtp)
|
||||
_, got, err := r.AddSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.smtp)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -372,8 +343,10 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
smtp *smtp.Config
|
||||
ctx context.Context
|
||||
instanceID string
|
||||
id string
|
||||
smtp *smtp.Config
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -385,6 +358,21 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "id empty, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{},
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty config, invalid argument error",
|
||||
fields: fields{
|
||||
@ -395,6 +383,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{},
|
||||
id: "configID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
@ -411,14 +400,17 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
},
|
||||
},
|
||||
instanceID: "INSTANCE",
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsNotFound,
|
||||
@ -447,6 +439,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -460,11 +454,14 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
instanceID: "INSTANCE",
|
||||
id: "ID",
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@wrongdomain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@wrongdomain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
@ -498,6 +495,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -513,14 +512,17 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
},
|
||||
},
|
||||
instanceID: "INSTANCE",
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsPreconditionFailed,
|
||||
@ -549,6 +551,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -562,6 +566,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
expectPush(
|
||||
newSMTPConfigChangedEvent(
|
||||
context.Background(),
|
||||
"ID",
|
||||
"test",
|
||||
false,
|
||||
"from2@domain.ch",
|
||||
"name2",
|
||||
@ -575,6 +581,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Description: "test",
|
||||
Tls: false,
|
||||
From: "from2@domain.ch",
|
||||
FromName: "name2",
|
||||
@ -584,6 +591,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
User: "user2",
|
||||
},
|
||||
},
|
||||
id: "ID",
|
||||
instanceID: "INSTANCE",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -599,15 +608,18 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
instanceID: "INSTANCE",
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
@ -621,15 +633,18 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "from@domain.ch",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: " ",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
instanceID: "INSTANCE",
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
@ -658,6 +673,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"",
|
||||
true,
|
||||
"from@domain.ch",
|
||||
"name",
|
||||
@ -671,6 +688,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
expectPush(
|
||||
newSMTPConfigChangedEvent(
|
||||
context.Background(),
|
||||
"ID",
|
||||
"test",
|
||||
false,
|
||||
"from2@domain.ch",
|
||||
"name2",
|
||||
@ -684,6 +703,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
smtp: &smtp.Config{
|
||||
Description: "test",
|
||||
Tls: false,
|
||||
From: "from2@domain.ch",
|
||||
FromName: "name2",
|
||||
@ -693,6 +713,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
User: "user2",
|
||||
},
|
||||
},
|
||||
instanceID: "INSTANCE",
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -706,7 +728,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeSMTPConfig(tt.args.ctx, tt.args.smtp)
|
||||
got, err := r.ChangeSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.smtp)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -726,8 +748,10 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
password string
|
||||
ctx context.Context
|
||||
instanceID string
|
||||
id string
|
||||
password string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -750,6 +774,7 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
password: "",
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsNotFound,
|
||||
@ -765,6 +790,8 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
@ -774,11 +801,19 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigActivatedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewSMTPConfigPasswordChangedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -791,8 +826,10 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
password: "password",
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
password: "password",
|
||||
id: "ID",
|
||||
instanceID: "INSTANCE",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -807,7 +844,246 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
eventstore: tt.fields.eventstore,
|
||||
smtpEncryption: tt.fields.alg,
|
||||
}
|
||||
got, err := r.ChangeSMTPConfigPassword(tt.args.ctx, tt.args.password)
|
||||
got, err := r.ChangeSMTPConfigPassword(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.password)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ActivateSMTPConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
instanceID string
|
||||
id string
|
||||
activatedId string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "id empty, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "smtp not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
instanceID: "INSTANCE",
|
||||
id: "id",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "activate smtp config, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewSMTPConfigActivatedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
id: "ID",
|
||||
instanceID: "INSTANCE",
|
||||
activatedId: "",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
smtpEncryption: tt.fields.alg,
|
||||
}
|
||||
got, err := r.ActivateSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.activatedId)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_DeactivateSMTPConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
instanceID string
|
||||
id string
|
||||
activatedId string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "id empty, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "smtp not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
instanceID: "INSTANCE",
|
||||
id: "id",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deactivate smtp config, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigActivatedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewSMTPConfigDeactivatedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
id: "ID",
|
||||
instanceID: "INSTANCE",
|
||||
activatedId: "",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
smtpEncryption: tt.fields.alg,
|
||||
}
|
||||
got, err := r.DeactivateSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.id)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -827,7 +1103,9 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
ctx context.Context
|
||||
instanceID string
|
||||
id string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -849,6 +1127,7 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
id: "ID",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsNotFound,
|
||||
@ -864,6 +1143,8 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
@ -878,12 +1159,15 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
instance.NewSMTPConfigRemovedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
id: "ID",
|
||||
instanceID: "INSTANCE",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -898,7 +1182,7 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
eventstore: tt.fields.eventstore,
|
||||
smtpEncryption: tt.fields.alg,
|
||||
}
|
||||
got, err := r.RemoveSMTPConfig(tt.args.ctx)
|
||||
got, err := r.RemoveSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.id)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -912,8 +1196,9 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newSMTPConfigChangedEvent(ctx context.Context, tls bool, fromAddress, fromName, replyTo, host, user string) *instance.SMTPConfigChangedEvent {
|
||||
func newSMTPConfigChangedEvent(ctx context.Context, id, description string, tls bool, fromAddress, fromName, replyTo, host, user string) *instance.SMTPConfigChangedEvent {
|
||||
changes := []instance.SMTPConfigChanges{
|
||||
instance.ChangeSMTPConfigDescription(description),
|
||||
instance.ChangeSMTPConfigTLS(tls),
|
||||
instance.ChangeSMTPConfigFromAddress(fromAddress),
|
||||
instance.ChangeSMTPConfigFromName(fromName),
|
||||
@ -923,6 +1208,7 @@ func newSMTPConfigChangedEvent(ctx context.Context, tls bool, fromAddress, fromN
|
||||
}
|
||||
event, _ := instance.NewSMTPConfigChangeEvent(ctx,
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
id,
|
||||
changes,
|
||||
)
|
||||
return event
|
||||
|
@ -6,4 +6,9 @@ const (
|
||||
SMTPConfigStateUnspecified SMTPConfigState = iota
|
||||
SMTPConfigStateActive
|
||||
SMTPConfigStateRemoved
|
||||
SMTPConfigStateInactive
|
||||
)
|
||||
|
||||
func (s SMTPConfigState) Exists() bool {
|
||||
return s != SMTPConfigStateUnspecified && s != SMTPConfigStateRemoved
|
||||
}
|
||||
|
@ -91,9 +91,9 @@ func (smtpConfig SMTP) connectToSMTP(tlsRequired bool) (client *smtp.Client, err
|
||||
}
|
||||
|
||||
if !tlsRequired {
|
||||
client, err = smtpConfig.getSMPTClient()
|
||||
client, err = smtpConfig.getSMTPClient()
|
||||
} else {
|
||||
client, err = smtpConfig.getSMPTClientWithTls(host)
|
||||
client, err = smtpConfig.getSMTPClientWithTls(host)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -106,7 +106,7 @@ func (smtpConfig SMTP) connectToSMTP(tlsRequired bool) (client *smtp.Client, err
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (smtpConfig SMTP) getSMPTClient() (*smtp.Client, error) {
|
||||
func (smtpConfig SMTP) getSMTPClient() (*smtp.Client, error) {
|
||||
client, err := smtp.Dial(smtpConfig.Host)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "EMAIL-skwos", "could not make smtp dial")
|
||||
@ -114,12 +114,12 @@ func (smtpConfig SMTP) getSMPTClient() (*smtp.Client, error) {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (smtpConfig SMTP) getSMPTClientWithTls(host string) (*smtp.Client, error) {
|
||||
func (smtpConfig SMTP) getSMTPClientWithTls(host string) (*smtp.Client, error) {
|
||||
conn, err := tls.Dial("tcp", smtpConfig.Host, &tls.Config{})
|
||||
|
||||
if errors.As(err, &tls.RecordHeaderError{}) {
|
||||
logging.Log("MAIN-xKIzT").OnError(err).Warn("could not connect using normal tls. trying starttls instead...")
|
||||
return smtpConfig.getSMPTClientWithStartTls(host)
|
||||
return smtpConfig.getSMTPClientWithStartTls(host)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -133,8 +133,8 @@ func (smtpConfig SMTP) getSMPTClientWithTls(host string) (*smtp.Client, error) {
|
||||
return client, err
|
||||
}
|
||||
|
||||
func (smtpConfig SMTP) getSMPTClientWithStartTls(host string) (*smtp.Client, error) {
|
||||
client, err := smtpConfig.getSMPTClient()
|
||||
func (smtpConfig SMTP) getSMTPClientWithStartTls(host string) (*smtp.Client, error) {
|
||||
client, err := smtpConfig.getSMTPClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package smtp
|
||||
|
||||
type Config struct {
|
||||
Description string
|
||||
SMTP SMTP
|
||||
Tls bool
|
||||
From string
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
// GetSMTPConfig reads the iam SMTP provider config
|
||||
func (n *NotificationQueries) GetSMTPConfig(ctx context.Context) (*smtp.Config, error) {
|
||||
config, err := n.SMTPConfigByAggregateID(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
config, err := n.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -19,6 +19,7 @@ func (n *NotificationQueries) GetSMTPConfig(ctx context.Context) (*smtp.Config,
|
||||
return nil, err
|
||||
}
|
||||
return &smtp.Config{
|
||||
Description: config.Description,
|
||||
From: config.SenderAddress,
|
||||
FromName: config.SenderName,
|
||||
ReplyToAddress: config.ReplyToAddress,
|
||||
|
@ -181,19 +181,19 @@ func (mr *MockQueriesMockRecorder) SMSProviderConfig(arg0 any, arg1 ...any) *gom
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMSProviderConfig", reflect.TypeOf((*MockQueries)(nil).SMSProviderConfig), varargs...)
|
||||
}
|
||||
|
||||
// SMTPConfigByAggregateID mocks base method.
|
||||
func (m *MockQueries) SMTPConfigByAggregateID(arg0 context.Context, arg1 string) (*query.SMTPConfig, error) {
|
||||
// SMTPConfigActive mocks base method.
|
||||
func (m *MockQueries) SMTPConfigActive(arg0 context.Context, arg1 string) (*query.SMTPConfig, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SMTPConfigByAggregateID", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "SMTPConfigActive", arg0, arg1)
|
||||
ret0, _ := ret[0].(*query.SMTPConfig)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SMTPConfigByAggregateID indicates an expected call of SMTPConfigByAggregateID.
|
||||
func (mr *MockQueriesMockRecorder) SMTPConfigByAggregateID(arg0, arg1 any) *gomock.Call {
|
||||
// SMTPConfigActive indicates an expected call of SMTPConfigActive.
|
||||
func (mr *MockQueriesMockRecorder) SMTPConfigActive(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMTPConfigByAggregateID", reflect.TypeOf((*MockQueries)(nil).SMTPConfigByAggregateID), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMTPConfigActive", reflect.TypeOf((*MockQueries)(nil).SMTPConfigActive), arg0, arg1)
|
||||
}
|
||||
|
||||
// SearchInstanceDomains mocks base method.
|
||||
|
@ -22,7 +22,7 @@ type Queries interface {
|
||||
SearchMilestones(ctx context.Context, instanceIDs []string, queries *query.MilestonesSearchQueries) (*query.Milestones, error)
|
||||
NotificationProviderByIDAndType(ctx context.Context, aggID string, providerType domain.NotificationProviderType) (*query.DebugNotificationProvider, error)
|
||||
SMSProviderConfig(ctx context.Context, queries ...query.SearchQuery) (*query.SMSConfig, error)
|
||||
SMTPConfigByAggregateID(ctx context.Context, aggregateID string) (*query.SMTPConfig, error)
|
||||
SMTPConfigActive(ctx context.Context, resourceOwner string) (*query.SMTPConfig, error)
|
||||
GetDefaultLanguage(ctx context.Context) language.Tag
|
||||
GetInstanceRestrictions(ctx context.Context) (restrictions query.Restrictions, err error)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package projection
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
old_handler "github.com/zitadel/zitadel/internal/eventstore/handler"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
@ -11,14 +12,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
SMTPConfigProjectionTable = "projections.smtp_configs1"
|
||||
|
||||
SMTPConfigColumnAggregateID = "aggregate_id"
|
||||
SMTPConfigProjectionTable = "projections.smtp_configs2"
|
||||
SMTPConfigColumnInstanceID = "instance_id"
|
||||
SMTPConfigColumnResourceOwner = "resource_owner"
|
||||
SMTPConfigColumnID = "id"
|
||||
SMTPConfigColumnCreationDate = "creation_date"
|
||||
SMTPConfigColumnChangeDate = "change_date"
|
||||
SMTPConfigColumnSequence = "sequence"
|
||||
SMTPConfigColumnResourceOwner = "resource_owner"
|
||||
SMTPConfigColumnInstanceID = "instance_id"
|
||||
SMTPConfigColumnTLS = "tls"
|
||||
SMTPConfigColumnSenderAddress = "sender_address"
|
||||
SMTPConfigColumnSenderName = "sender_name"
|
||||
@ -26,6 +26,8 @@ const (
|
||||
SMTPConfigColumnSMTPHost = "host"
|
||||
SMTPConfigColumnSMTPUser = "username"
|
||||
SMTPConfigColumnSMTPPassword = "password"
|
||||
SMTPConfigColumnState = "state"
|
||||
SMTPConfigColumnDescription = "description"
|
||||
)
|
||||
|
||||
type smtpConfigProjection struct{}
|
||||
@ -41,7 +43,7 @@ func (*smtpConfigProjection) Name() string {
|
||||
func (*smtpConfigProjection) Init() *old_handler.Check {
|
||||
return handler.NewTableCheck(
|
||||
handler.NewTable([]*handler.InitColumn{
|
||||
handler.NewColumn(SMTPConfigColumnAggregateID, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigColumnID, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigColumnCreationDate, handler.ColumnTypeTimestamp),
|
||||
handler.NewColumn(SMTPConfigColumnChangeDate, handler.ColumnTypeTimestamp),
|
||||
handler.NewColumn(SMTPConfigColumnSequence, handler.ColumnTypeInt64),
|
||||
@ -54,8 +56,10 @@ func (*smtpConfigProjection) Init() *old_handler.Check {
|
||||
handler.NewColumn(SMTPConfigColumnSMTPHost, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigColumnSMTPUser, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigColumnSMTPPassword, handler.ColumnTypeJSONB, handler.Nullable()),
|
||||
handler.NewColumn(SMTPConfigColumnState, handler.ColumnTypeEnum),
|
||||
handler.NewColumn(SMTPConfigColumnDescription, handler.ColumnTypeText),
|
||||
},
|
||||
handler.NewPrimaryKey(SMTPConfigColumnInstanceID, SMTPConfigColumnAggregateID),
|
||||
handler.NewPrimaryKey(SMTPConfigColumnInstanceID, SMTPConfigColumnResourceOwner, SMTPConfigColumnID),
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -77,6 +81,14 @@ func (p *smtpConfigProjection) Reducers() []handler.AggregateReducer {
|
||||
Event: instance.SMTPConfigPasswordChangedEventType,
|
||||
Reduce: p.reduceSMTPConfigPasswordChanged,
|
||||
},
|
||||
{
|
||||
Event: instance.SMTPConfigActivatedEventType,
|
||||
Reduce: p.reduceSMTPConfigActivated,
|
||||
},
|
||||
{
|
||||
Event: instance.SMTPConfigDeactivatedEventType,
|
||||
Reduce: p.reduceSMTPConfigDeactivated,
|
||||
},
|
||||
{
|
||||
Event: instance.SMTPConfigRemovedEventType,
|
||||
Reduce: p.reduceSMTPConfigRemoved,
|
||||
@ -95,15 +107,26 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-sk99F", "reduce.wrong.event.type %s", instance.SMTPConfigAddedEventType)
|
||||
}
|
||||
|
||||
// Deal with old and unique SMTP settings (empty ID)
|
||||
id := e.ID
|
||||
description := e.Description
|
||||
state := domain.SMTPConfigStateInactive
|
||||
if e.ID == "" {
|
||||
id = e.Aggregate().ResourceOwner
|
||||
description = "generic"
|
||||
state = domain.SMTPConfigStateActive
|
||||
}
|
||||
|
||||
return handler.NewCreateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCol(SMTPConfigColumnCreationDate, e.CreationDate()),
|
||||
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
|
||||
handler.NewCol(SMTPConfigColumnID, id),
|
||||
handler.NewCol(SMTPConfigColumnTLS, e.TLS),
|
||||
handler.NewCol(SMTPConfigColumnSenderAddress, e.SenderAddress),
|
||||
handler.NewCol(SMTPConfigColumnSenderName, e.SenderName),
|
||||
@ -111,6 +134,8 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
|
||||
handler.NewCol(SMTPConfigColumnSMTPHost, e.Host),
|
||||
handler.NewCol(SMTPConfigColumnSMTPUser, e.User),
|
||||
handler.NewCol(SMTPConfigColumnSMTPPassword, e.Password),
|
||||
handler.NewCol(SMTPConfigColumnState, state),
|
||||
handler.NewCol(SMTPConfigColumnDescription, description),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
@ -124,6 +149,13 @@ func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (
|
||||
columns := make([]handler.Column, 0, 8)
|
||||
columns = append(columns, handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()))
|
||||
|
||||
// Deal with old and unique SMTP settings (empty ID)
|
||||
id := e.ID
|
||||
if e.ID == "" {
|
||||
id = e.Aggregate().ResourceOwner
|
||||
}
|
||||
|
||||
if e.TLS != nil {
|
||||
columns = append(columns, handler.NewCol(SMTPConfigColumnTLS, *e.TLS))
|
||||
}
|
||||
@ -142,11 +174,18 @@ func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (
|
||||
if e.User != nil {
|
||||
columns = append(columns, handler.NewCol(SMTPConfigColumnSMTPUser, *e.User))
|
||||
}
|
||||
if e.Password != nil {
|
||||
columns = append(columns, handler.NewCol(SMTPConfigColumnSMTPPassword, *e.Password))
|
||||
}
|
||||
if e.Description != nil {
|
||||
columns = append(columns, handler.NewCol(SMTPConfigColumnDescription, *e.Description))
|
||||
}
|
||||
return handler.NewUpdateStatement(
|
||||
e,
|
||||
columns,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SMTPConfigColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCond(SMTPConfigColumnID, id),
|
||||
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
@ -158,6 +197,12 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-fk02f", "reduce.wrong.event.type %s", instance.SMTPConfigChangedEventType)
|
||||
}
|
||||
|
||||
// Deal with old and unique SMTP settings (empty ID)
|
||||
id := e.ID
|
||||
if e.ID == "" {
|
||||
id = e.Aggregate().ResourceOwner
|
||||
}
|
||||
|
||||
return handler.NewUpdateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
@ -166,7 +211,62 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
|
||||
handler.NewCol(SMTPConfigColumnSMTPPassword, e.Password),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SMTPConfigColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCond(SMTPConfigColumnID, id),
|
||||
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *smtpConfigProjection) reduceSMTPConfigActivated(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*instance.SMTPConfigActivatedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-fq92r", "reduce.wrong.event.type %s", instance.SMTPConfigActivatedEventType)
|
||||
}
|
||||
|
||||
// Deal with old and unique SMTP settings (empty ID)
|
||||
id := e.ID
|
||||
if e.ID == "" {
|
||||
id = e.Aggregate().ResourceOwner
|
||||
}
|
||||
|
||||
return handler.NewUpdateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
|
||||
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateActive),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SMTPConfigColumnID, id),
|
||||
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *smtpConfigProjection) reduceSMTPConfigDeactivated(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*instance.SMTPConfigDeactivatedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-hv89j", "reduce.wrong.event.type %s", instance.SMTPConfigDeactivatedEventType)
|
||||
}
|
||||
|
||||
// Deal with old and unique SMTP settings (empty ID)
|
||||
id := e.ID
|
||||
if e.ID == "" {
|
||||
id = e.Aggregate().ResourceOwner
|
||||
}
|
||||
|
||||
return handler.NewUpdateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
|
||||
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SMTPConfigColumnID, id),
|
||||
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
@ -177,10 +277,18 @@ func (p *smtpConfigProjection) reduceSMTPConfigRemoved(event eventstore.Event) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deal with old and unique SMTP settings (empty ID)
|
||||
id := e.ID
|
||||
if e.ID == "" {
|
||||
id = e.Aggregate().ResourceOwner
|
||||
}
|
||||
|
||||
return handler.NewDeleteStatement(
|
||||
e,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SMTPConfigColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCond(SMTPConfigColumnID, id),
|
||||
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
|
@ -3,6 +3,7 @@ package projection
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
@ -27,12 +28,16 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
instance.SMTPConfigChangedEventType,
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"description": "test",
|
||||
"tls": true,
|
||||
"senderAddress": "sender",
|
||||
"senderName": "name",
|
||||
"replyToAddress": "reply-to",
|
||||
"host": "host",
|
||||
"user": "user"
|
||||
"user": "user",
|
||||
"id": "44444",
|
||||
"resource_owner": "ro-id",
|
||||
"instance_id": "instance-id"
|
||||
}`,
|
||||
),
|
||||
), instance.SMTPConfigChangedEventMapper),
|
||||
@ -44,7 +49,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs1 SET (change_date, sequence, tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (aggregate_id = $9) AND (instance_id = $10)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, tls, sender_address, sender_name, reply_to_address, host, username, description) = ($1, $2, $3, $4, $5, $6, $7, $8, $9) WHERE (id = $10) AND (resource_owner = $11) AND (instance_id = $12)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -54,7 +59,9 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
"reply-to",
|
||||
"host",
|
||||
"user",
|
||||
"agg-id",
|
||||
"test",
|
||||
"44444",
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
@ -71,6 +78,8 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"tls": true,
|
||||
"id": "id",
|
||||
"description": "test",
|
||||
"senderAddress": "sender",
|
||||
"senderName": "name",
|
||||
"replyToAddress": "reply-to",
|
||||
@ -91,14 +100,14 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs1 (aggregate_id, creation_date, change_date, resource_owner, instance_id, sequence, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs2 (creation_date, change_date, resource_owner, instance_id, sequence, id, tls, sender_address, sender_name, reply_to_address, host, username, password, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
uint64(15),
|
||||
"id",
|
||||
true,
|
||||
"sender",
|
||||
"name",
|
||||
@ -106,6 +115,72 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
"host",
|
||||
"user",
|
||||
anyArg{},
|
||||
domain.SMTPConfigState(3),
|
||||
"test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceSMTPConfigActivated",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
instance.SMTPConfigActivatedEventType,
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "config-id"
|
||||
}`),
|
||||
), instance.SMTPConfigActivatedEventMapper),
|
||||
},
|
||||
reduce: (&smtpConfigProjection{}).reduceSMTPConfigActivated,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("instance"),
|
||||
sequence: 15,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (resource_owner = $5) AND (instance_id = $6)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
domain.SMTPConfigStateActive,
|
||||
"config-id",
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceSMTPConfigDeactivated",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
instance.SMTPConfigDeactivatedEventType,
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "config-id"
|
||||
}`),
|
||||
), instance.SMTPConfigDeactivatedEventMapper),
|
||||
},
|
||||
reduce: (&smtpConfigProjection{}).reduceSMTPConfigDeactivated,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("instance"),
|
||||
sequence: 15,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (resource_owner = $5) AND (instance_id = $6)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
domain.SMTPConfigStateInactive,
|
||||
"config-id",
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -120,6 +195,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
instance.SMTPConfigPasswordChangedEventType,
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "config-id",
|
||||
"password": {
|
||||
"cryptoType": 0,
|
||||
"algorithm": "RSA-265",
|
||||
@ -135,12 +211,13 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs1 SET (change_date, sequence, password) = ($1, $2, $3) WHERE (aggregate_id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, password) = ($1, $2, $3) WHERE (id = $4) AND (resource_owner = $5) AND (instance_id = $6)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
anyArg{},
|
||||
"agg-id",
|
||||
"config-id",
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
@ -154,7 +231,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
event: getEvent(testEvent(
|
||||
instance.SMTPConfigRemovedEventType,
|
||||
instance.AggregateType,
|
||||
[]byte(`{}`),
|
||||
[]byte(`{ "id": "config-id"}`),
|
||||
), instance.SMTPConfigRemovedEventMapper),
|
||||
},
|
||||
reduce: (&smtpConfigProjection{}).reduceSMTPConfigRemoved,
|
||||
@ -164,9 +241,10 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs1 WHERE (aggregate_id = $1) AND (instance_id = $2)",
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs2 WHERE (id = $1) AND (resource_owner = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"config-id",
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
@ -191,7 +269,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs1 WHERE (instance_id = $1)",
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs2 WHERE (instance_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
|
@ -11,20 +11,27 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/call"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query/projection"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type SMTPConfigsSearchQueries struct {
|
||||
SearchRequest
|
||||
Queries []SearchQuery
|
||||
}
|
||||
|
||||
type SMTPConfigs struct {
|
||||
SearchResponse
|
||||
Configs []*SMTPConfig
|
||||
}
|
||||
|
||||
var (
|
||||
smtpConfigsTable = table{
|
||||
name: projection.SMTPConfigProjectionTable,
|
||||
instanceIDCol: projection.SMTPConfigColumnInstanceID,
|
||||
}
|
||||
SMTPConfigColumnAggregateID = Column{
|
||||
name: projection.SMTPConfigColumnAggregateID,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnCreationDate = Column{
|
||||
name: projection.SMTPConfigColumnCreationDate,
|
||||
table: smtpConfigsTable,
|
||||
@ -73,20 +80,25 @@ var (
|
||||
name: projection.SMTPConfigColumnSMTPPassword,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnID = Column{
|
||||
name: projection.SMTPConfigColumnID,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnState = Column{
|
||||
name: projection.SMTPConfigColumnState,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnDescription = Column{
|
||||
name: projection.SMTPConfigColumnDescription,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
)
|
||||
|
||||
type SMTPConfigs struct {
|
||||
SearchResponse
|
||||
SMTPConfigs []*SMTPConfig
|
||||
}
|
||||
|
||||
type SMTPConfig struct {
|
||||
AggregateID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
TLS bool
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
@ -94,19 +106,44 @@ type SMTPConfig struct {
|
||||
Host string
|
||||
User string
|
||||
Password *crypto.CryptoValue
|
||||
ID string
|
||||
State domain.SMTPConfigState
|
||||
Description string
|
||||
}
|
||||
|
||||
func (q *Queries) SMTPConfigByAggregateID(ctx context.Context, aggregateID string) (config *SMTPConfig, err error) {
|
||||
func (q *Queries) SMTPConfigActive(ctx context.Context, resourceOwner string) (config *SMTPConfig, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
stmt, scan := prepareSMTPConfigQuery(ctx, q.client)
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
SMTPConfigColumnAggregateID.identifier(): aggregateID,
|
||||
SMTPConfigColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
SMTPConfigColumnResourceOwner.identifier(): resourceOwner,
|
||||
SMTPConfigColumnInstanceID.identifier(): resourceOwner,
|
||||
SMTPConfigColumnState.identifier(): domain.SMTPConfigStateActive,
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-3m9sl", "Errors.Query.SQLStatment")
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-3m9sl", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
err = q.client.QueryRowContext(ctx, func(row *sql.Row) error {
|
||||
config, err = scan(row)
|
||||
return err
|
||||
}, query, args...)
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (q *Queries) SMTPConfigByID(ctx context.Context, instanceID, resourceOwner, id string) (config *SMTPConfig, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
stmt, scan := prepareSMTPConfigQuery(ctx, q.client)
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
SMTPConfigColumnResourceOwner.identifier(): resourceOwner,
|
||||
SMTPConfigColumnInstanceID.identifier(): instanceID,
|
||||
SMTPConfigColumnID.identifier(): id,
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-8f8gw", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
err = q.client.QueryRowContext(ctx, func(row *sql.Row) error {
|
||||
@ -120,7 +157,6 @@ func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
password := new(crypto.CryptoValue)
|
||||
|
||||
return sq.Select(
|
||||
SMTPConfigColumnAggregateID.identifier(),
|
||||
SMTPConfigColumnCreationDate.identifier(),
|
||||
SMTPConfigColumnChangeDate.identifier(),
|
||||
SMTPConfigColumnResourceOwner.identifier(),
|
||||
@ -131,13 +167,15 @@ func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
SMTPConfigColumnReplyToAddress.identifier(),
|
||||
SMTPConfigColumnSMTPHost.identifier(),
|
||||
SMTPConfigColumnSMTPUser.identifier(),
|
||||
SMTPConfigColumnSMTPPassword.identifier()).
|
||||
SMTPConfigColumnSMTPPassword.identifier(),
|
||||
SMTPConfigColumnID.identifier(),
|
||||
SMTPConfigColumnState.identifier(),
|
||||
SMTPConfigColumnDescription.identifier()).
|
||||
From(smtpConfigsTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*SMTPConfig, error) {
|
||||
config := new(SMTPConfig)
|
||||
err := row.Scan(
|
||||
&config.AggregateID,
|
||||
&config.CreationDate,
|
||||
&config.ChangeDate,
|
||||
&config.ResourceOwner,
|
||||
@ -149,6 +187,9 @@ func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
&config.Host,
|
||||
&config.User,
|
||||
&password,
|
||||
&config.ID,
|
||||
&config.State,
|
||||
&config.Description,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
@ -160,3 +201,79 @@ func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareSMTPConfigsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*SMTPConfigs, error)) {
|
||||
return sq.Select(
|
||||
SMTPConfigColumnCreationDate.identifier(),
|
||||
SMTPConfigColumnChangeDate.identifier(),
|
||||
SMTPConfigColumnResourceOwner.identifier(),
|
||||
SMTPConfigColumnSequence.identifier(),
|
||||
SMTPConfigColumnTLS.identifier(),
|
||||
SMTPConfigColumnSenderAddress.identifier(),
|
||||
SMTPConfigColumnSenderName.identifier(),
|
||||
SMTPConfigColumnReplyToAddress.identifier(),
|
||||
SMTPConfigColumnSMTPHost.identifier(),
|
||||
SMTPConfigColumnSMTPUser.identifier(),
|
||||
SMTPConfigColumnSMTPPassword.identifier(),
|
||||
SMTPConfigColumnID.identifier(),
|
||||
SMTPConfigColumnState.identifier(),
|
||||
SMTPConfigColumnDescription.identifier(),
|
||||
countColumn.identifier()).
|
||||
From(smtpConfigsTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*SMTPConfigs, error) {
|
||||
configs := &SMTPConfigs{Configs: []*SMTPConfig{}}
|
||||
for rows.Next() {
|
||||
config := new(SMTPConfig)
|
||||
err := rows.Scan(
|
||||
&config.CreationDate,
|
||||
&config.ChangeDate,
|
||||
&config.ResourceOwner,
|
||||
&config.Sequence,
|
||||
&config.TLS,
|
||||
&config.SenderAddress,
|
||||
&config.SenderName,
|
||||
&config.ReplyToAddress,
|
||||
&config.Host,
|
||||
&config.User,
|
||||
&config.Password,
|
||||
&config.ID,
|
||||
&config.State,
|
||||
&config.Description,
|
||||
&configs.Count,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, zerrors.ThrowNotFound(err, "QUERY-fwofw", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-9k87F", "Errors.Internal")
|
||||
}
|
||||
configs.Configs = append(configs.Configs, config)
|
||||
}
|
||||
return configs, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queries) SearchSMTPConfigs(ctx context.Context, queries *SMTPConfigsSearchQueries) (configs *SMTPConfigs, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
query, scan := prepareSMTPConfigsQuery(ctx, q.client)
|
||||
stmt, args, err := queries.toQuery(query).
|
||||
Where(sq.Eq{
|
||||
SMTPConfigColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "QUERY-sZ7Cx", "Errors.Query.InvalidRequest")
|
||||
}
|
||||
|
||||
err = q.client.QueryContext(ctx, func(rows *sql.Rows) error {
|
||||
configs, err = scan(rows)
|
||||
return err
|
||||
}, stmt, args...)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-tOpKN", "Errors.Internal")
|
||||
}
|
||||
configs.State, err = q.latestState(ctx, smsConfigsTable)
|
||||
return configs, err
|
||||
}
|
||||
|
@ -9,26 +9,28 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
prepareSMTPConfigStmt = `SELECT projections.smtp_configs1.aggregate_id,` +
|
||||
` projections.smtp_configs1.creation_date,` +
|
||||
` projections.smtp_configs1.change_date,` +
|
||||
` projections.smtp_configs1.resource_owner,` +
|
||||
` projections.smtp_configs1.sequence,` +
|
||||
` projections.smtp_configs1.tls,` +
|
||||
` projections.smtp_configs1.sender_address,` +
|
||||
` projections.smtp_configs1.sender_name,` +
|
||||
` projections.smtp_configs1.reply_to_address,` +
|
||||
` projections.smtp_configs1.host,` +
|
||||
` projections.smtp_configs1.username,` +
|
||||
` projections.smtp_configs1.password` +
|
||||
` FROM projections.smtp_configs1` +
|
||||
prepareSMTPConfigStmt = `SELECT projections.smtp_configs2.creation_date,` +
|
||||
` projections.smtp_configs2.change_date,` +
|
||||
` projections.smtp_configs2.resource_owner,` +
|
||||
` projections.smtp_configs2.sequence,` +
|
||||
` projections.smtp_configs2.tls,` +
|
||||
` projections.smtp_configs2.sender_address,` +
|
||||
` projections.smtp_configs2.sender_name,` +
|
||||
` projections.smtp_configs2.reply_to_address,` +
|
||||
` projections.smtp_configs2.host,` +
|
||||
` projections.smtp_configs2.username,` +
|
||||
` projections.smtp_configs2.password,` +
|
||||
` projections.smtp_configs2.id,` +
|
||||
` projections.smtp_configs2.state,` +
|
||||
` projections.smtp_configs2.description` +
|
||||
` FROM projections.smtp_configs2` +
|
||||
` AS OF SYSTEM TIME '-1 ms'`
|
||||
prepareSMTPConfigCols = []string{
|
||||
"aggregate_id",
|
||||
"creation_date",
|
||||
"change_date",
|
||||
"resource_owner",
|
||||
@ -40,6 +42,9 @@ var (
|
||||
"smtp_host",
|
||||
"smtp_user",
|
||||
"smtp_password",
|
||||
"id",
|
||||
"state",
|
||||
"description",
|
||||
}
|
||||
)
|
||||
|
||||
@ -80,7 +85,6 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
regexp.QuoteMeta(prepareSMTPConfigStmt),
|
||||
prepareSMTPConfigCols,
|
||||
[]driver.Value{
|
||||
"agg-id",
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
@ -92,11 +96,13 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
"2232323",
|
||||
domain.SMTPConfigStateActive,
|
||||
"test",
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
AggregateID: "agg-id",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
@ -108,6 +114,93 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: &crypto.CryptoValue{},
|
||||
ID: "2232323",
|
||||
State: domain.SMTPConfigStateActive,
|
||||
Description: "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareSMTPConfigQuery another config found",
|
||||
prepare: prepareSMTPConfigQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(prepareSMTPConfigStmt),
|
||||
prepareSMTPConfigCols,
|
||||
[]driver.Value{
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211109),
|
||||
true,
|
||||
"sender2",
|
||||
"name2",
|
||||
"reply-to2",
|
||||
"host2",
|
||||
"user2",
|
||||
&crypto.CryptoValue{},
|
||||
"44442323",
|
||||
domain.SMTPConfigStateInactive,
|
||||
"test2",
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211109,
|
||||
TLS: true,
|
||||
SenderAddress: "sender2",
|
||||
SenderName: "name2",
|
||||
ReplyToAddress: "reply-to2",
|
||||
Host: "host2",
|
||||
User: "user2",
|
||||
Password: &crypto.CryptoValue{},
|
||||
ID: "44442323",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
Description: "test2",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareSMTPConfigQuery yet another config found",
|
||||
prepare: prepareSMTPConfigQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(prepareSMTPConfigStmt),
|
||||
prepareSMTPConfigCols,
|
||||
[]driver.Value{
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211109),
|
||||
true,
|
||||
"sender3",
|
||||
"name3",
|
||||
"reply-to3",
|
||||
"host3",
|
||||
"user3",
|
||||
&crypto.CryptoValue{},
|
||||
"23234444",
|
||||
domain.SMTPConfigStateInactive,
|
||||
"test3",
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211109,
|
||||
TLS: true,
|
||||
SenderAddress: "sender3",
|
||||
SenderName: "name3",
|
||||
ReplyToAddress: "reply-to3",
|
||||
Host: "host3",
|
||||
User: "user3",
|
||||
Password: &crypto.CryptoValue{},
|
||||
ID: "23234444",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
Description: "test3",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -14,6 +14,8 @@ func init() {
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SecretGeneratorRemovedEventType, SecretGeneratorRemovedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigAddedEventType, SMTPConfigAddedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigChangedEventType, SMTPConfigChangedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigActivatedEventType, SMTPConfigActivatedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigDeactivatedEventType, SMTPConfigDeactivatedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigPasswordChangedEventType, SMTPConfigPasswordChangedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigRemovedEventType, SMTPConfigRemovedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMSConfigTwilioAddedEventType, SMSConfigTwilioAddedEventMapper)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@ -14,23 +15,29 @@ const (
|
||||
SMTPConfigChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "changed"
|
||||
SMTPConfigPasswordChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "password.changed"
|
||||
SMTPConfigRemovedEventType = instanceEventTypePrefix + smtpConfigPrefix + "removed"
|
||||
SMTPConfigActivatedEventType = instanceEventTypePrefix + smtpConfigPrefix + "activated"
|
||||
SMTPConfigDeactivatedEventType = instanceEventTypePrefix + smtpConfigPrefix + "deactivated"
|
||||
)
|
||||
|
||||
type SMTPConfigAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
SenderAddress string `json:"senderAddress,omitempty"`
|
||||
SenderName string `json:"senderName,omitempty"`
|
||||
ReplyToAddress string `json:"replyToAddress,omitempty"`
|
||||
TLS bool `json:"tls,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
SenderAddress string `json:"senderAddress,omitempty"`
|
||||
SenderName string `json:"senderName,omitempty"`
|
||||
ReplyToAddress string `json:"replyToAddress,omitempty"`
|
||||
TLS bool `json:"tls,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
State domain.SMTPConfigState `json:"state,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id, description string,
|
||||
tls bool,
|
||||
senderAddress,
|
||||
senderName,
|
||||
@ -45,6 +52,8 @@ func NewSMTPConfigAddedEvent(
|
||||
aggregate,
|
||||
SMTPConfigAddedEventType,
|
||||
),
|
||||
ID: id,
|
||||
Description: description,
|
||||
TLS: tls,
|
||||
SenderAddress: senderAddress,
|
||||
SenderName: senderName,
|
||||
@ -77,13 +86,15 @@ func SMTPConfigAddedEventMapper(event eventstore.Event) (eventstore.Event, error
|
||||
|
||||
type SMTPConfigChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
FromAddress *string `json:"senderAddress,omitempty"`
|
||||
FromName *string `json:"senderName,omitempty"`
|
||||
ReplyToAddress *string `json:"replyToAddress,omitempty"`
|
||||
TLS *bool `json:"tls,omitempty"`
|
||||
Host *string `json:"host,omitempty"`
|
||||
User *string `json:"user,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
FromAddress *string `json:"senderAddress,omitempty"`
|
||||
FromName *string `json:"senderName,omitempty"`
|
||||
ReplyToAddress *string `json:"replyToAddress,omitempty"`
|
||||
TLS *bool `json:"tls,omitempty"`
|
||||
Host *string `json:"host,omitempty"`
|
||||
User *string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func (e *SMTPConfigChangedEvent) Payload() interface{} {
|
||||
@ -97,6 +108,7 @@ func (e *SMTPConfigChangedEvent) UniqueConstraints() []*eventstore.UniqueConstra
|
||||
func NewSMTPConfigChangeEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
changes []SMTPConfigChanges,
|
||||
) (*SMTPConfigChangedEvent, error) {
|
||||
if len(changes) == 0 {
|
||||
@ -108,6 +120,7 @@ func NewSMTPConfigChangeEvent(
|
||||
aggregate,
|
||||
SMTPConfigChangedEventType,
|
||||
),
|
||||
ID: id,
|
||||
}
|
||||
for _, change := range changes {
|
||||
change(changeEvent)
|
||||
@ -117,6 +130,18 @@ func NewSMTPConfigChangeEvent(
|
||||
|
||||
type SMTPConfigChanges func(event *SMTPConfigChangedEvent)
|
||||
|
||||
func ChangeSMTPConfigID(id string) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.ID = id
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigDescription(description string) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.Description = &description
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigTLS(tls bool) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.TLS = &tls
|
||||
@ -153,6 +178,12 @@ func ChangeSMTPConfigSMTPUser(smtpUser string) func(event *SMTPConfigChangedEven
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigSMTPPassword(password *crypto.CryptoValue) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.Password = password
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigChangedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
e := &SMTPConfigChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
@ -168,13 +199,14 @@ func SMTPConfigChangedEventMapper(event eventstore.Event) (eventstore.Event, err
|
||||
|
||||
type SMTPConfigPasswordChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigPasswordChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
password *crypto.CryptoValue,
|
||||
) *SMTPConfigPasswordChangedEvent {
|
||||
return &SMTPConfigPasswordChangedEvent{
|
||||
@ -196,24 +228,106 @@ func (e *SMTPConfigPasswordChangedEvent) UniqueConstraints() []*eventstore.Uniqu
|
||||
}
|
||||
|
||||
func SMTPConfigPasswordChangedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigPasswordChagned := &SMTPConfigPasswordChangedEvent{
|
||||
smtpConfigPasswordChanged := &SMTPConfigPasswordChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigPasswordChagned)
|
||||
err := event.Unmarshal(smtpConfigPasswordChanged)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-99iNF", "unable to unmarshal smtp config password changed")
|
||||
}
|
||||
|
||||
return smtpConfigPasswordChagned, nil
|
||||
return smtpConfigPasswordChanged, nil
|
||||
}
|
||||
|
||||
type SMTPConfigActivatedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigActivatedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
) *SMTPConfigActivatedEvent {
|
||||
return &SMTPConfigActivatedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigActivatedEventType,
|
||||
),
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigActivatedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *SMTPConfigActivatedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigActivatedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigActivated := &SMTPConfigActivatedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigActivated)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-KPr5t", "unable to unmarshal smtp config removed")
|
||||
}
|
||||
|
||||
return smtpConfigActivated, nil
|
||||
}
|
||||
|
||||
type SMTPConfigDeactivatedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigDeactivatedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
) *SMTPConfigDeactivatedEvent {
|
||||
return &SMTPConfigDeactivatedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigDeactivatedEventType,
|
||||
),
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigDeactivatedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *SMTPConfigDeactivatedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigDeactivatedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigDeactivated := &SMTPConfigDeactivatedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigDeactivated)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-KPr5t", "unable to unmarshal smtp config removed")
|
||||
}
|
||||
|
||||
return smtpConfigDeactivated, nil
|
||||
}
|
||||
|
||||
type SMTPConfigRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigRemovedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
) *SMTPConfigRemovedEvent {
|
||||
return &SMTPConfigRemovedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@ -221,6 +335,7 @@ func NewSMTPConfigRemovedEvent(
|
||||
aggregate,
|
||||
SMTPConfigRemovedEventType,
|
||||
),
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: SMTP конфигурацията не е намерена
|
||||
AlreadyExists: SMTP конфигурация вече съществува
|
||||
AlreadyDeactivated: SMTP конфигурацията вече е деактивирана
|
||||
SenderAdressNotCustomDomain: >-
|
||||
Адресът на изпращача трябва да бъде конфигуриран като персонализиран
|
||||
домейн в екземпляра.
|
||||
@ -1151,6 +1152,9 @@ EventTypes:
|
||||
config:
|
||||
added: Добавена е SMTP конфигурация
|
||||
changed: SMTP конфигурацията е променена
|
||||
activated: SMTP конфигурацията е активирана
|
||||
deactivated: SMTP конфигурацията е деактивирана
|
||||
removed: Премахната SMTP конфигурация
|
||||
password:
|
||||
changed: Тайната на конфигурацията на SMTP е променена
|
||||
sms:
|
||||
@ -1305,6 +1309,8 @@ EventTypes:
|
||||
config:
|
||||
added: Добавена е SMTP конфигурация
|
||||
changed: SMTP конфигурацията е променена
|
||||
activated: SMTP конфигурацията е активирана
|
||||
deactivated: SMTP конфигурацията е деактивирана
|
||||
password:
|
||||
changed: Паролата на SMTP конфигурацията е променена
|
||||
removed: Премахната SMTP конфигурация
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: Konfigurace SMTP nebyla nalezena
|
||||
AlreadyExists: Konfigurace SMTP již existuje
|
||||
AlreadyDeactivated: Konfigurace SMTP je již deaktivována
|
||||
SenderAdressNotCustomDomain: Adresa odesílatele musí být nakonfigurována jako vlastní doména na instanci.
|
||||
Notification:
|
||||
NoDomain: Pro zprávu nebyla nalezena žádná doména
|
||||
@ -1126,6 +1127,9 @@ EventTypes:
|
||||
config:
|
||||
added: Konfigurace SMTP přidána
|
||||
changed: Konfigurace SMTP změněna
|
||||
activated: Konfigurace SMTP aktivována
|
||||
deactivated: Konfigurace SMTP deaktivována
|
||||
removed: Konfigurace SMTP odstraněna
|
||||
password:
|
||||
changed: Tajemství konfigurace SMTP změněno
|
||||
sms:
|
||||
@ -1271,6 +1275,8 @@ EventTypes:
|
||||
config:
|
||||
added: Konfigurace SMTP přidána
|
||||
changed: Konfigurace SMTP změněna
|
||||
activated: Konfigurace SMTP aktivována
|
||||
deactivated: Konfigurace SMTP deaktivována
|
||||
password:
|
||||
changed: Heslo konfigurace SMTP změněno
|
||||
removed: Konfigurace SMTP odstraněna
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: SMTP Konfiguration nicht gefunden
|
||||
AlreadyExists: SMTP Konfiguration existiert bereits
|
||||
AlreadyDeactivated: SMTP-Konfiguration bereits deaktiviert
|
||||
SenderAdressNotCustomDomain: Die Sender Adresse muss als Custom Domain auf der Instanz registriert sein.
|
||||
Notification:
|
||||
NoDomain: Keine Domäne für Nachricht gefunden
|
||||
@ -1128,6 +1129,9 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP Konfiguration hinzugefügt
|
||||
changed: SMTP Konfiguration geändert
|
||||
activated: SMTP Konfiguration aktiviert
|
||||
deactivated: SMTP Konfiguration deaktiviert
|
||||
removed: SMTP Konfiguration entfernt
|
||||
password:
|
||||
changed: SMTP Konfigurations Passwort geändert
|
||||
sms:
|
||||
@ -1273,6 +1277,8 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP Konfiguration hinzugefügt
|
||||
changed: SMTP Konfiguration geändert
|
||||
activated: SMTP Konfiguration aktiviert
|
||||
deactivated: SMTP Konfiguration deaktiviert
|
||||
password:
|
||||
changed: Passwort von SMTP Konfiguration geändert
|
||||
removed: SMTP Konfiguration gelöscht
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: SMTP configuration not found
|
||||
AlreadyExists: SMTP configuration already exists
|
||||
AlreadyDeactivated: SMTP configuration already deactivated
|
||||
SenderAdressNotCustomDomain: The sender address must be configured as custom domain on the instance.
|
||||
Notification:
|
||||
NoDomain: No Domain found for message
|
||||
@ -787,7 +788,7 @@ EventTypes:
|
||||
code:
|
||||
added: Phone number code generated
|
||||
sent: Phone number code sent
|
||||
removed: Phone number removed
|
||||
|
||||
profile:
|
||||
changed: User profile changed
|
||||
address:
|
||||
@ -1128,6 +1129,9 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP configuration added
|
||||
changed: SMTP configuration changed
|
||||
activated: SMTP configuration activated
|
||||
deactivated: SMTP configuration deactivated
|
||||
removed: SMTP configuration removed
|
||||
password:
|
||||
changed: SMTP configuration secret changed
|
||||
sms:
|
||||
@ -1273,6 +1277,8 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP configuration added
|
||||
changed: SMTP configuration changed
|
||||
activated: SMTP configuration activated
|
||||
deactivated: SMTP configuration deactivated
|
||||
password:
|
||||
changed: Password of SMTP configuration changed
|
||||
removed: SMTP configuration removed
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: configuración SMTP no encontrada
|
||||
AlreadyExists: la configuración SMTP ya existe
|
||||
AlreadyDeactivated: la configuración SMTP ya está desactivada
|
||||
SenderAdressNotCustomDomain: La dirección del remitente debe configurarse como un dominio personalizado en la instancia.
|
||||
Notification:
|
||||
NoDomain: No se encontró el dominio para el mensaje
|
||||
@ -1128,6 +1129,9 @@ EventTypes:
|
||||
config:
|
||||
added: Configuración SMTP añadida
|
||||
changed: Configuración SMTP modificada
|
||||
activated: Configuración SMTP activada
|
||||
deactivated: Configuración SMTP desactivada
|
||||
removed: Configuración SMTP eliminada
|
||||
password:
|
||||
changed: Configuración de secreto SMTP modificada
|
||||
sms:
|
||||
@ -1273,6 +1277,8 @@ EventTypes:
|
||||
config:
|
||||
added: Configuración SMTP añadida
|
||||
changed: Configuración SMTP modificada
|
||||
activated: Configuración SMTP activada
|
||||
deactivated: Configuración SMTP desactivada
|
||||
password:
|
||||
changed: Contraseña de configuración SMTP modificada
|
||||
removed: Configuración SMTP eliminada
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: Configuration SMTP non trouvée
|
||||
AlreadyExists: La configuration SMTP existe déjà
|
||||
AlreadyDeactivated: Configuration SMTP déjà désactivée
|
||||
SenderAdressNotCustomDomain: L'adresse de l'expéditeur doit être configurée comme un domaine personnalisé sur l'instance.
|
||||
Notification:
|
||||
NoDomain: Aucun domaine trouvé pour le message
|
||||
@ -816,6 +817,12 @@ EventTypes:
|
||||
set: Ensemble de métadonnées de l'utilisateur
|
||||
removed: Métadonnées de l'utilisateur supprimées
|
||||
removed.all: Suppression de toutes les métadonnées utilisateur
|
||||
domain:
|
||||
claimed: Domaine revendiqué
|
||||
claimed.sent: Notification de domaine revendiqué envoyée
|
||||
pat:
|
||||
added: Personal Access Token added
|
||||
removed: Personal Access Token removed
|
||||
org:
|
||||
added: Organisation ajoutée
|
||||
changed: Organisation modifiée
|
||||
@ -862,6 +869,10 @@ EventTypes:
|
||||
config:
|
||||
added: Configuration IDP SAML ajoutée
|
||||
changed: Modification de la configuration IDP SAML
|
||||
jwt:
|
||||
config:
|
||||
added: Configuration JWT IDP ajoutée
|
||||
changed: La configuration du fournisseur d'identité JWT a été modifiée
|
||||
customtext:
|
||||
set: Jeu de texte personnalisé
|
||||
removed: Texte personnalisé supprimé
|
||||
@ -875,6 +886,8 @@ EventTypes:
|
||||
idpprovider:
|
||||
added: Fournisseur d'Idp ajouté à la politique de connexion
|
||||
removed: Idp Provider supprimé de la politique de connexion
|
||||
cascade:
|
||||
removed: Cascade de fournisseurs d'identité supprimée de la stratégie de connexion
|
||||
secondfactor:
|
||||
added: Second factor ajouté à la politique de connexion
|
||||
removed: Second facteur supprimé de la politique de connexion
|
||||
@ -920,6 +933,14 @@ EventTypes:
|
||||
added: Politique de confidentialité et CGU ajoutés
|
||||
changed: Politique de confidentialité et CGU modifiées
|
||||
removed: Politique de confidentialité et conditions d'utilisation supprimées
|
||||
domain:
|
||||
added: Politique de domaine ajoutée
|
||||
changed: Politique de domaine modifiée
|
||||
removed: Politique de domaine supprimée
|
||||
lockout:
|
||||
added: Politique de verrouillage ajoutée
|
||||
changed: La politique de verrouillage a été modifiée
|
||||
removed: Politique de verrouillage supprimée
|
||||
notification:
|
||||
added: Politique de notification ajoutée
|
||||
changed: Politique de notification modifiée
|
||||
@ -930,6 +951,20 @@ EventTypes:
|
||||
cascade:
|
||||
removed: Cascade d'actions supprimée
|
||||
removed: Actions supprimées
|
||||
cleared: Flux effacé
|
||||
mail:
|
||||
template:
|
||||
added: Modèle de courrier électronique ajouté
|
||||
changed: Modèle d'e-mail modifié
|
||||
removed: Modèle d'e-mail supprimé
|
||||
text:
|
||||
added: Texte de l'e-mail ajouté
|
||||
changed: Le texte de l'e-mail a été modifié
|
||||
removed: Texte de l'e-mail supprimé
|
||||
metadata:
|
||||
removed: Metadata removed
|
||||
removed.all: All metadata removed
|
||||
set: Metadata set
|
||||
project:
|
||||
added: Projet ajouté
|
||||
changed: Projet modifié
|
||||
@ -1036,6 +1071,10 @@ EventTypes:
|
||||
saml:
|
||||
config:
|
||||
added: Ajout de la configuration SAML IDP
|
||||
changed: La configuration SAML IDP a été modifiée
|
||||
jwt:
|
||||
config:
|
||||
added: Configuration JWT du fournisseur d'identité ajoutée
|
||||
changed: Modification de la configuration de SAML IDP
|
||||
customtext:
|
||||
set: Le texte a été mis en place
|
||||
@ -1085,6 +1124,9 @@ EventTypes:
|
||||
config:
|
||||
added: Ajout de la configuration SMTP
|
||||
changed: Modification de la configuration SMTP
|
||||
activated: Configuration SMTP activée
|
||||
deactivated: Configuration SMTP désactivée
|
||||
removed: Configuration SMTP supprimée
|
||||
password:
|
||||
changed: Modification du secret de la configuration SMTP
|
||||
sms:
|
||||
@ -1099,6 +1141,8 @@ EventTypes:
|
||||
deactivated: Fournisseur de SMS Twilio désactivé
|
||||
key_pair:
|
||||
added: Paire de clés ajoutée
|
||||
certificate:
|
||||
added: Certificat ajouté
|
||||
action:
|
||||
added: Action ajoutée
|
||||
changed: Action modifiée
|
||||
@ -1111,7 +1155,134 @@ EventTypes:
|
||||
deactivated: Schéma utilisateur désactivé
|
||||
reactivated: Schéma utilisateur réactivé
|
||||
deleted: Schéma utilisateur supprimé
|
||||
instance:
|
||||
added: Instance ajoutée
|
||||
changed: Instance modifiée
|
||||
customtext:
|
||||
removed: Texte personnalisé supprimé
|
||||
set: Ensemble de texte personnalisé
|
||||
template:
|
||||
removed: Modèle de texte personnalisé supprimé
|
||||
default:
|
||||
language:
|
||||
set: Langue par défaut définie
|
||||
org:
|
||||
set: Ensemble d'organisation par défaut
|
||||
domain:
|
||||
added: Domaine ajouté
|
||||
primary:
|
||||
set: Ensemble de domaines principal
|
||||
removed: Domaine supprimé
|
||||
iam:
|
||||
console:
|
||||
set: Ensemble d'applications Console ZITADEL
|
||||
project:
|
||||
set: ZITADEL project set
|
||||
mail:
|
||||
template:
|
||||
added: Modèle de courrier électronique ajouté
|
||||
changed: Modèle d'e-mail modifié
|
||||
text:
|
||||
added: Texte de l'e-mail ajouté
|
||||
changed: Le texte de l'e-mail a été modifié
|
||||
member:
|
||||
added: Membre de l'instance ajouté
|
||||
changed: Membre de l'instance modifié
|
||||
removed: Membre de l'instance supprimé
|
||||
cascade:
|
||||
removed: Cascade de membres de l'instance supprimée
|
||||
notification:
|
||||
provider:
|
||||
debug:
|
||||
fileadded: Fournisseur de notification de débogage de fichiers ajouté
|
||||
filechanged: Le fournisseur de notification de débogage de fichier a été modifié
|
||||
fileremoved: Fournisseur de notification de débogage de fichier supprimé
|
||||
logadded: Fournisseur de notification de débogage de journal ajouté
|
||||
logchanged: Le fournisseur de notification de débogage du journal a été modifié
|
||||
logremoved: Fournisseur de notification de débogage du journal supprimé
|
||||
oidc:
|
||||
settings:
|
||||
added: Paramètres OIDC ajoutés
|
||||
changed: Paramètres OIDC modifiés
|
||||
policy:
|
||||
domain:
|
||||
added: Politique de domaine ajoutée
|
||||
changed: Politique de domaine modifiée
|
||||
label:
|
||||
activated: Politique d'étiquetage activée
|
||||
added: Politique d'étiquetage ajoutée
|
||||
assets:
|
||||
removed: L'élément de la stratégie d'étiquette a été supprimé
|
||||
changed: Politique d'étiquetage modifiée
|
||||
font:
|
||||
added: Police ajoutée à la stratégie d'étiquette
|
||||
removed: Police supprimée de la stratégie relative aux étiquettes
|
||||
icon:
|
||||
added: Icône ajoutée à la politique d'étiquetage
|
||||
removed: Icône supprimée des règles relatives aux étiquettes
|
||||
dark:
|
||||
added: Icône ajoutée à la politique d'étiquette sombre
|
||||
removed: Icône supprimée de la politique relative aux étiquettes sombres
|
||||
logo:
|
||||
added: Logo ajouté à la politique d'étiquetage
|
||||
removed: Logo supprimé de la politique relative aux étiquettes
|
||||
dark:
|
||||
added: Logo ajouté à la politique relative aux étiquettes sombres
|
||||
removed: Logo supprimé de la politique relative aux étiquettes sombres
|
||||
lockout:
|
||||
added: Politique de verrouillage ajoutée
|
||||
changed: La politique de verrouillage a été modifiée
|
||||
login:
|
||||
added: Politique de connexion ajoutée
|
||||
changed: Politique de connexion modifiée
|
||||
idpprovider:
|
||||
added: Fournisseur d'identité ajouté à la politique de connexion
|
||||
cascade:
|
||||
removed: Cascade de fournisseurs d'identité supprimée de la stratégie de connexion
|
||||
removed: Fournisseur d'identité supprimé de la stratégie de connexion
|
||||
multifactor:
|
||||
added: Multifactor ajouté à la politique de connexion
|
||||
removed: Multifactor supprimé de la politique de connexion
|
||||
secondfactor:
|
||||
added: Deuxième facteur ajouté à la politique de connexion
|
||||
removed: Deuxième facteur supprimé de la politique de connexion
|
||||
password:
|
||||
age:
|
||||
added: Politique d'âge du mot de passe ajoutée
|
||||
changed: La politique relative à l'âge du mot de passe a été modifiée
|
||||
complexity:
|
||||
added: Politique de complexité des mots de passe ajoutée
|
||||
changed: Politique de complexité des mots de passe supprimée
|
||||
privacy:
|
||||
added: Politique de confidentialité ajoutée
|
||||
changed: Politique de confidentialité modifiée
|
||||
security:
|
||||
set: Ensemble de règles de sécurité
|
||||
|
||||
removed: Instance removed
|
||||
secret:
|
||||
generator:
|
||||
added: Générateur de secrets ajouté
|
||||
changed: Le générateur de secrets a changé
|
||||
removed: Générateur de secrets supprimé
|
||||
sms:
|
||||
configtwilio:
|
||||
activated: Configuration SMS Twilio activée
|
||||
added: Configuration SMS Twilio ajoutée
|
||||
changed: La configuration des SMS Twilio a été modifiée
|
||||
deactivated: Configuration SMS Twilio désactivée
|
||||
removed: Configuration SMS Twilio supprimée
|
||||
token:
|
||||
changed: Jeton de configuration SMS Twilio modifié
|
||||
smtp:
|
||||
config:
|
||||
added: Configuration SMTP ajoutée
|
||||
changed: Configuration SMTP modifiée
|
||||
activated: Configuration SMTP activée
|
||||
deactivated: Configuration SMTP désactivée
|
||||
password:
|
||||
changed: Mot de passe de configuration SMTP modifié
|
||||
removed: Configuration SMTP supprimée
|
||||
Application:
|
||||
OIDC:
|
||||
UnsupportedVersion: Votre version de l'OIDC n'est pas prise en charge
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: Configurazione SMTP non trovata
|
||||
AlreadyExists: La configurazione SMTP esiste già
|
||||
AlreadyDeactivated: Configurazione SMTP già disattivata
|
||||
SenderAdressNotCustomDomain: L'indirizzo del mittente deve essere configurato come dominio personalizzato sull'istanza.
|
||||
Notification:
|
||||
NoDomain: Nessun dominio trovato per il messaggio
|
||||
@ -218,7 +219,6 @@ Errors:
|
||||
EmptyString: I caratteri non numerici e alfabetici non validi sono stati sostituiti con spazi vuoti e il dominio risultante è una stringa vuota
|
||||
IDP:
|
||||
InvalidSearchQuery: Parametro di ricerca non valido
|
||||
InvalidCharacter: Per un dominio sono ammessi solo caratteri alfanumerici, . e -
|
||||
ClientIDMissing: ClientID mancante
|
||||
TeamIDMissing: TeamID mancante
|
||||
KeyIDMissing: ID chiave mancante
|
||||
@ -616,6 +616,7 @@ EventTypes:
|
||||
username:
|
||||
reserved: Nome utente riservato
|
||||
released: Nome utente rilasciato
|
||||
changed: Nome utente cambiato
|
||||
email:
|
||||
reserved: Indirizzo e-mail riservato
|
||||
released: Indirizzo e-mail rilasciato
|
||||
@ -786,6 +787,7 @@ EventTypes:
|
||||
code:
|
||||
added: Codice del numero di telefono generato
|
||||
sent: Codice del numero di telefono inviato
|
||||
removed: Codice del numero di telefono rimosso
|
||||
profile:
|
||||
changed: Profilo utente cambiato
|
||||
address:
|
||||
@ -799,7 +801,9 @@ EventTypes:
|
||||
succeeded: Controllo OTP riuscito
|
||||
failed: Controllo OTP fallito
|
||||
init:
|
||||
skipped: Inizializzazione saltata
|
||||
skipped: Inizializzazione OTP saltata
|
||||
init:
|
||||
skipped: Inizializzazione saltata
|
||||
signed:
|
||||
out: L'utente è uscito
|
||||
grant:
|
||||
@ -817,6 +821,12 @@ EventTypes:
|
||||
set: Set di metadati utente
|
||||
removed: Metadati utente rimossi
|
||||
removed.all: Tutti i metadati utente rimossi
|
||||
domain:
|
||||
claimed: Dominio rivendicato
|
||||
claimed.sent: Notifica di rivendicazione del dominio inviata
|
||||
pat:
|
||||
added: Aggiunto token di accesso personale
|
||||
removed: Token di accesso personale rimosso
|
||||
org:
|
||||
added: Organizzazione aggiunta
|
||||
changed: Organizzazione cambiata
|
||||
@ -863,6 +873,10 @@ EventTypes:
|
||||
config:
|
||||
added: Aggiunta la configurazione IDP SAML
|
||||
changed: Configurazione IDP SAML modificata
|
||||
jwt:
|
||||
config:
|
||||
added: Aggiunta la configurazione IDP JWT
|
||||
changed: La configurazione dell'IDP JWT è stata modificata
|
||||
customtext:
|
||||
set: Testo personalizzato salvato
|
||||
removed: Testo personalizzato rimosso
|
||||
@ -876,6 +890,8 @@ EventTypes:
|
||||
idpprovider:
|
||||
added: IDP aggiunto alle impostazioni di accesso
|
||||
removed: IDP rimosso dalle impostazioni di accesso
|
||||
cascade:
|
||||
removed: Cascata di provider di identità rimossa dalla policy di accesso
|
||||
secondfactor:
|
||||
added: Secondo fattore aggiunto alle impostazioni di accesso
|
||||
removed: Secondo fattore rimosso dalle impostazioni di accesso
|
||||
@ -921,6 +937,14 @@ EventTypes:
|
||||
added: Informativa sulla privacy e termini e condizioni aggiunti
|
||||
changed: Informativa sulla privacy e termini e condizioni cambiati
|
||||
removed: Informativa sulla privacy e termini e condizioni rimossi
|
||||
domain:
|
||||
added: Aggiunta politica di dominio
|
||||
changed: La politica del dominio è cambiata
|
||||
removed: Politica del dominio rimossa
|
||||
lockout:
|
||||
added: Lockout policy added
|
||||
changed: Lockout policy changed
|
||||
removed: Lockout policy removed
|
||||
notification:
|
||||
added: Impostazione di notifica creata
|
||||
changed: Impostazione di notifica cambiata
|
||||
@ -931,6 +955,20 @@ EventTypes:
|
||||
cascade:
|
||||
removed: Azioni a cascata rimosse
|
||||
removed: Azioni rimosse
|
||||
cleared: Il flusso è stato eliminato
|
||||
mail:
|
||||
template:
|
||||
added: Aggiunto modello di posta elettronica
|
||||
changed: Il modello di posta elettronica è stato modificato
|
||||
removed: Modello di posta elettronica rimosso
|
||||
text:
|
||||
added: Aggiunto il testo dell'e-mail
|
||||
changed: Il testo dell'e-mail è stato modificato
|
||||
removed: Testo dell'e-mail rimosso
|
||||
metadata:
|
||||
removed: Metadati rimossi
|
||||
removed.all: Tutti i metadati rimossi
|
||||
set: Insieme di metadati
|
||||
project:
|
||||
added: Progetto aggiunto
|
||||
changed: Progetto cambiato
|
||||
@ -1037,7 +1075,11 @@ EventTypes:
|
||||
saml:
|
||||
config:
|
||||
added: Aggiunta la configurazione IDP SAML
|
||||
changed: Configurazione IDP SAML modificata
|
||||
changed: La configurazione dell'IDP SAML è stata modificata
|
||||
jwt:
|
||||
config:
|
||||
added: Aggiunta la configurazione JWT al provider di identità
|
||||
changed: Configurazione JWT dal provider di identità rimossa
|
||||
customtext:
|
||||
set: Il testo è stato impostato
|
||||
removed: Il testo è stato rimosso
|
||||
@ -1086,6 +1128,9 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP configuration added
|
||||
changed: SMTP configuration changed
|
||||
activated: Configurazione SMTP attivata
|
||||
deactivated: Configurazione SMTP disattivata
|
||||
removed: Configurazione SMTP rimossa
|
||||
password:
|
||||
changed: SMTP configuration secret changed
|
||||
sms:
|
||||
@ -1100,6 +1145,8 @@ EventTypes:
|
||||
deactivated: Provider SMS Twilio disattivato
|
||||
key_pair:
|
||||
added: Keypair aggiunto
|
||||
certificate:
|
||||
added: Certificato aggiunto
|
||||
action:
|
||||
added: Azione aggiunta
|
||||
changed: Azione cambiata
|
||||
@ -1112,6 +1159,134 @@ EventTypes:
|
||||
deactivated: Schema utente disattivato
|
||||
reactivated: Schema utente riattivato
|
||||
deleted: Schema utente eliminato
|
||||
instance:
|
||||
added: Istanza aggiunta
|
||||
changed: L'istanza è cambiata
|
||||
customtext:
|
||||
removed: Testo personalizzato rimosso
|
||||
set: Set di testo personalizzato
|
||||
template:
|
||||
removed: Modello di testo personalizzato rimosso
|
||||
default:
|
||||
language:
|
||||
set: Lingua predefinita impostata
|
||||
org:
|
||||
set: Insieme di organizzazioni predefinito
|
||||
domain:
|
||||
added: Dominio aggiunto
|
||||
primary:
|
||||
set: Insieme di domini primari
|
||||
removed: Dominio rimosso
|
||||
iam:
|
||||
console:
|
||||
set: Set di applicazioni per console ZITADEL
|
||||
project:
|
||||
set: Set progetto ZITADEL
|
||||
mail:
|
||||
template:
|
||||
added: Aggiunto modello di posta elettronica
|
||||
changed: Il modello di posta elettronica è stato modificato
|
||||
text:
|
||||
added: Aggiunto il testo dell'e-mail
|
||||
changed: Il testo dell'e-mail è stato modificato
|
||||
member:
|
||||
added: Membro dell'istanza aggiunto
|
||||
changed: Il membro dell'istanza è cambiato
|
||||
removed: Membro dell'istanza rimosso
|
||||
cascade:
|
||||
removed: Cascata di membri dell'istanza rimossa
|
||||
notification:
|
||||
provider:
|
||||
debug:
|
||||
fileadded: Aggiunto provider di notifiche di debug dei file
|
||||
filechanged: Il provider delle notifiche di debug dei file è stato modificato
|
||||
fileremoved: Provider di notifiche di debug del file rimosso
|
||||
logadded: Aggiunto provider di notifiche di debug del registro
|
||||
logchanged: Il provider delle notifiche di debug del registro è stato modificato
|
||||
logremoved: Provider di notifiche di debug del registro rimosso
|
||||
oidc:
|
||||
settings:
|
||||
added: Aggiunte impostazioni OIDC
|
||||
changed: Le impostazioni OIDC sono state modificate
|
||||
policy:
|
||||
domain:
|
||||
added: Aggiunta politica di dominio
|
||||
changed: Domain policy changed
|
||||
label:
|
||||
activated: Criterio etichetta attivato
|
||||
added: Aggiunta la politica sull'etichetta
|
||||
assets:
|
||||
removed: Risorsa dalla norma sull'etichetta rimossa
|
||||
changed: La politica sull'etichetta è cambiata
|
||||
font:
|
||||
added: Carattere aggiunto ai criteri di etichetta
|
||||
removed: Carattere rimosso dai criteri di etichetta
|
||||
icon:
|
||||
added: Icona aggiunta al criterio dell'etichetta
|
||||
removed: Icona rimossa dal criterio di etichetta
|
||||
dark:
|
||||
added: Icona aggiunta al criterio dell'etichetta oscura
|
||||
removed: Icona rimossa dal criterio dell'etichetta oscura
|
||||
logo:
|
||||
added: Logo aggiunto alla politica sull'etichetta
|
||||
removed: Logo rimosso dalla politica sull'etichetta
|
||||
dark:
|
||||
added: Logo aggiunto alla politica delle etichette scure
|
||||
removed: Logo rimosso dalla politica delle etichette scure
|
||||
lockout:
|
||||
added: Aggiunta politica di blocco
|
||||
changed: La politica di blocco è cambiata
|
||||
login:
|
||||
added: Criteri di accesso aggiunti
|
||||
changed: La politica di accesso è cambiata
|
||||
idpprovider:
|
||||
added: Provider di identità aggiunto alla policy di accesso
|
||||
cascade:
|
||||
removed: Cascata di provider di identità rimossa dalla policy di accesso
|
||||
removed: Provider di identità rimosso dalla policy di accesso
|
||||
multifactor:
|
||||
added: Multifattore aggiunto alla policy di accesso
|
||||
removed: Multifattore rimosso dalla policy di accesso
|
||||
secondfactor:
|
||||
added: Secondo fattore aggiunto alla politica di accesso
|
||||
removed: Secondo fattore rimosso dalla politica di accesso
|
||||
password:
|
||||
age:
|
||||
added: Aggiunta politica sull'età della password
|
||||
changed: La politica di validità della password è cambiata
|
||||
complexity:
|
||||
added: Aggiunta policy sulla complessità della password
|
||||
changed: Criterio di complessità della password rimosso
|
||||
privacy:
|
||||
added: Aggiunta informativa sulla privacy
|
||||
changed: L'informativa sulla privacy è cambiata
|
||||
security:
|
||||
set: Insieme di politiche di sicurezza
|
||||
|
||||
removed: Istanza rimossa
|
||||
secret:
|
||||
generator:
|
||||
added: Aggiunto generatore segreto
|
||||
changed: Il generatore segreto è cambiato
|
||||
removed: Generatore segreto rimosso
|
||||
sms:
|
||||
configtwilio:
|
||||
activated: Configurazione SMS Twilio attivata
|
||||
added: Aggiunta la configurazione SMS di Twilio
|
||||
changed: La configurazione SMS di Twilio è stata modificata
|
||||
deactivated: Configurazione SMS Twilio disattivata
|
||||
removed: Configurazione SMS di Twilio rimossa
|
||||
token:
|
||||
changed: La configurazione del token di Twilio SMS è stata modificata
|
||||
smtp:
|
||||
config:
|
||||
added: Aggiunta configurazione SMTP
|
||||
changed: La configurazione SMTP è stata modificata
|
||||
activated: Configurazione SMTP attivata
|
||||
deactivated: Configurazione SMTP disattivata
|
||||
password:
|
||||
changed: La password della configurazione SMTP è cambiata
|
||||
removed: Configurazione SMTP rimossa
|
||||
|
||||
Application:
|
||||
OIDC:
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: SMTP構成が見つかりません
|
||||
AlreadyExists: すでに存在するSMTP構成です
|
||||
AlreadyDeactivated: SMTP設定はすでに無効化されています
|
||||
SenderAdressNotCustomDomain: 送信者アドレスは、インスタンスのカスタムドメインとして構成する必要があります。
|
||||
Notification:
|
||||
NoDomain: メッセージのドメインが見つかりません
|
||||
@ -1117,6 +1118,9 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP構成の追加
|
||||
changed: SMTP構成の変更
|
||||
activated: SMTP設定が有効化されました
|
||||
deactivated: SMTP設定が無効化されました
|
||||
removed: SMTP設定が削除されました
|
||||
password:
|
||||
changed: SMTP構成シークレットの変更
|
||||
sms:
|
||||
@ -1262,6 +1266,8 @@ EventTypes:
|
||||
config:
|
||||
added: SMTP構成の追加
|
||||
changed: SMTP構成の変更
|
||||
activated: SMTP設定が有効化されました
|
||||
deactivated: SMTP設定が無効化されました
|
||||
password:
|
||||
changed: SMTP構成パスワードの変更
|
||||
removed: SMTP構成の削除
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: SMTP конфигурацијата не е пронајдена
|
||||
AlreadyExists: SMTP конфигурацијата веќе постои
|
||||
AlreadyDeactivated: SMTP конфигурацијата е веќе деактивирана
|
||||
SenderAdressNotCustomDomain: Адресата на испраќачот мора да биде конфигурирана како прилагоден домен на инстанцата.
|
||||
Notification:
|
||||
NoDomain: Не е пронајден домен за пораката
|
||||
@ -1127,6 +1128,9 @@ EventTypes:
|
||||
config:
|
||||
added: Додадена SMTP конфигурација
|
||||
changed: Променета SMTP конфигурација
|
||||
activated: SMTP конфигурацијата е активирана
|
||||
deactivated: SMTP конфигурацијата е деактивирана
|
||||
removed: SMTP конфигурацијата е отстранета
|
||||
password:
|
||||
changed: Променена тајна на SMTP конфигурација
|
||||
sms:
|
||||
@ -1271,6 +1275,8 @@ EventTypes:
|
||||
config:
|
||||
added: Додадена SMTP конфигурација
|
||||
changed: Променета SMTP конфигурација
|
||||
activated: SMTP конфигурацијата е активирана
|
||||
deactivated: SMTP конфигурацијата е деактивирана
|
||||
password:
|
||||
changed: Променета лозинка на SMTP конфигурацијата
|
||||
removed: Отстранета SMTP конфигурација
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: Konfiguracja SMTP nie znaleziona
|
||||
AlreadyExists: Konfiguracja SMTP już istnieje
|
||||
AlreadyDeactivated: Konfiguracja SMTP jest już dezaktywowana
|
||||
SenderAdressNotCustomDomain: Adres nadawcy musi być skonfigurowany jako domena niestandardowa na instancji.
|
||||
Notification:
|
||||
NoDomain: Nie znaleziono domeny dla wiadomości
|
||||
@ -1128,6 +1129,9 @@ EventTypes:
|
||||
config:
|
||||
added: Dodano konfigurację SMTP
|
||||
changed: Zmieniono konfigurację SMTP
|
||||
activated: Konfiguracja SMTP została aktywowana
|
||||
deactivated: Konfiguracja SMTP dezaktywowana
|
||||
removed: Konfiguracja SMTP została usunięta
|
||||
password:
|
||||
changed: Zmieniono sekret konfiguracji SMTP
|
||||
sms:
|
||||
@ -1273,6 +1277,8 @@ EventTypes:
|
||||
config:
|
||||
added: Konfiguracja SMTP dodana
|
||||
changed: Konfiguracja SMTP zmieniona
|
||||
activated: Konfiguracja SMTP została aktywowana
|
||||
deactivated: Konfiguracja SMTP dezaktywowana
|
||||
password:
|
||||
changed: Hasło konfiguracji SMTP zmienione
|
||||
removed: Konfiguracja SMTP usunięta
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: Configuração de SMTP não encontrada
|
||||
AlreadyExists: Configuração de SMTP já existe
|
||||
AlreadyDeactivated: Configuração SMTP já desativada
|
||||
SenderAdressNotCustomDomain: O endereço do remetente deve ser configurado como um domínio personalizado na instância.
|
||||
Notification:
|
||||
NoDomain: Nenhum domínio encontrado para a mensagem
|
||||
@ -1122,6 +1123,9 @@ EventTypes:
|
||||
config:
|
||||
added: Configuração SMTP adicionada
|
||||
changed: Configuração SMTP alterada
|
||||
activated: Configuração SMTP ativada
|
||||
deactivated: Configuração SMTP desativada
|
||||
removed: Configuração SMTP removida
|
||||
password:
|
||||
changed: Segredo da configuração SMTP alterado
|
||||
sms:
|
||||
@ -1267,6 +1271,8 @@ EventTypes:
|
||||
config:
|
||||
added: Configuração SMTP adicionada
|
||||
changed: Configuração SMTP alterada
|
||||
activated: Configuração SMTP ativada
|
||||
deactivated: Configuração SMTP desativada
|
||||
password:
|
||||
changed: Senha da configuração SMTP alterada
|
||||
removed: Configuração SMTP removida
|
||||
|
@ -56,7 +56,8 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: Конфигурация SMTP не найдена
|
||||
AlreadyExists: Конфигурация SMTP уже существует
|
||||
SenderAdressNotCustomDomain: Адрес отправителя должен быть настроен как личный домен в экземпляре
|
||||
AlreadyDeactivated: Конфигурация SMTP уже деактивирована
|
||||
SenderAdressNotCustomDomain: Адрес отправителя должен быть настроен как личный домен на экземпляре.
|
||||
Notification:
|
||||
NoDomain: Домен не найден
|
||||
User:
|
||||
@ -1117,6 +1118,9 @@ EventTypes:
|
||||
config:
|
||||
added: Конфигурация SMTP добавлена
|
||||
changed: Конфигурация SMTP изменена
|
||||
activated: Конфигурация SMTP активирована
|
||||
deactivated: Конфигурация SMTP деактивирована
|
||||
removed: Конфигурация SMTP удалена.
|
||||
password:
|
||||
changed: Ключ конфигурации SMTP изменён
|
||||
sms:
|
||||
@ -1262,6 +1266,8 @@ EventTypes:
|
||||
config:
|
||||
added: Конфигурация SMTP добавлена
|
||||
changed: Конфигурация SMTP изменена
|
||||
activated: Конфигурация SMTP активирована
|
||||
deactivated: Конфигурация SMTP деактивирована
|
||||
password:
|
||||
changed: Пароль конфигурации SMTP изменён
|
||||
removed: Конфигурация SMTP удалена
|
||||
|
@ -56,6 +56,7 @@ Errors:
|
||||
SMTPConfig:
|
||||
NotFound: 未找到 SMTP 配置
|
||||
AlreadyExists: SMTP 配置已存在
|
||||
AlreadyDeactivated: SMTP 配置已停用
|
||||
SenderAdressNotCustomDomain: 发件人地址必须在在实例的域名设置中验证。
|
||||
Notification:
|
||||
NoDomain: 未找到对应的域名
|
||||
@ -615,6 +616,7 @@ EventTypes:
|
||||
username:
|
||||
reserved: 保留用户名
|
||||
released: 用户名已发布
|
||||
changed: 用户名已更改
|
||||
email:
|
||||
reserved: 电子邮件地址已保留
|
||||
released: 电子邮件地址已发布
|
||||
@ -670,6 +672,10 @@ EventTypes:
|
||||
check:
|
||||
succeeded: 密码检查成功
|
||||
failed: 密码检查失败
|
||||
change:
|
||||
sent: 密码更改已发送
|
||||
hash:
|
||||
updated: 密码哈希已更新
|
||||
externallogin:
|
||||
check:
|
||||
succeeded: 外部登录成功
|
||||
@ -773,10 +779,6 @@ EventTypes:
|
||||
check:
|
||||
succeeded: 密码检查成功
|
||||
failed: 密码检查失败
|
||||
change:
|
||||
sent: 密码更改已发送
|
||||
hash:
|
||||
updated: 密码哈希已更新
|
||||
phone:
|
||||
changed: 更改手机号码
|
||||
verified: 验证手机号码
|
||||
@ -785,6 +787,7 @@ EventTypes:
|
||||
code:
|
||||
added: 生成的手机号码验证码
|
||||
sent: 发送手机号码验证码
|
||||
removed: 电话号码已删除
|
||||
profile:
|
||||
changed: 修改用户资料
|
||||
address:
|
||||
@ -797,8 +800,10 @@ EventTypes:
|
||||
check:
|
||||
succeeded: MFA OTP 验证成功
|
||||
failed: MFA OTP 验证失败
|
||||
init:
|
||||
skipped: 跳过 MFA 初始化
|
||||
init:
|
||||
skipped: 跳过 MFA 初始化
|
||||
skipped: 跳过多因素初始化
|
||||
signed:
|
||||
out: 用户退出登录
|
||||
grant:
|
||||
@ -816,6 +821,12 @@ EventTypes:
|
||||
set: 用户元数据集
|
||||
removed: 删除用户元数据
|
||||
removed.all: 删除所有用户元数据
|
||||
domain:
|
||||
claimed: 已认领域名
|
||||
claimed.sent: 已发送域声明通知
|
||||
pat:
|
||||
added: 添加个人访问令牌
|
||||
removed: 个人访问令牌已删除
|
||||
org:
|
||||
added: 添加组织
|
||||
changed: 更改组织
|
||||
@ -862,6 +873,10 @@ EventTypes:
|
||||
config:
|
||||
added: 添加 SAML IDP 配置
|
||||
changed: 更改 SAML IDP 配置
|
||||
jwt:
|
||||
config:
|
||||
added: 添加了 JWT IDP 配置
|
||||
changed: JWT IDP 配置已更改
|
||||
customtext:
|
||||
set: 设置自定义文本
|
||||
removed: 删除自定义文本
|
||||
@ -875,6 +890,8 @@ EventTypes:
|
||||
idpprovider:
|
||||
added: 添加 IDP 到登录策略
|
||||
removed: 从登录策略删除 IDP
|
||||
cascade:
|
||||
removed: 从登录策略中删除了身份提供者级联
|
||||
secondfactor:
|
||||
added: 添加两步认证到登录策略
|
||||
removed: 删除两步认证到登录策略
|
||||
@ -918,6 +935,14 @@ EventTypes:
|
||||
removed: 从标签策略中删除的资产
|
||||
privacy:
|
||||
added: 添加隐私政策和服务条款
|
||||
changed: 隐私政策和服务条款已更改
|
||||
removed: 隐私政策和 TOS 已删除
|
||||
domain:
|
||||
added: 添加了域策略
|
||||
changed: 域策略已更改
|
||||
removed: 域策略已删除
|
||||
lockout:
|
||||
added: 添加了锁定策略
|
||||
changed: 更改隐私政策和服务条款
|
||||
removed: 删除隐私政策和服务条款
|
||||
notification:
|
||||
@ -930,6 +955,20 @@ EventTypes:
|
||||
cascade:
|
||||
removed: 删除动作级联
|
||||
removed: 删除动作
|
||||
cleared: 流量已清除
|
||||
mail:
|
||||
template:
|
||||
added: 添加了电子邮件模板
|
||||
changed: 电子邮件模板已更改
|
||||
removed: 电子邮件模板已删除
|
||||
text:
|
||||
added: 添加了电子邮件文本
|
||||
changed: 电子邮件文本已更改
|
||||
removed: 电子邮件文本已删除
|
||||
metadata:
|
||||
removed: 电子邮件文本已删除
|
||||
removed.all: 所有元数据已删除
|
||||
set: 元数据集
|
||||
project:
|
||||
added: 添加项目
|
||||
changed: 更改项目
|
||||
@ -1037,6 +1076,10 @@ EventTypes:
|
||||
config:
|
||||
added: 添加 SAML IDP 配置
|
||||
changed: 更改 SAML IDP 配置
|
||||
jwt:
|
||||
config:
|
||||
added: 添加了身份提供者的 JWT 配置
|
||||
changed: 身份提供商的 JWT 配置已删除
|
||||
customtext:
|
||||
set: 设置文本
|
||||
removed: 删除文本
|
||||
@ -1085,6 +1128,9 @@ EventTypes:
|
||||
config:
|
||||
added: 添加 SMTP 配置
|
||||
changed: 更改 SMTP 配置
|
||||
activated: SMTP 配置已激活
|
||||
deactivated: SMTP 配置已停用
|
||||
removed: SMTP 配置已删除
|
||||
password:
|
||||
changed: 更改 SMTP 安全设置
|
||||
sms:
|
||||
@ -1099,6 +1145,8 @@ EventTypes:
|
||||
deactivated: 停用 Twilio SMS 提供者
|
||||
key_pair:
|
||||
added: 添加密钥对
|
||||
certificate:
|
||||
added: 证书已添加
|
||||
action:
|
||||
added: 添加动作
|
||||
changed: 更改动作
|
||||
@ -1111,6 +1159,134 @@ EventTypes:
|
||||
deactivated: 用户架构已停用
|
||||
reactivated: 用户架构已重新激活
|
||||
deleted: 用户架构已删除
|
||||
instance:
|
||||
added: 实例已添加
|
||||
changed: 实例已更改
|
||||
customtext:
|
||||
removed: 自定义文本已删除
|
||||
set: 自定义文本集
|
||||
template:
|
||||
removed: 删除了自定义文本模板
|
||||
default:
|
||||
language:
|
||||
set: 默认语言设置
|
||||
org:
|
||||
set: 默认组织集
|
||||
domain:
|
||||
added: 已添加域名
|
||||
primary:
|
||||
set: 主域集
|
||||
removed: 域名已删除
|
||||
iam:
|
||||
console:
|
||||
set: ZITADEL 控制台应用程序集
|
||||
project:
|
||||
set: ZITADEL 项目集
|
||||
mail:
|
||||
template:
|
||||
added: 添加了电子邮件模板
|
||||
changed: 电子邮件模板已更改
|
||||
text:
|
||||
added: 添加了电子邮件文本
|
||||
changed: 电子邮件文本已更改
|
||||
member:
|
||||
added: 已添加实例成员
|
||||
changed: 实例成员发生变化
|
||||
removed: 实例成员已删除
|
||||
cascade:
|
||||
removed: 实例成员级联已删除
|
||||
notification:
|
||||
provider:
|
||||
debug:
|
||||
fileadded: 添加了文件调试通知提供程序
|
||||
filechanged: 文件调试通知提供程序已更改
|
||||
fileremoved: 删除文件调试通知提供程序
|
||||
logadded: 添加了日志调试通知提供程序
|
||||
logchanged: 日志调试通知提供程序已更改
|
||||
logremoved: 日志调试通知提供程序已删除
|
||||
oidc:
|
||||
settings:
|
||||
added: 添加了 OIDC 设置
|
||||
changed: OIDC 设置已更改
|
||||
policy:
|
||||
domain:
|
||||
added: 添加了域策略
|
||||
changed: 域策略已更改
|
||||
label:
|
||||
activated: 标签政策已激活
|
||||
added: 添加了标签策略
|
||||
assets:
|
||||
removed: 已删除标签政策中的资产
|
||||
changed: 标签政策已更改
|
||||
font:
|
||||
added: 添加到标签政策的字体
|
||||
removed: 从标签政策中删除的字体
|
||||
icon:
|
||||
added: 图标已添加到标签策略
|
||||
removed: 图标已从标签政策中删除
|
||||
dark:
|
||||
added: 图标已添加到暗标签政策
|
||||
removed: 图标已从暗标签政策中删除
|
||||
logo:
|
||||
added: 徽标已添加到标签政策中
|
||||
removed: 徽标已从标签政策中删除
|
||||
dark:
|
||||
added: 徽标已添加到暗标签政策中
|
||||
removed: 徽标从暗标签政策中删除
|
||||
lockout:
|
||||
added: 添加了锁定策略
|
||||
changed: 锁定政策已更改
|
||||
login:
|
||||
added: 添加了登录策略
|
||||
changed: 登录政策已更改
|
||||
idpprovider:
|
||||
added: 身份提供商已添加到登录策略中
|
||||
cascade:
|
||||
removed: 身份提供者级联从登录策略中删除
|
||||
removed: 身份提供商已从登录策略中删除
|
||||
multifactor:
|
||||
added: 登录策略中添加了多因素
|
||||
removed: 从登录策略中删除了多因素
|
||||
secondfactor:
|
||||
added: 添加到登录策略的第二个因素
|
||||
removed: 从登录策略中删除了第二个因素
|
||||
password:
|
||||
age:
|
||||
added: 添加了密码年龄策略
|
||||
changed: 密码期限政策已更改
|
||||
complexity:
|
||||
added: 添加了密码复杂性策略
|
||||
changed: 删除了密码复杂性策略
|
||||
privacy:
|
||||
added: 添加了隐私政策
|
||||
changed: 隐私政策已更改
|
||||
security:
|
||||
set: 安全策略集
|
||||
|
||||
removed: 实例已删除
|
||||
secret:
|
||||
generator:
|
||||
added: 添加了秘密生成器
|
||||
changed: 秘密生成器已更改
|
||||
removed: 秘密生成器已移除
|
||||
sms:
|
||||
configtwilio:
|
||||
activated: Twilio SMS 配置已激活
|
||||
added: 添加了 Twilio SMS 配置
|
||||
changed: Twilio SMS 配置已更改
|
||||
deactivated: Twilio SMS 配置已停用
|
||||
removed: Twilio SMS 配置已删除
|
||||
token:
|
||||
changed: Twilio SMS 配置的令牌已更改
|
||||
smtp:
|
||||
config:
|
||||
added: 添加了 SMTP 配置
|
||||
changed: SMTP 配置已更改
|
||||
activated: SMTP 配置已激活
|
||||
deactivated: SMTP 配置已停用
|
||||
password:
|
||||
changed: SMTP 配置密码已更改
|
||||
removed: SMTP 配置已删除
|
||||
|
||||
Application:
|
||||
OIDC:
|
||||
|
@ -381,8 +381,24 @@ service AdminService {
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "SMTP";
|
||||
summary: "Get SMTP Configuration";
|
||||
description: "Returns the SMTP configuration from the system. This is used to send E-Mails to the users."
|
||||
summary: "Get active SMTP Configuration";
|
||||
description: "Returns the active SMTP configuration from the system. This is used to send E-Mails to the users."
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetSMTPConfigById(GetSMTPConfigByIdRequest) returns (GetSMTPConfigByIdResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/smtp/{id}";
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.read";
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "SMTP";
|
||||
summary: "Get SMTP provider configuration by its id";
|
||||
description: "Get a specific SMTP provider configuration by its ID.";
|
||||
};
|
||||
}
|
||||
|
||||
@ -405,7 +421,7 @@ service AdminService {
|
||||
|
||||
rpc UpdateSMTPConfig(UpdateSMTPConfigRequest) returns (UpdateSMTPConfigResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/smtp";
|
||||
put: "/smtp/{id}";
|
||||
body: "*"
|
||||
};
|
||||
|
||||
@ -422,7 +438,7 @@ service AdminService {
|
||||
|
||||
rpc UpdateSMTPConfigPassword(UpdateSMTPConfigPasswordRequest) returns (UpdateSMTPConfigPasswordResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/smtp/password";
|
||||
put: "/smtp/{id}/password";
|
||||
body: "*"
|
||||
};
|
||||
|
||||
@ -437,9 +453,43 @@ service AdminService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc ActivateSMTPConfig(ActivateSMTPConfigRequest) returns (ActivateSMTPConfigResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/smtp/{id}/_activate";
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.write";
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "SMTP Provider";
|
||||
summary: "Activate SMTP Provider";
|
||||
description: "Activate an SMTP provider."
|
||||
};
|
||||
}
|
||||
|
||||
rpc DeactivateSMTPConfig(DeactivateSMTPConfigRequest) returns (DeactivateSMTPConfigResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/smtp/{id}/_deactivate";
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.write";
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "SMTP Provider";
|
||||
summary: "Deactivate SMTP Provider";
|
||||
description: "Deactivate an SMTP provider. After deactivating the provider, the users will not be able to receive SMTP notifications from that provider anymore."
|
||||
};
|
||||
}
|
||||
|
||||
rpc RemoveSMTPConfig(RemoveSMTPConfigRequest) returns (RemoveSMTPConfigResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/smtp";
|
||||
delete: "/smtp/{id}";
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
@ -453,6 +503,23 @@ service AdminService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc ListSMTPConfigs(ListSMTPConfigsRequest) returns (ListSMTPConfigsResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/smtp/_search"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.read";
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "SMTP Configs";
|
||||
summary: "List SMTP Configs";
|
||||
description: "Returns a list of SMTP configurations."
|
||||
};
|
||||
}
|
||||
|
||||
rpc ListSMSProviders(ListSMSProvidersRequest) returns (ListSMSProvidersResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/sms/_search"
|
||||
@ -4007,6 +4074,23 @@ message GetSMTPConfigResponse {
|
||||
zitadel.settings.v1.SMTPConfig smtp_config = 1;
|
||||
}
|
||||
|
||||
message GetSMTPConfigByIdRequest {
|
||||
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 100}];
|
||||
}
|
||||
|
||||
message GetSMTPConfigByIdResponse {
|
||||
zitadel.settings.v1.SMTPConfig smtp_config = 1;
|
||||
}
|
||||
|
||||
message ListSMTPConfigsRequest {
|
||||
zitadel.v1.ListQuery query = 1;
|
||||
}
|
||||
|
||||
message ListSMTPConfigsResponse {
|
||||
zitadel.v1.ListDetails details = 1;
|
||||
repeated zitadel.settings.v1.SMTPConfig result = 2;
|
||||
}
|
||||
|
||||
message AddSMTPConfigRequest {
|
||||
string sender_address = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
@ -4051,7 +4135,15 @@ message AddSMTPConfigRequest {
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"replyto@m.zitadel.cloud\"";
|
||||
min_length: 1;
|
||||
min_length: 0;
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
string description = 8 [
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"provider description\"";
|
||||
min_length: 0;
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
@ -4059,6 +4151,7 @@ message AddSMTPConfigRequest {
|
||||
|
||||
message AddSMTPConfigResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message UpdateSMTPConfigRequest {
|
||||
@ -4104,6 +4197,20 @@ message UpdateSMTPConfigRequest {
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
string password = 7 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"this-is-my-password\"";
|
||||
}
|
||||
];
|
||||
string description = 8 [
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"provider description\"";
|
||||
min_length: 1;
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
string id = 9 [(validate.rules).string = {min_len: 1, max_len: 100}];
|
||||
}
|
||||
|
||||
message UpdateSMTPConfigResponse {
|
||||
@ -4116,14 +4223,32 @@ message UpdateSMTPConfigPasswordRequest {
|
||||
example: "\"this-is-my-updated-password\"";
|
||||
}
|
||||
];
|
||||
string id = 2 [(validate.rules).string = {min_len: 1, max_len: 100}];
|
||||
}
|
||||
|
||||
message UpdateSMTPConfigPasswordResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
//this is an empty request
|
||||
message RemoveSMTPConfigRequest {}
|
||||
message ActivateSMTPConfigRequest {
|
||||
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
}
|
||||
|
||||
message ActivateSMTPConfigResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
message DeactivateSMTPConfigRequest {
|
||||
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
}
|
||||
|
||||
message DeactivateSMTPConfigResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
message RemoveSMTPConfigRequest {
|
||||
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 100}];
|
||||
}
|
||||
|
||||
message RemoveSMTPConfigResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
|
@ -40,6 +40,12 @@ message SecretGeneratorTypeQuery {
|
||||
SecretGeneratorType generator_type = 1;
|
||||
}
|
||||
|
||||
enum SMTPConfigState {
|
||||
SMTP_CONFIG_STATE_UNSPECIFIED = 0;
|
||||
SMTP_CONFIG_ACTIVE = 1;
|
||||
SMTP_CONFIG_INACTIVE = 2;
|
||||
}
|
||||
|
||||
enum SecretGeneratorType {
|
||||
SECRET_GENERATOR_TYPE_UNSPECIFIED = 0;
|
||||
SECRET_GENERATOR_TYPE_INIT_CODE = 1;
|
||||
@ -80,6 +86,13 @@ message SMTPConfig {
|
||||
example: "\"replyto@m.zitadel.cloud\"";
|
||||
}
|
||||
];
|
||||
SMTPConfigState state = 8;
|
||||
string description = 9 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"Mailjet\"";
|
||||
}
|
||||
];
|
||||
string id = 10;
|
||||
}
|
||||
|
||||
message SMSProvider {
|
||||
|