mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 02:07:24 +00:00
fix: add smtp config, remove smtp and sms provider, console adaptations (#3792)
* fix: add AddSMTPConfig to admin api * addsmtpconfig * fix: add RemoveSMTPConfig and RemoveSMSProvider to admin api * update twilio, token fcn * fix account switcher, twilio token set, cleanup dialog * cleanup * buttons Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
parent
ab7651fe26
commit
3500961fbb
@ -44,7 +44,6 @@
|
|||||||
>{{ 'USER.STATE.' + session.authState | translate }}</span
|
>{{ 'USER.STATE.' + session.authState | translate }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<span class="fill-space"></span>
|
|
||||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a class="row" (click)="selectNewAccount()">
|
<a class="row" (click)="selectNewAccount()">
|
||||||
@ -54,7 +53,6 @@
|
|||||||
<span class="col">
|
<span class="col">
|
||||||
<span class="user-title">{{ 'USER.ADDACCOUNT' | translate }}</span>
|
<span class="user-title">{{ 'USER.ADDACCOUNT' | translate }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="fill-space"></span>
|
|
||||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,6 +109,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
.user-title {
|
.user-title {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@ -123,11 +124,14 @@
|
|||||||
.loginname {
|
.loginname {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
|
white-space: nowrap;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loginname {
|
.loginname {
|
||||||
color: $secondary-text;
|
color: $secondary-text;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.state {
|
.state {
|
||||||
@ -136,10 +140,6 @@
|
|||||||
padding: 1px 0.5rem;
|
padding: 1px 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fill-space {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,7 @@
|
|||||||
<span>{{ provider === SMSProviderType.Twilio ? 'Twilio' : ('SETTING.SMS.ADDPROVIDER' | translate) }}</span>
|
<span>{{ provider === SMSProviderType.Twilio ? 'Twilio' : ('SETTING.SMS.ADDPROVIDER' | translate) }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<!-- <p class="desc cnsl-secondary-text">{{ 'SETTING.SMS.ADDPROVIDERDESCRIPTION' | translate }}</p> -->
|
|
||||||
|
|
||||||
<!-- <cnsl-form-field class="form-field" label="Access Code" required="true">
|
|
||||||
<cnsl-label>{{ 'MFA.TYPE' | translate }}</cnsl-label>
|
|
||||||
<mat-select [(ngModel)]="provider">
|
|
||||||
<mat-option *ngFor="let prov of availableSMSProviders" [value]="prov">
|
|
||||||
<span *ngIf="prov === SMSProviderType.Twilio">Twilio</span>
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</cnsl-form-field> -->
|
|
||||||
|
|
||||||
<form *ngIf="provider === SMSProviderType.Twilio" (ngSubmit)="closeDialogWithRequest()" [formGroup]="twilioForm">
|
<form *ngIf="provider === SMSProviderType.Twilio" (ngSubmit)="closeDialogWithRequest()" [formGroup]="twilioForm">
|
||||||
<!-- <h2>Twilio</h2> -->
|
|
||||||
|
|
||||||
<cnsl-form-field class="sms-form-field" label="sid">
|
<cnsl-form-field class="sms-form-field" label="sid">
|
||||||
<cnsl-label>{{ 'SETTING.SMS.TWILIO.SID' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'SETTING.SMS.TWILIO.SID' | translate }}</cnsl-label>
|
||||||
<input cnslInput name="sid" formControlName="sid" />
|
<input cnslInput name="sid" formControlName="sid" />
|
||||||
@ -30,6 +17,10 @@
|
|||||||
<cnsl-label>{{ 'SETTING.SMS.TWILIO.SENDERNUMBER' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'SETTING.SMS.TWILIO.SENDERNUMBER' | translate }}</cnsl-label>
|
||||||
<input cnslInput name="senderNumber" formControlName="senderNumber" />
|
<input cnslInput name="senderNumber" formControlName="senderNumber" />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
|
<button *ngIf="twilio" type="button" mat-stroked-button (click)="changeToken()">
|
||||||
|
{{ 'SETTING.SMS.TWILIO.CHANGETOKEN' | translate }}
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { AddSMSProviderTwilioRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
import {
|
||||||
|
AddSMSProviderTwilioRequest,
|
||||||
|
UpdateSMSProviderTwilioRequest,
|
||||||
|
UpdateSMSProviderTwilioTokenRequest,
|
||||||
|
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||||
|
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';
|
||||||
|
|
||||||
enum SMSProviderType {
|
enum SMSProviderType {
|
||||||
Twilio = 1,
|
Twilio = 1,
|
||||||
@ -16,13 +25,18 @@ export class DialogAddSMSProviderComponent {
|
|||||||
public SMSProviderType: any = SMSProviderType;
|
public SMSProviderType: any = SMSProviderType;
|
||||||
public availableSMSProviders: SMSProviderType[] = [SMSProviderType.Twilio];
|
public availableSMSProviders: SMSProviderType[] = [SMSProviderType.Twilio];
|
||||||
public provider: SMSProviderType = SMSProviderType.Twilio;
|
public provider: SMSProviderType = SMSProviderType.Twilio;
|
||||||
public req: AddSMSProviderTwilioRequest = new AddSMSProviderTwilioRequest();
|
public req!: AddSMSProviderTwilioRequest | UpdateSMSProviderTwilioRequest;
|
||||||
|
|
||||||
public twilioForm!: FormGroup;
|
public twilioForm!: FormGroup;
|
||||||
|
|
||||||
|
private smsProviders: SMSProvider.AsObject[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
|
private service: AdminService,
|
||||||
public dialogRef: MatDialogRef<DialogAddSMSProviderComponent>,
|
public dialogRef: MatDialogRef<DialogAddSMSProviderComponent>,
|
||||||
|
private toast: ToastService,
|
||||||
|
private dialog: MatDialog,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
) {
|
) {
|
||||||
this.twilioForm = this.fb.group({
|
this.twilioForm = this.fb.group({
|
||||||
@ -30,6 +44,11 @@ export class DialogAddSMSProviderComponent {
|
|||||||
token: ['', [Validators.required]],
|
token: ['', [Validators.required]],
|
||||||
senderNumber: ['', [Validators.required]],
|
senderNumber: ['', [Validators.required]],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.smsProviders = data.smsProviders;
|
||||||
|
if (!!this.twilio) {
|
||||||
|
this.twilioForm.patchValue(this.twilio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
@ -37,12 +56,47 @@ export class DialogAddSMSProviderComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public closeDialogWithRequest(): void {
|
public closeDialogWithRequest(): void {
|
||||||
|
if (!!this.twilio) {
|
||||||
|
this.req = new UpdateSMSProviderTwilioRequest();
|
||||||
|
|
||||||
|
this.req.setSid(this.sid?.value);
|
||||||
|
this.req.setSenderNumber(this.senderNumber?.value);
|
||||||
|
this.dialogRef.close(this.req);
|
||||||
|
} else {
|
||||||
|
this.req = new AddSMSProviderTwilioRequest();
|
||||||
|
|
||||||
this.req.setSid(this.sid?.value);
|
this.req.setSid(this.sid?.value);
|
||||||
this.req.setToken(this.token?.value);
|
this.req.setToken(this.token?.value);
|
||||||
this.req.setSenderNumber(this.senderNumber?.value);
|
this.req.setSenderNumber(this.senderNumber?.value);
|
||||||
|
|
||||||
this.dialogRef.close(this.req);
|
this.dialogRef.close(this.req);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeToken(): void {
|
||||||
|
const dialogRef = this.dialog.open(PasswordDialogComponent, {
|
||||||
|
width: '400px',
|
||||||
|
data: {
|
||||||
|
i18nTitle: 'SETTING.SMS.TWILIO.SETTOKEN',
|
||||||
|
i18nLabel: 'SETTING.SMS.TWILIO.TOKEN',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((token: string) => {
|
||||||
|
if (token) {
|
||||||
|
const tokenReq = new UpdateSMSProviderTwilioTokenRequest();
|
||||||
|
tokenReq.setToken(token);
|
||||||
|
|
||||||
|
this.service
|
||||||
|
.updateSMSProviderTwilioToken(tokenReq)
|
||||||
|
.then(() => {
|
||||||
|
this.toast.showInfo('SETTING.SMS.TWILIO.TOKENSET', true);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public get senderNumber(): AbstractControl | null {
|
public get senderNumber(): AbstractControl | null {
|
||||||
return this.twilioForm.get('senderNumber');
|
return this.twilioForm.get('senderNumber');
|
||||||
@ -55,4 +109,13 @@ export class DialogAddSMSProviderComponent {
|
|||||||
public get sid(): AbstractControl | null {
|
public get sid(): AbstractControl | null {
|
||||||
return this.twilioForm.get('sid');
|
return this.twilioForm.get('sid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get twilio(): TwilioConfig.AsObject | undefined {
|
||||||
|
const twilioProvider: SMSProvider.AsObject | undefined = this.smsProviders.find((p) => p.twilio);
|
||||||
|
if (twilioProvider && !!twilioProvider.twilio) {
|
||||||
|
return twilioProvider.twilio;
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,9 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="set-password-btn"
|
class="set-password-btn"
|
||||||
[disabled]="(['iam.write'] | hasRole | async) === false"
|
[disabled]="(['iam.write'] | hasRole | async) === false || !hasSMTPConfig"
|
||||||
(click)="setSMTPPassword()"
|
(click)="setSMTPPassword()"
|
||||||
|
type="button"
|
||||||
mat-stroked-button
|
mat-stroked-button
|
||||||
>
|
>
|
||||||
{{ 'SETTING.SMTP.SETPASSWORD' | translate }}
|
{{ 'SETTING.SMTP.SETPASSWORD' | translate }}
|
||||||
@ -77,7 +78,7 @@
|
|||||||
></span>
|
></span>
|
||||||
|
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<button [disabled]="(['iam.write'] | hasRole | async) === false" mat-icon-button (click)="addSMSProvider()">
|
<button [disabled]="(['iam.write'] | hasRole | async) === false" mat-icon-button (click)="editSMSProvider()">
|
||||||
<i class="las la-pen"></i>
|
<i class="las la-pen"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,6 +4,8 @@ import { MatDialog } from '@angular/material/dialog';
|
|||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
AddSMSProviderTwilioRequest,
|
AddSMSProviderTwilioRequest,
|
||||||
|
AddSMTPConfigRequest,
|
||||||
|
UpdateSMSProviderTwilioRequest,
|
||||||
UpdateSMTPConfigPasswordRequest,
|
UpdateSMTPConfigPasswordRequest,
|
||||||
UpdateSMTPConfigPasswordResponse,
|
UpdateSMTPConfigPasswordResponse,
|
||||||
UpdateSMTPConfigRequest,
|
UpdateSMTPConfigRequest,
|
||||||
@ -16,7 +18,7 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||||
import { DialogAddSMSProviderComponent } from './dialog-add-sms-provider/dialog-add-sms-provider.component';
|
import { DialogAddSMSProviderComponent } from './dialog-add-sms-provider/dialog-add-sms-provider.component';
|
||||||
import { SMTPPasswordDialogComponent } from './smtp-password-dialog/smtp-password-dialog.component';
|
import { PasswordDialogComponent } from './password-dialog/password-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-notification-settings',
|
selector: 'cnsl-notification-settings',
|
||||||
@ -39,6 +41,8 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
public SMSProviderConfigState: any = SMSProviderConfigState;
|
public SMSProviderConfigState: any = SMSProviderConfigState;
|
||||||
public InfoSectionType: any = InfoSectionType;
|
public InfoSectionType: any = InfoSectionType;
|
||||||
|
|
||||||
|
public hasSMTPConfig: boolean = false;
|
||||||
|
|
||||||
// show available providers
|
// show available providers
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -76,6 +80,7 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
.then((smtpConfig) => {
|
.then((smtpConfig) => {
|
||||||
this.smtpLoading = false;
|
this.smtpLoading = false;
|
||||||
if (smtpConfig.smtpConfig) {
|
if (smtpConfig.smtpConfig) {
|
||||||
|
this.hasSMTPConfig = true;
|
||||||
this.form.patchValue(smtpConfig.smtpConfig);
|
this.form.patchValue(smtpConfig.smtpConfig);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -83,6 +88,7 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
this.smtpLoading = false;
|
this.smtpLoading = false;
|
||||||
if (error && error.code === 5) {
|
if (error && error.code === 5) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
this.hasSMTPConfig = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -109,9 +115,8 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
this.logNotificationProvider = logNotificationProvider.provider;
|
this.logNotificationProvider = logNotificationProvider.provider;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(() => {
|
||||||
this.logProviderLoading = false;
|
this.logProviderLoading = false;
|
||||||
this.toast.showError(error);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.fileProviderLoading = true;
|
this.fileProviderLoading = true;
|
||||||
@ -123,13 +128,13 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
this.fileNotificationProvider = fileNotificationProvider.provider;
|
this.fileNotificationProvider = fileNotificationProvider.provider;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(() => {
|
||||||
this.fileProviderLoading = false;
|
this.fileProviderLoading = false;
|
||||||
this.toast.showError(error);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateData(): Promise<UpdateSMTPConfigPasswordResponse.AsObject> | any {
|
private updateData(): Promise<UpdateSMTPConfigPasswordResponse.AsObject> | any {
|
||||||
|
if (this.hasSMTPConfig) {
|
||||||
const req = new UpdateSMTPConfigRequest();
|
const req = new UpdateSMTPConfigRequest();
|
||||||
req.setHost(this.host?.value ?? '');
|
req.setHost(this.host?.value ?? '');
|
||||||
req.setSenderAddress(this.senderAddress?.value ?? '');
|
req.setSenderAddress(this.senderAddress?.value ?? '');
|
||||||
@ -140,6 +145,18 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
return this.service.updateSMTPConfig(req).catch((error) => {
|
return this.service.updateSMTPConfig(req).catch((error) => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const req = new AddSMTPConfigRequest();
|
||||||
|
req.setHost(this.host?.value ?? '');
|
||||||
|
req.setSenderAddress(this.senderAddress?.value ?? '');
|
||||||
|
req.setSenderName(this.senderName?.value ?? '');
|
||||||
|
req.setTls(this.tls?.value ?? false);
|
||||||
|
req.setUser(this.user?.value ?? '');
|
||||||
|
|
||||||
|
return this.service.addSMTPConfig(req).catch((error) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public savePolicy(): void {
|
public savePolicy(): void {
|
||||||
@ -158,15 +175,28 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public addSMSProvider(): void {
|
public editSMSProvider(): void {
|
||||||
const dialogRef = this.dialog.open(DialogAddSMSProviderComponent, {
|
const dialogRef = this.dialog.open(DialogAddSMSProviderComponent, {
|
||||||
width: '400px',
|
width: '400px',
|
||||||
|
data: {
|
||||||
|
smsProviders: this.smsProviders,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((req: AddSMSProviderTwilioRequest) => {
|
dialogRef.afterClosed().subscribe((req: AddSMSProviderTwilioRequest | UpdateSMSProviderTwilioRequest) => {
|
||||||
if (req) {
|
if (req) {
|
||||||
|
if (this.hasTwilio) {
|
||||||
this.service
|
this.service
|
||||||
.addSMSProviderTwilio(req)
|
.updateSMSProviderTwilio(req as UpdateSMSProviderTwilioRequest)
|
||||||
|
.then(() => {
|
||||||
|
this.toast.showInfo('SETTING.SMS.TWILIO.ADDED', true);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.service
|
||||||
|
.addSMSProviderTwilio(req as AddSMSProviderTwilioRequest)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.toast.showInfo('SETTING.SMS.TWILIO.ADDED', true);
|
this.toast.showInfo('SETTING.SMS.TWILIO.ADDED', true);
|
||||||
})
|
})
|
||||||
@ -174,12 +204,17 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSMTPPassword(): void {
|
public setSMTPPassword(): void {
|
||||||
const dialogRef = this.dialog.open(SMTPPasswordDialogComponent, {
|
const dialogRef = this.dialog.open(PasswordDialogComponent, {
|
||||||
width: '400px',
|
width: '400px',
|
||||||
|
data: {
|
||||||
|
i18nTitle: 'SETTING.SMTP.SETPASSWORD',
|
||||||
|
i18nLabel: 'SETTING.SMTP.PASSWORD',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((password: string) => {
|
dialogRef.afterClosed().subscribe((password: string) => {
|
||||||
@ -222,4 +257,13 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
public get host(): AbstractControl | null {
|
public get host(): AbstractControl | null {
|
||||||
return this.form.get('host');
|
return this.form.get('host');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get hasTwilio(): boolean {
|
||||||
|
const twilioProvider: SMSProvider.AsObject | undefined = this.smsProviders.find((p) => p.twilio);
|
||||||
|
if (twilioProvider && !!twilioProvider.twilio) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@ import { InfoSectionModule } from '../../info-section/info-section.module';
|
|||||||
import { InputModule } from '../../input/input.module';
|
import { InputModule } from '../../input/input.module';
|
||||||
import { DialogAddSMSProviderComponent } from './dialog-add-sms-provider/dialog-add-sms-provider.component';
|
import { DialogAddSMSProviderComponent } from './dialog-add-sms-provider/dialog-add-sms-provider.component';
|
||||||
import { NotificationSettingsComponent } from './notification-settings.component';
|
import { NotificationSettingsComponent } from './notification-settings.component';
|
||||||
import { SMTPPasswordDialogComponent } from './smtp-password-dialog/smtp-password-dialog.component';
|
import { PasswordDialogComponent } from './password-dialog/password-dialog.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [NotificationSettingsComponent, DialogAddSMSProviderComponent, SMTPPasswordDialogComponent],
|
declarations: [NotificationSettingsComponent, DialogAddSMSProviderComponent, PasswordDialogComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
CardModule,
|
CardModule,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<h1 mat-dialog-title>
|
<h1 mat-dialog-title>
|
||||||
<span>{{ 'SETTING.SMTP.SETPASSWORD' | translate }} {{ data?.number }}</span>
|
<span>{{ data.i18nTitle | translate }} {{ data?.number }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'SETTING.SMTP.PASSWORD' | translate }}</cnsl-label>
|
<cnsl-label>{{ data.i18nLabel | translate }}</cnsl-label>
|
||||||
<input cnslInput [(ngModel)]="password" />
|
<input cnslInput [(ngModel)]="password" />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
@ -1,19 +1,19 @@
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { SMTPPasswordDialogComponent } from './smtp-password-dialog.component';
|
import { PasswordDialogComponent } from './password-dialog.component';
|
||||||
|
|
||||||
describe('CodeDialogComponent', () => {
|
describe('PasswordDialogComponent', () => {
|
||||||
let component: SMTPPasswordDialogComponent;
|
let component: PasswordDialogComponent;
|
||||||
let fixture: ComponentFixture<SMTPPasswordDialogComponent>;
|
let fixture: ComponentFixture<PasswordDialogComponent>;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [SMTPPasswordDialogComponent],
|
declarations: [PasswordDialogComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(SMTPPasswordDialogComponent);
|
fixture = TestBed.createComponent(PasswordDialogComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
@ -0,0 +1,16 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'cnsl-password-dialog',
|
||||||
|
templateUrl: './password-dialog.component.html',
|
||||||
|
styleUrls: ['./password-dialog.component.scss'],
|
||||||
|
})
|
||||||
|
export class PasswordDialogComponent {
|
||||||
|
public password: string = '';
|
||||||
|
constructor(public dialogRef: MatDialogRef<PasswordDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {}
|
||||||
|
|
||||||
|
closeDialog(password: string = ''): void {
|
||||||
|
this.dialogRef.close(password);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cnsl-smtp-password-dialog',
|
|
||||||
templateUrl: './smtp-password-dialog.component.html',
|
|
||||||
styleUrls: ['./smtp-password-dialog.component.scss'],
|
|
||||||
})
|
|
||||||
export class SMTPPasswordDialogComponent {
|
|
||||||
public password: string = '';
|
|
||||||
constructor(public dialogRef: MatDialogRef<SMTPPasswordDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {}
|
|
||||||
|
|
||||||
closeDialog(password: string = ''): void {
|
|
||||||
this.dialogRef.close(password);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,6 +19,8 @@ import {
|
|||||||
AddSecondFactorToLoginPolicyResponse,
|
AddSecondFactorToLoginPolicyResponse,
|
||||||
AddSMSProviderTwilioRequest,
|
AddSMSProviderTwilioRequest,
|
||||||
AddSMSProviderTwilioResponse,
|
AddSMSProviderTwilioResponse,
|
||||||
|
AddSMTPConfigRequest,
|
||||||
|
AddSMTPConfigResponse,
|
||||||
DeactivateIDPRequest,
|
DeactivateIDPRequest,
|
||||||
DeactivateIDPResponse,
|
DeactivateIDPResponse,
|
||||||
GetCustomDomainClaimedMessageTextRequest,
|
GetCustomDomainClaimedMessageTextRequest,
|
||||||
@ -180,6 +182,10 @@ import {
|
|||||||
UpdatePrivacyPolicyResponse,
|
UpdatePrivacyPolicyResponse,
|
||||||
UpdateSecretGeneratorRequest,
|
UpdateSecretGeneratorRequest,
|
||||||
UpdateSecretGeneratorResponse,
|
UpdateSecretGeneratorResponse,
|
||||||
|
UpdateSMSProviderTwilioRequest,
|
||||||
|
UpdateSMSProviderTwilioResponse,
|
||||||
|
UpdateSMSProviderTwilioTokenRequest,
|
||||||
|
UpdateSMSProviderTwilioTokenResponse,
|
||||||
UpdateSMTPConfigPasswordRequest,
|
UpdateSMTPConfigPasswordRequest,
|
||||||
UpdateSMTPConfigPasswordResponse,
|
UpdateSMTPConfigPasswordResponse,
|
||||||
UpdateSMTPConfigRequest,
|
UpdateSMTPConfigRequest,
|
||||||
@ -466,6 +472,10 @@ export class AdminService {
|
|||||||
return this.grpcService.admin.getSMTPConfig(req, null).then((resp) => resp.toObject());
|
return this.grpcService.admin.getSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addSMTPConfig(req: AddSMTPConfigRequest): Promise<AddSMTPConfigResponse.AsObject> {
|
||||||
|
return this.grpcService.admin.addSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
public updateSMTPConfig(req: UpdateSMTPConfigRequest): Promise<UpdateSMTPConfigResponse.AsObject> {
|
public updateSMTPConfig(req: UpdateSMTPConfigRequest): Promise<UpdateSMTPConfigResponse.AsObject> {
|
||||||
return this.grpcService.admin.updateSMTPConfig(req, null).then((resp) => resp.toObject());
|
return this.grpcService.admin.updateSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||||
}
|
}
|
||||||
@ -490,6 +500,16 @@ export class AdminService {
|
|||||||
return this.grpcService.admin.addSMSProviderTwilio(req, null).then((resp) => resp.toObject());
|
return this.grpcService.admin.addSMSProviderTwilio(req, null).then((resp) => resp.toObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateSMSProviderTwilio(req: UpdateSMSProviderTwilioRequest): Promise<UpdateSMSProviderTwilioResponse.AsObject> {
|
||||||
|
return this.grpcService.admin.updateSMSProviderTwilio(req, null).then((resp) => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateSMSProviderTwilioToken(
|
||||||
|
req: UpdateSMSProviderTwilioTokenRequest,
|
||||||
|
): Promise<UpdateSMSProviderTwilioTokenResponse.AsObject> {
|
||||||
|
return this.grpcService.admin.updateSMSProviderTwilioToken(req, null).then((resp) => resp.toObject());
|
||||||
|
}
|
||||||
|
|
||||||
/* lockout */
|
/* lockout */
|
||||||
|
|
||||||
public getLockoutPolicy(): Promise<GetLockoutPolicyResponse.AsObject> {
|
public getLockoutPolicy(): Promise<GetLockoutPolicyResponse.AsObject> {
|
||||||
|
@ -886,7 +886,10 @@
|
|||||||
"SID": "Sid",
|
"SID": "Sid",
|
||||||
"TOKEN": "Token",
|
"TOKEN": "Token",
|
||||||
"SENDERNUMBER": "Sender Number",
|
"SENDERNUMBER": "Sender Number",
|
||||||
"ADDED": "Twilio erfolgreich hinzugefügt."
|
"ADDED": "Twilio erfolgreich hinzugefügt.",
|
||||||
|
"CHANGETOKEN": "Token ändern",
|
||||||
|
"SETTOKEN": "Token setzen",
|
||||||
|
"TOKENSET": "Token erfolgreich gesetzt."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
|
@ -886,7 +886,10 @@
|
|||||||
"SID": "Sid",
|
"SID": "Sid",
|
||||||
"TOKEN": "Token",
|
"TOKEN": "Token",
|
||||||
"SENDERNUMBER": "Sender Number",
|
"SENDERNUMBER": "Sender Number",
|
||||||
"ADDED": "Twilio added successfully."
|
"ADDED": "Twilio added successfully.",
|
||||||
|
"CHANGETOKEN": "Change Token",
|
||||||
|
"SETTOKEN": "Set Token",
|
||||||
|
"TOKENSET": "Token successfully set."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
|
@ -886,7 +886,10 @@
|
|||||||
"SID": "Sid",
|
"SID": "Sid",
|
||||||
"TOKEN": "Token",
|
"TOKEN": "Token",
|
||||||
"SENDERNUMBER": "Sender Number",
|
"SENDERNUMBER": "Sender Number",
|
||||||
"ADDED": "Twilio aggiunto con successo."
|
"ADDED": "Twilio aggiunto con successo.",
|
||||||
|
"CHANGETOKEN": "Cambia Token",
|
||||||
|
"SETTOKEN": "Cambia Token",
|
||||||
|
"TOKENSET": "Token cambiato con successo."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
|
@ -116,6 +116,18 @@ Get system smtp configuration
|
|||||||
GET: /smtp
|
GET: /smtp
|
||||||
|
|
||||||
|
|
||||||
|
### AddSMTPConfig
|
||||||
|
|
||||||
|
> **rpc** AddSMTPConfig([AddSMTPConfigRequest](#addsmtpconfigrequest))
|
||||||
|
[AddSMTPConfigResponse](#addsmtpconfigresponse)
|
||||||
|
|
||||||
|
Add system smtp configuration
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
POST: /smtp
|
||||||
|
|
||||||
|
|
||||||
### UpdateSMTPConfig
|
### UpdateSMTPConfig
|
||||||
|
|
||||||
> **rpc** UpdateSMTPConfig([UpdateSMTPConfigRequest](#updatesmtpconfigrequest))
|
> **rpc** UpdateSMTPConfig([UpdateSMTPConfigRequest](#updatesmtpconfigrequest))
|
||||||
@ -140,6 +152,18 @@ Update system smtp configuration password for host
|
|||||||
PUT: /smtp/password
|
PUT: /smtp/password
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveSMTPConfig
|
||||||
|
|
||||||
|
> **rpc** RemoveSMTPConfig([RemoveSMTPConfigRequest](#removesmtpconfigrequest))
|
||||||
|
[RemoveSMTPConfigResponse](#removesmtpconfigresponse)
|
||||||
|
|
||||||
|
Remove system smtp configuration
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DELETE: /smtp
|
||||||
|
|
||||||
|
|
||||||
### ListSMSProviders
|
### ListSMSProviders
|
||||||
|
|
||||||
> **rpc** ListSMSProviders([ListSMSProvidersRequest](#listsmsprovidersrequest))
|
> **rpc** ListSMSProviders([ListSMSProvidersRequest](#listsmsprovidersrequest))
|
||||||
@ -200,6 +224,18 @@ Update twilio sms provider token
|
|||||||
PUT: /sms/twilio/{id}/token
|
PUT: /sms/twilio/{id}/token
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveSMSProvider
|
||||||
|
|
||||||
|
> **rpc** RemoveSMSProvider([RemoveSMSProviderRequest](#removesmsproviderrequest))
|
||||||
|
[RemoveSMSProviderResponse](#removesmsproviderresponse)
|
||||||
|
|
||||||
|
Remove sms provider token
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DELETE: /sms/{id}
|
||||||
|
|
||||||
|
|
||||||
### GetOIDCSettings
|
### GetOIDCSettings
|
||||||
|
|
||||||
> **rpc** GetOIDCSettings([GetOIDCSettingsRequest](#getoidcsettingsrequest))
|
> **rpc** GetOIDCSettings([GetOIDCSettingsRequest](#getoidcsettingsrequest))
|
||||||
@ -1646,6 +1682,33 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### AddSMTPConfigRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| sender_address | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| sender_name | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| tls | bool | - | |
|
||||||
|
| host | string | - | string.min_len: 1<br /> string.max_len: 500<br /> |
|
||||||
|
| user | string | - | |
|
||||||
|
| password | string | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### AddSMTPConfigResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### AddSecondFactorToLoginPolicyRequest
|
### AddSecondFactorToLoginPolicyRequest
|
||||||
|
|
||||||
|
|
||||||
@ -2941,6 +3004,45 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveSMSProviderRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveSMSProviderResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveSMTPConfigRequest
|
||||||
|
this is en empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### RemoveSMTPConfigResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### RemoveSecondFactorFromLoginPolicyRequest
|
### RemoveSecondFactorFromLoginPolicyRequest
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,6 +55,19 @@ func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigR
|
|||||||
}, nil
|
}, 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) {
|
func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) {
|
||||||
details, err := s.command.ChangeSMTPConfig(ctx, UpdateSMTPToConfig(req))
|
details, err := s.command.ChangeSMTPConfig(ctx, UpdateSMTPToConfig(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -68,6 +81,19 @@ func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPC
|
|||||||
}, nil
|
}, 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) {
|
func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) {
|
||||||
details, err := s.command.ChangeSMTPConfigPassword(ctx, req.Password)
|
details, err := s.command.ChangeSMTPConfigPassword(ctx, req.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
|
||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||||
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
@ -113,6 +113,19 @@ func SecretGeneratorTypeToDomain(generatorType settings_pb.SecretGeneratorType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddSMTPToConfig(req *admin_pb.AddSMTPConfigRequest) *smtp.EmailConfig {
|
||||||
|
return &smtp.EmailConfig{
|
||||||
|
Tls: req.Tls,
|
||||||
|
From: req.SenderAddress,
|
||||||
|
FromName: req.SenderName,
|
||||||
|
SMTP: smtp.SMTP{
|
||||||
|
Host: req.Host,
|
||||||
|
User: req.User,
|
||||||
|
Password: req.Password,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func UpdateSMTPToConfig(req *admin_pb.UpdateSMTPConfigRequest) *smtp.EmailConfig {
|
func UpdateSMTPToConfig(req *admin_pb.UpdateSMTPConfigRequest) *smtp.EmailConfig {
|
||||||
return &smtp.EmailConfig{
|
return &smtp.EmailConfig{
|
||||||
Tls: req.Tls,
|
Tls: req.Tls,
|
||||||
|
@ -73,3 +73,14 @@ func (s *Server) UpdateSMSProviderTwilioToken(ctx context.Context, req *admin_pb
|
|||||||
Details: object.DomainToChangeDetailsPb(result),
|
Details: object.DomainToChangeDetailsPb(result),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveSMSProvider(ctx context.Context, req *admin_pb.RemoveSMSProviderRequest) (*admin_pb.RemoveSMSProviderResponse, error) {
|
||||||
|
result, err := s.command.RemoveSMSConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
|
||||||
|
}
|
||||||
|
return &admin_pb.RemoveSMSProviderResponse{
|
||||||
|
Details: object.DomainToAddDetailsPb(result),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -82,6 +82,14 @@ func (wm *InstanceSMTPConfigWriteModel) Reduce() error {
|
|||||||
if e.User != nil {
|
if e.User != nil {
|
||||||
wm.User = *e.User
|
wm.User = *e.User
|
||||||
}
|
}
|
||||||
|
case *instance.SMTPConfigRemovedEvent:
|
||||||
|
wm.State = domain.SMTPConfigStateRemoved
|
||||||
|
wm.TLS = false
|
||||||
|
wm.SenderName = ""
|
||||||
|
wm.SenderAddress = ""
|
||||||
|
wm.Host = ""
|
||||||
|
wm.User = ""
|
||||||
|
wm.Password = nil
|
||||||
case *instance.DomainAddedEvent:
|
case *instance.DomainAddedEvent:
|
||||||
wm.domainState = domain.InstanceDomainStateActive
|
wm.domainState = domain.InstanceDomainStateActive
|
||||||
case *instance.DomainRemovedEvent:
|
case *instance.DomainRemovedEvent:
|
||||||
|
@ -170,7 +170,7 @@ func (c *Commands) DeactivateSMSConfigTwilio(ctx context.Context, instanceID, id
|
|||||||
return writeModelToObjectDetails(&smsConfigWriteModel.WriteModel), nil
|
return writeModelToObjectDetails(&smsConfigWriteModel.WriteModel), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) RemoveSMSConfigTwilio(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
|
func (c *Commands) RemoveSMSConfig(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "SMS-3j9fs", "Errors.IDMissing")
|
return nil, caos_errs.ThrowInvalidArgument(nil, "SMS-3j9fs", "Errors.IDMissing")
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ func (c *Commands) RemoveSMSConfigTwilio(ctx context.Context, instanceID, id str
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !smsConfigWriteModel.State.Exists() || smsConfigWriteModel.Twilio == nil {
|
if !smsConfigWriteModel.State.Exists() {
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-sn9we", "Errors.SMSConfig.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-sn9we", "Errors.SMSConfig.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,7 +496,7 @@ func TestCommandSide_DeactivateSMSConfigTwilio(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommandSide_RemoveSMSConfigTwilio(t *testing.T) {
|
func TestCommandSide_RemoveSMSConfig(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
}
|
}
|
||||||
@ -547,7 +547,7 @@ func TestCommandSide_RemoveSMSConfigTwilio(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "sms config twilio remove, ok",
|
name: "sms config remove, ok",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
eventstore: eventstoreExpect(
|
eventstore: eventstoreExpect(
|
||||||
t,
|
t,
|
||||||
@ -593,7 +593,7 @@ func TestCommandSide_RemoveSMSConfigTwilio(t *testing.T) {
|
|||||||
r := &Commands{
|
r := &Commands{
|
||||||
eventstore: tt.fields.eventstore,
|
eventstore: tt.fields.eventstore,
|
||||||
}
|
}
|
||||||
got, err := r.RemoveSMSConfigTwilio(tt.args.ctx, tt.args.instanceID, tt.args.id)
|
got, err := r.RemoveSMSConfig(tt.args.ctx, tt.args.instanceID, tt.args.id)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,24 @@ func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string
|
|||||||
}, nil
|
}, 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)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
events, err := c.eventstore.Push(ctx, cmds...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &domain.ObjectDetails{
|
||||||
|
Sequence: events[len(events)-1].Sequence(),
|
||||||
|
EventDate: events[len(events)-1].CreationDate(),
|
||||||
|
ResourceOwner: events[len(events)-1].Aggregate().InstanceID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, host, user string, password []byte, tls bool) preparation.Validation {
|
func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, host, user string, password []byte, tls bool) preparation.Validation {
|
||||||
return func() (preparation.CreateCommands, error) {
|
return func() (preparation.CreateCommands, error) {
|
||||||
if from = strings.TrimSpace(from); from == "" {
|
if from = strings.TrimSpace(from); from == "" {
|
||||||
@ -171,6 +189,23 @@ func (c *Commands) prepareChangeSMTPConfig(a *instance.Aggregate, from, name, ho
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, errors.ThrowNotFound(nil, "INST-Sfefg", "Errors.SMTPConfig.NotFound")
|
||||||
|
}
|
||||||
|
return []eventstore.Command{
|
||||||
|
instance.NewSMTPConfigRemovedEvent(ctx, &a.Aggregate),
|
||||||
|
}, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func checkSenderAddress(writeModel *InstanceSMTPConfigWriteModel) error {
|
func checkSenderAddress(writeModel *InstanceSMTPConfigWriteModel) error {
|
||||||
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
|
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
|
||||||
return nil
|
return nil
|
||||||
|
@ -554,6 +554,101 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
alg crypto.EncryptionAlgorithm
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "smtp config, error not found",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsNotFound,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove smtp config, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
instance.NewSMTPConfigAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||||
|
true,
|
||||||
|
"from",
|
||||||
|
"name",
|
||||||
|
"host",
|
||||||
|
"user",
|
||||||
|
&crypto.CryptoValue{},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusherWithInstanceID(
|
||||||
|
"INSTANCE",
|
||||||
|
instance.NewSMTPConfigRemovedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||||
|
},
|
||||||
|
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.RemoveSMTPConfig(tt.args.ctx)
|
||||||
|
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 newSMTPConfigChangedEvent(ctx context.Context, tls bool, fromAddress, fromName, host, user string) *instance.SMTPConfigChangedEvent {
|
func newSMTPConfigChangedEvent(ctx context.Context, tls bool, fromAddress, fromName, host, user string) *instance.SMTPConfigChangedEvent {
|
||||||
changes := []instance.SMTPConfigChanges{
|
changes := []instance.SMTPConfigChanges{
|
||||||
instance.ChangeSMTPConfigTLS(tls),
|
instance.ChangeSMTPConfigTLS(tls),
|
||||||
|
@ -5,4 +5,5 @@ type SMTPConfigState int32
|
|||||||
const (
|
const (
|
||||||
SMTPConfigStateUnspecified SMTPConfigState = iota
|
SMTPConfigStateUnspecified SMTPConfigState = iota
|
||||||
SMTPConfigStateActive
|
SMTPConfigStateActive
|
||||||
|
SMTPConfigStateRemoved
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
|||||||
RegisterFilterEventMapper(SMTPConfigAddedEventType, SMTPConfigAddedEventMapper).
|
RegisterFilterEventMapper(SMTPConfigAddedEventType, SMTPConfigAddedEventMapper).
|
||||||
RegisterFilterEventMapper(SMTPConfigChangedEventType, SMTPConfigChangedEventMapper).
|
RegisterFilterEventMapper(SMTPConfigChangedEventType, SMTPConfigChangedEventMapper).
|
||||||
RegisterFilterEventMapper(SMTPConfigPasswordChangedEventType, SMTPConfigPasswordChangedEventMapper).
|
RegisterFilterEventMapper(SMTPConfigPasswordChangedEventType, SMTPConfigPasswordChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(SMTPConfigRemovedEventType, SMTPConfigRemovedEventMapper).
|
||||||
RegisterFilterEventMapper(SMSConfigTwilioAddedEventType, SMSConfigTwilioAddedEventMapper).
|
RegisterFilterEventMapper(SMSConfigTwilioAddedEventType, SMSConfigTwilioAddedEventMapper).
|
||||||
RegisterFilterEventMapper(SMSConfigTwilioChangedEventType, SMSConfigTwilioChangedEventMapper).
|
RegisterFilterEventMapper(SMSConfigTwilioChangedEventType, SMSConfigTwilioChangedEventMapper).
|
||||||
RegisterFilterEventMapper(SMSConfigTwilioTokenChangedEventType, SMSConfigTwilioTokenChangedEventMapper).
|
RegisterFilterEventMapper(SMSConfigTwilioTokenChangedEventType, SMSConfigTwilioTokenChangedEventMapper).
|
||||||
|
@ -15,6 +15,7 @@ const (
|
|||||||
SMTPConfigAddedEventType = instanceEventTypePrefix + smtpConfigPrefix + "added"
|
SMTPConfigAddedEventType = instanceEventTypePrefix + smtpConfigPrefix + "added"
|
||||||
SMTPConfigChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "changed"
|
SMTPConfigChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "changed"
|
||||||
SMTPConfigPasswordChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "password.changed"
|
SMTPConfigPasswordChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "password.changed"
|
||||||
|
SMTPConfigRemovedEventType = instanceEventTypePrefix + smtpConfigPrefix + "removed"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SMTPConfigAddedEvent struct {
|
type SMTPConfigAddedEvent struct {
|
||||||
@ -197,3 +198,40 @@ func SMTPConfigPasswordChangedEventMapper(event *repository.Event) (eventstore.E
|
|||||||
|
|
||||||
return smtpConfigPasswordChagned, nil
|
return smtpConfigPasswordChagned, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SMTPConfigRemovedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSMTPConfigRemovedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
) *SMTPConfigRemovedEvent {
|
||||||
|
return &SMTPConfigRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
SMTPConfigRemovedEventType,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SMTPConfigRemovedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SMTPConfigRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SMTPConfigRemovedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
smtpConfigRemoved := &SMTPConfigRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(event.Data, smtpConfigRemoved)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "IAM-DVw1s", "unable to unmarshal smtp config removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return smtpConfigRemoved, nil
|
||||||
|
}
|
||||||
|
@ -237,6 +237,18 @@ service AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add system smtp configuration
|
||||||
|
rpc AddSMTPConfig(AddSMTPConfigRequest) returns (AddSMTPConfigResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/smtp";
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.write";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Update system smtp configuration
|
// Update system smtp configuration
|
||||||
rpc UpdateSMTPConfig(UpdateSMTPConfigRequest) returns (UpdateSMTPConfigResponse) {
|
rpc UpdateSMTPConfig(UpdateSMTPConfigRequest) returns (UpdateSMTPConfigResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -261,6 +273,17 @@ service AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove system smtp configuration
|
||||||
|
rpc RemoveSMTPConfig(RemoveSMTPConfigRequest) returns (RemoveSMTPConfigResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
delete: "/smtp";
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.write";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// list sms provider configurations
|
// list sms provider configurations
|
||||||
rpc ListSMSProviders(ListSMSProvidersRequest) returns (ListSMSProvidersResponse) {
|
rpc ListSMSProviders(ListSMSProvidersRequest) returns (ListSMSProvidersResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -320,6 +343,17 @@ service AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove sms provider token
|
||||||
|
rpc RemoveSMSProvider(RemoveSMSProviderRequest) returns (RemoveSMSProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
delete: "/sms/{id}";
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.write";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Get OIDC settings (e.g token lifetimes, etc.)
|
// Get OIDC settings (e.g token lifetimes, etc.)
|
||||||
rpc GetOIDCSettings(GetOIDCSettingsRequest) returns (GetOIDCSettingsResponse) {
|
rpc GetOIDCSettings(GetOIDCSettingsRequest) returns (GetOIDCSettingsResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -2661,6 +2695,19 @@ message GetSMTPConfigResponse {
|
|||||||
zitadel.settings.v1.SMTPConfig smtp_config = 1;
|
zitadel.settings.v1.SMTPConfig smtp_config = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddSMTPConfigRequest {
|
||||||
|
string sender_address = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string sender_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
bool tls = 3;
|
||||||
|
string host = 4 [(validate.rules).string = {min_len: 1, max_len: 500}];
|
||||||
|
string user = 5;
|
||||||
|
string password = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddSMTPConfigResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message UpdateSMTPConfigRequest {
|
message UpdateSMTPConfigRequest {
|
||||||
string sender_address = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
string sender_address = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
string sender_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
string sender_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
@ -2681,6 +2728,13 @@ message UpdateSMTPConfigPasswordResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this is en empty request
|
||||||
|
message RemoveSMTPConfigRequest {}
|
||||||
|
|
||||||
|
message RemoveSMTPConfigResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message ListSMSProvidersRequest {
|
message ListSMSProvidersRequest {
|
||||||
//list limitations and ordering
|
//list limitations and ordering
|
||||||
zitadel.v1.ListQuery query = 1;
|
zitadel.v1.ListQuery query = 1;
|
||||||
@ -2729,6 +2783,14 @@ message UpdateSMSProviderTwilioTokenResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message RemoveSMSProviderRequest {
|
||||||
|
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
}
|
||||||
|
|
||||||
|
message RemoveSMSProviderResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
}
|
||||||
|
|
||||||
//This is an empty request
|
//This is an empty request
|
||||||
message GetFileSystemNotificationProviderRequest {}
|
message GetFileSystemNotificationProviderRequest {}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user