Merge branch 'next' into next-rc

This commit is contained in:
Livio Spring 2024-06-25 11:42:45 -07:00
commit 2c93bcbf24
No known key found for this signature in database
GPG Key ID: 26BB1C2FA5952CF0
112 changed files with 8317 additions and 5461 deletions

View File

@ -2,7 +2,7 @@
title="{{
id ? ('SMTP.DETAIL.TITLE' | translate) : ('SMTP.CREATE.STEPS.TITLE' | translate: { value: providerDefaultSetting.name })
}}"
[createSteps]="3"
[createSteps]="4"
[currentCreateStep]="currentCreateStep"
(closed)="close()"
>
@ -93,7 +93,7 @@
[disabled]="firstFormGroup.invalid"
color="primary"
matStepperNext
data-e2e="continue-button"
data-e2e="continue-to-2nd-form"
>
{{ 'ACTIONS.CONTINUE' | translate }}
</button>
@ -130,19 +130,74 @@
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
<button
mat-raised-button
class="create-button"
[disabled]="secondFormGroup.invalid"
color="primary"
data-e2e="create-button"
(click)="savePolicy(stepper)"
[disabled]="
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
"
matStepperNext
data-e2e="continue-button"
>
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
{{ 'ACTIONS.CONTINUE' | translate }}
</button>
</div>
</mat-step>
<mat-step [editable]="true">
<form>
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.SAVE_SETTINGS' | translate }}</ng-template>
<cnsl-info-section>
<div class="title-row">
<div class="left">
<h2 class="title">{{ 'SMTP.CREATE.STEPS.TEST.TITLE' | translate }}</h2>
</div>
<div class="right">
<button color="primary" mat-raised-button class="continue-button" (click)="testEmailConfiguration()">
{{ 'ACTIONS.TEST' | translate }}
</button>
</div>
</div>
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.TEST.DESCRIPTION' | translate }}</p>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_EMAIL' | translate }}</cnsl-label>
<input
cnslInput
[(ngModel)]="email"
[ngModelOptions]="{ standalone: true }"
data-e2e="email-test-dialog-input"
/>
</cnsl-form-field>
<div class="is-loading" *ngIf="isLoading()">
<mat-spinner diameter="50"></mat-spinner>
</div>
<cnsl-form-field class="formfield" *ngIf="testResult">
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_RESULT' | translate }}</cnsl-label>
<textarea
cnslInput
class="{{ resultClass }}"
[(ngModel)]="testResult"
[ngModelOptions]="{ standalone: true }"
></textarea>
</cnsl-form-field>
</cnsl-info-section>
<div class="smtp-create-actions">
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
<button
mat-raised-button
class="create-button"
color="primary"
data-e2e="create-button"
(click)="savePolicy(stepper)"
[disabled]="
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
"
>
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
</button>
</div>
</form>
</mat-step>
<mat-step [editable]="true">
<form>
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.NEXT_STEPS' | translate }}</ng-template>

View File

@ -1,8 +1,8 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component } from '@angular/core';
import { Component, signal } from '@angular/core';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { Subject, take } 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';
@ -11,6 +11,7 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
import {
AddSMTPConfigRequest,
AddSMTPConfigResponse,
TestSMTPConfigRequest,
UpdateSMTPConfigRequest,
UpdateSMTPConfigResponse,
} from 'src/app/proto/generated/zitadel/admin_pb';
@ -31,8 +32,10 @@ import {
OutlookDefaultSettings,
SendgridDefaultSettings,
} from './known-smtp-providers-settings';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { MatStepper } from '@angular/material/stepper';
import { SMTPConfigState } from 'src/app/proto/generated/zitadel/settings_pb';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'cnsl-smtp-provider',
@ -61,6 +64,11 @@ export class SMTPProviderComponent {
public senderEmailPlaceholder = 'sender@example.com';
public resultClass = 'test-success';
public isLoading = signal(false);
public email: string = '';
public testResult: string = '';
constructor(
private service: AdminService,
private _location: Location,
@ -68,6 +76,8 @@ export class SMTPProviderComponent {
private toast: ToastService,
private router: Router,
private route: ActivatedRoute,
private authService: GrpcAuthService,
private translate: TranslateService,
) {
this.route.parent?.url.subscribe((urlPath) => {
const providerName = urlPath[urlPath.length - 1].path;
@ -136,6 +146,17 @@ export class SMTPProviderComponent {
this.fetchData(this.id);
}
}
this.authService
.getMyUser()
.then((resp) => {
if (resp.user) {
this.email = resp.user.human?.email?.email || '';
}
})
.catch((error) => {
this.toast.showError(error);
});
});
}
@ -281,6 +302,38 @@ export class SMTPProviderComponent {
});
}
public testEmailConfiguration(): void {
this.isLoading.set(true);
const req = new TestSMTPConfigRequest();
req.setSenderAddress(this.senderAddress?.value ?? '');
req.setSenderName(this.senderName?.value ?? '');
req.setHost(this.hostAndPort?.value ?? '');
req.setUser(this.user?.value);
req.setPassword(this.password?.value ?? '');
req.setTls(this.tls?.value ?? false);
req.setId(this.id ?? '');
req.setReceiverAddress(this.email ?? '');
this.service
.testSMTPConfig(req)
.then(() => {
this.resultClass = 'test-success';
this.isLoading.set(false);
this.translate
.get('SMTP.CREATE.STEPS.TEST.RESULT')
.pipe(take(1))
.subscribe((msg) => {
this.testResult = msg;
});
})
.catch((error) => {
this.resultClass = 'test-error';
this.isLoading.set(false);
this.testResult = error;
});
}
public get description(): AbstractControl | null {
return this.firstFormGroup.get('description');
}

View File

@ -96,4 +96,26 @@
width: 1.2rem;
}
}
.continue-button {
margin-top: 3rem;
display: block;
height: 3.5rem;
padding: 0 4rem;
}
.is-loading {
display: flex;
justify-content: center;
}
.test-error {
border-color: #ff3b5b !important;
min-height: 200px;
}
.test-success {
border-color: #10b981 !important;
min-height: 200px;
}
}

View File

@ -93,6 +93,18 @@
<i class="las la-times-circle"></i>
</button>
<button
actions
[disabled]="(['iam.write'] | hasRole | async) === false"
mat-icon-button
color="primary"
matTooltip="{{ 'SMTP.LIST.TEST' | translate }}"
data-e2e="test-provider-button"
(click)="testSMTPConfig(config.id); $event.stopPropagation()"
>
<i class="las la-flask"></i>
</button>
<button
actions
[disabled]="(['iam.write'] | hasRole | async) === false"

View File

@ -16,6 +16,7 @@ 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';
import { SmtpTestDialogComponent } from '../smtp-test-dialog/smtp-test-dialog.component';
@Component({
selector: 'cnsl-smtp-table',
@ -149,6 +150,21 @@ export class SMTPTableComponent implements OnInit {
});
}
public testSMTPConfig(id: string): void {
this.dialog.open(SmtpTestDialogComponent, {
data: {
id: id,
confirmKey: 'ACTIONS.TEST',
cancelKey: 'ACTIONS.CLOSE',
titleKey: 'SMTP.LIST.DIALOG.TEST_TITLE',
descriptionKey: 'SMTP.LIST.DIALOG.TEST_DESCRIPTION',
emailKey: 'SMTP.LIST.DIALOG.TEST_EMAIL',
testResultKey: 'SMTP.LIST.DIALOG.TEST_RESULT',
},
width: '500px',
});
}
private async getData(limit: number, offset: number): Promise<void> {
this.loadingSubject.next(true);

View File

@ -18,6 +18,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTableModule } from '@angular/material/table';
import { SmtpTestDialogModule } from '../smtp-test-dialog/smtp-test-dialog.module';
@NgModule({
declarations: [SMTPTableComponent],
@ -40,6 +41,7 @@ import { MatTableModule } from '@angular/material/table';
HasRoleModule,
HasRolePipeModule,
TruncatePipeModule,
SmtpTestDialogModule,
],
exports: [SMTPTableComponent],
})

View File

@ -0,0 +1,47 @@
<h1 mat-dialog-title>
<span>{{ data.titleKey | translate: data.titleParam }}</span>
</h1>
<div mat-dialog-content>
<div class="icon-wrapper" *ngIf="data.icon">
<i class="icon {{ data.icon }}"></i>
</div>
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate: data.descriptionParam }}</p>
<cnsl-info-section *ngIf="data.warnSectionKey" [type]="InfoSectionType.WARN">
{{ data.warnSectionKey | translate }}
</cnsl-info-section>
<p *ngIf="data.hintKey" class="desc cnsl-secondary-text">{{ data.hintKey | translate: { value: data.confirmation } }}</p>
<cnsl-form-field class="formfield">
<cnsl-label>{{ data.emailKey | translate }}</cnsl-label>
<input cnslInput [(ngModel)]="email" data-e2e="email-test-dialog-input" />
</cnsl-form-field>
<div class="is-loading" *ngIf="isLoading()">
<mat-spinner diameter="50"></mat-spinner>
</div>
<cnsl-form-field class="formfield" *ngIf="testResult">
<cnsl-label>{{ data.testResultKey | translate }}</cnsl-label>
<textarea cnslInput class="{{ resultClass }}" [(ngModel)]="testResult"></textarea>
</cnsl-form-field>
</div>
<div class="action" mat-dialog-actions>
<button *ngIf="data.cancelKey" mat-stroked-button (click)="closeDialog()">
{{ data.cancelKey | translate }}
</button>
<span class="fill-space"></span>
<button
color="primary"
[disabled]="!email || isLoading()"
mat-raised-button
class="ok-button"
(click)="testEmailConfiguration()"
data-e2e="test-email-button"
>
{{ data.confirmKey | translate }}
</button>
</div>

View File

@ -0,0 +1,51 @@
h1 {
font-size: 1.5rem;
margin: 0;
}
.icon-wrapper {
display: flex;
justify-content: center;
padding: 1rem;
margin: 1rem;
align-items: center;
.icon {
font-size: 3rem;
}
}
.desc {
font-size: 0.9rem;
}
.action {
display: flex;
button {
border-radius: 0.5rem;
}
.ok-button {
margin-left: 0.5rem;
}
.fill-space {
flex: 1;
}
}
.is-loading {
display: flex;
justify-content: center;
}
.test-error {
border-color: #ff3b5b;
min-height: 200px;
}
.test-success {
border-color: #10b981;
min-height: 200px;
}

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { SmtpTestDialogComponent } from './smtp-test-dialog.component';
describe('SmtpTestDialogComponent', () => {
let component: SmtpTestDialogComponent;
let fixture: ComponentFixture<SmtpTestDialogComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [SmtpTestDialogComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SmtpTestDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,72 @@
import { Component, Inject, signal } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { InfoSectionType } from '../info-section/info-section.component';
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 { TranslateService } from '@ngx-translate/core';
import { TestSMTPConfigByIdRequest } from 'src/app/proto/generated/zitadel/admin_pb';
import { take } from 'rxjs';
@Component({
selector: 'cnsl-smtp-test-dialog',
templateUrl: './smtp-test-dialog.component.html',
styleUrls: ['./smtp-test-dialog.component.scss'],
})
export class SmtpTestDialogComponent {
public resultClass = 'test-success';
public isLoading = signal(false);
public email: string = '';
public testResult: string = '';
InfoSectionType: any = InfoSectionType;
constructor(
public dialogRef: MatDialogRef<SmtpTestDialogComponent>,
private adminService: AdminService,
private authService: GrpcAuthService,
private toast: ToastService,
private translate: TranslateService,
@Inject(MAT_DIALOG_DATA) public data: any,
) {
this.authService
.getMyUser()
.then((resp) => {
if (resp.user) {
this.email = resp.user.human?.email?.email || '';
}
})
.catch((error) => {
this.toast.showError(error);
});
}
public testEmailConfiguration(): void {
this.isLoading.set(true);
const req = new TestSMTPConfigByIdRequest();
req.setId(this.data.id);
req.setReceiverAddress(this.email);
this.adminService
.testSMTPConfigById(req)
.then(() => {
this.resultClass = 'test-success';
this.isLoading.set(false);
this.translate
.get('SMTP.CREATE.STEPS.TEST.RESULT')
.pipe(take(1))
.subscribe((msg) => {
this.testResult = msg;
});
})
.catch((error) => {
this.resultClass = 'test-error';
this.isLoading.set(false);
this.testResult = error;
});
}
public closeDialog(): void {
this.dialogRef.close(false);
}
}

View File

@ -0,0 +1,26 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { TranslateModule } from '@ngx-translate/core';
import { MatDialogModule } from '@angular/material/dialog';
import { InfoSectionModule } from '../info-section/info-section.module';
import { InputModule } from '../input/input.module';
import { SmtpTestDialogComponent } from './smtp-test-dialog.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@NgModule({
declarations: [SmtpTestDialogComponent],
imports: [
CommonModule,
FormsModule,
MatDialogModule,
MatProgressSpinnerModule,
TranslateModule,
InfoSectionModule,
MatButtonModule,
InputModule,
],
})
export class SmtpTestDialogModule {}

View File

@ -240,6 +240,10 @@ import {
SetSecurityPolicyResponse,
SetUpOrgRequest,
SetUpOrgResponse,
TestSMTPConfigByIdRequest,
TestSMTPConfigByIdResponse,
TestSMTPConfigRequest,
TestSMTPConfigResponse,
UpdateAppleProviderRequest,
UpdateAppleProviderResponse,
UpdateAzureADProviderRequest,
@ -330,6 +334,7 @@ import {
} from '../proto/generated/zitadel/milestone/v1/milestone_pb';
import { OrgFieldName, OrgQuery } from '../proto/generated/zitadel/org_pb';
import { SortDirection } from '@angular/material/sort';
import { SMTPConfig } from '../proto/generated/zitadel/settings_pb';
export interface OnboardingActions {
order: number;
@ -946,6 +951,14 @@ export class AdminService {
return this.grpcService.admin.deactivateSMTPConfig(req, null).then((resp) => resp.toObject());
}
public testSMTPConfigById(req: TestSMTPConfigByIdRequest): Promise<TestSMTPConfigByIdResponse.AsObject> {
return this.grpcService.admin.testSMTPConfigById(req, null).then((resp) => resp.toObject());
}
public testSMTPConfig(req: TestSMTPConfigRequest): Promise<TestSMTPConfigResponse.AsObject> {
return this.grpcService.admin.testSMTPConfig(req, null).then((resp) => resp.toObject());
}
public removeSMTPConfig(id: string): Promise<RemoveSMTPConfigResponse.AsObject> {
const req = new RemoveSMTPConfigRequest();
req.setId(id);

View File

@ -485,8 +485,15 @@
"NEXT": "Следващ",
"MORE": "Повече ▼",
"STEP": "стъпка",
"SETUP": "Настройвам",
"COMINGSOON": "Очаквайте скоро",
"TEST": "Тест",
"UNSAVEDCHANGES": "Незапазени промени",
"UNSAVED": {
"DIALOG": {
"DESCRIPTION": "Сигурни ли сте, че искате да отхвърлите това ново действие? Вашето действие ще бъде загубено",
"CANCEL": "Отказ",
"DISCARD": "Изхвърлете"
}
},
"TABLE": {
"SHOWUSER": "Покажи потребител {{value}}"
},
@ -2228,6 +2235,7 @@
"ACTIVATED": "Активиран",
"ACTIVATE": "Активирайте доставчика",
"DEACTIVATE": "Деактивирайте доставчика",
"TEST": "Тествайте вашия доставчик",
"TYPE": "Тип",
"DIALOG": {
"ACTIVATED": "SMTP конфигурацията е активирана",
@ -2251,7 +2259,6 @@
"CURRENT_DESC_TITLE": "Това са вашите SMTP настройки",
"PROVIDER_SETTINGS": "Настройки на SMTP доставчик",
"SENDER_SETTINGS": "Настройки на изпращача",
"TEST_SETTINGS": "Тествайте настройките на SMTP",
"NEXT_STEPS": "Следващи стъпки",
"ACTIVATE": {
"TITLE": "Активирайте вашия SMTP доставчик",
@ -2260,6 +2267,12 @@
"DEACTIVATE": {
"TITLE": "Деактивирайте вашия SMTP доставчик",
"DESCRIPTION": "Ако деактивирате този SMTP доставчик, ZITADEL не може да го използва за изпращане на известия, докато не го активирате отново."
},
"SAVE_SETTINGS": "Запазете вашите настройки",
"TEST": {
"TITLE": "Тествайте настройките си",
"DESCRIPTION": "Можете да тествате настройките на вашия SMTP доставчик и да проверите резултата от теста, преди да ги запазите",
"RESULT": "Вашият имейл беше изпратен успешно"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "více",
"STEP": "Krok",
"SETUP": "Nastavit",
"TEST": "Test",
"UNSAVEDCHANGES": "Neuložené změny",
"UNSAVED": {
"DIALOG": {
@ -2247,6 +2248,7 @@
"ACTIVATED": "Aktivováno",
"ACTIVATE": "Aktivujte poskytovatele",
"DEACTIVATE": "Deaktivovat poskytovatele",
"TEST": "Otestujte svého poskytovatele",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "Konfigurace SMTP byla aktivována",
@ -2270,7 +2272,6 @@
"CURRENT_DESC_TITLE": "Toto jsou vaše nastavení SMTP",
"PROVIDER_SETTINGS": "Nastavení poskytovatele SMTP",
"SENDER_SETTINGS": "Nastavení odesílatele",
"TEST_SETTINGS": "Otestujte nastavení SMTP",
"NEXT_STEPS": "Další kroky",
"ACTIVATE": {
"TITLE": "Aktivujte svého poskytovatele SMTP",
@ -2279,6 +2280,12 @@
"DEACTIVATE": {
"TITLE": "Deaktivujte svého poskytovatele SMTP",
"DESCRIPTION": "Pokud deaktivujete tohoto poskytovatele SMTP, ZITADEL jej nebude moci používat k odesílání upozornění, dokud jej znovu neaktivujete."
},
"SAVE_SETTINGS": "Uložte nastavení",
"TEST": {
"TITLE": "Otestujte svá nastavení",
"DESCRIPTION": "Nastavení poskytovatele SMTP můžete otestovat a před uložením zkontrolovat výsledek testu",
"RESULT": "Váš email byl úspěšně odeslán"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "Weiter",
"MORE": "mehr",
"STEP": "Schritt",
"SETUP": "Aufstellen",
"TEST": "Prüfen",
"UNSAVEDCHANGES": "Nicht gespeicherte Änderungen",
"UNSAVED": {
"DIALOG": {
@ -2237,6 +2239,7 @@
"ACTIVATED": "Aktiviert",
"ACTIVATE": "Anbieter aktivieren",
"DEACTIVATE": "Anbieter deaktivieren",
"TEST": "Testen Sie Ihren Anbieter",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "Die SMTP-Konfiguration wurde aktiviert",
@ -2260,7 +2263,6 @@
"CURRENT_DESC_TITLE": "Dies sind Ihre SMTP-Einstellungen",
"PROVIDER_SETTINGS": "SMTP-Anbietereinstellungen",
"SENDER_SETTINGS": "Absendereinstellungen",
"TEST_SETTINGS": "Testen Sie die SMTP-Einstellungen",
"NEXT_STEPS": "Nächste Schritte",
"ACTIVATE": {
"TITLE": "Aktivieren Sie Ihren SMTP-Anbieter",
@ -2269,6 +2271,12 @@
"DEACTIVATE": {
"TITLE": "Deaktivieren Sie Ihren SMTP-Anbieter",
"DESCRIPTION": "Wenn Sie diesen SMTP-Anbieter deaktivieren, kann ZITADEL ihn nicht zum Versenden von Benachrichtigungen verwenden, bis Sie ihn erneut aktivieren."
},
"SAVE_SETTINGS": "Speichern Sie Ihre Einstellungen",
"TEST": {
"TITLE": "Testen Sie Ihre Einstellungen",
"DESCRIPTION": "Sie können die Einstellungen Ihres SMTP-Anbieters testen und das Testergebnis überprüfen, bevor Sie sie speichern",
"RESULT": "Deine E-Mail wurde erfolgreich versandt"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "more",
"STEP": "Step",
"SETUP": "Setup",
"TEST": "Test",
"UNSAVEDCHANGES": "Unsaved changes",
"UNSAVED": {
"DIALOG": {
@ -2259,6 +2260,7 @@
"ACTIVATED": "Activated",
"ACTIVATE": "Activate provider",
"DEACTIVATE": "Deactivate provider",
"TEST": "Test your provider",
"TYPE": "Type",
"DIALOG": {
"ACTIVATED": "SMTP config has been activated",
@ -2270,7 +2272,11 @@
"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."
"SENDER": "Type {{value}}, to delete this SMTP configuration.",
"TEST_TITLE": "Test your SMTP config",
"TEST_DESCRIPTION": "Specify an email address to test your SMTP configuration for this provider",
"TEST_EMAIL": "Email address",
"TEST_RESULT": "Test result"
}
},
"CREATE": {
@ -2282,7 +2288,6 @@
"CURRENT_DESC_TITLE": "These are your SMTP settings",
"PROVIDER_SETTINGS": "SMTP Provider Settings",
"SENDER_SETTINGS": "Sender Settings",
"TEST_SETTINGS": "Test SMTP Settings",
"NEXT_STEPS": "Next Steps",
"ACTIVATE": {
"TITLE": "Activate your SMTP Provider",
@ -2291,6 +2296,12 @@
"DEACTIVATE": {
"TITLE": "Deactivate your SMTP Provider",
"DESCRIPTION": "If you deactivate this SMTP Provider, ZITADEL cannot use it to send notifications until you activate it again."
},
"SAVE_SETTINGS": "Save your settings",
"TEST": {
"TITLE": "Test your settings",
"DESCRIPTION": "You can test your SMTP provider settings and check the test result before saving them",
"RESULT": "Your email was succesfully sent"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "más",
"STEP": "Paso",
"SETUP": "Configurar",
"TEST": "Probar",
"UNSAVEDCHANGES": "Cambios no guardados",
"UNSAVED": {
"DIALOG": {
@ -2235,6 +2236,7 @@
"ACTIVATED": "Activado",
"ACTIVATE": "Activar proveedor",
"DEACTIVATE": "Desactivar proveedor",
"TEST": "Prueba tu proveedor",
"TYPE": "Tipo",
"DIALOG": {
"ACTIVATED": "Tu configuración SMTP ha sido activada",
@ -2258,7 +2260,6 @@
"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",
"NEXT_STEPS": "Pŕoximos pasos",
"ACTIVATE": {
"TITLE": "Activa tu proveedor SMTP",
@ -2267,6 +2268,12 @@
"DEACTIVATE": {
"TITLE": "Desactiva tu proveedor SMTP",
"DESCRIPTION": "Si desactivas este proveedor SMTP, ZITADEL no puede utilizarlo para enviar notificationes hasta que lo actives otra vez."
},
"SAVE_SETTINGS": "Guarda tu configuración",
"TEST": {
"TITLE": "Prueba tu configuración",
"DESCRIPTION": "Puedes probar tu configuración SMTP y revisar el resultado de la prueba antes de guardar la configuración",
"RESULT": "Tu email fue enviado con éxito"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "Suivant",
"MORE": "Plus",
"STEP": "Étape",
"SETUP": "Installation",
"TEST": "Test",
"UNSAVEDCHANGES": "Modifications non enregistrées",
"UNSAVED": {
"DIALOG": {
@ -2238,6 +2240,7 @@
"ACTIVATED": "Activé",
"ACTIVATE": "Activer le fournisseur",
"DEACTIVATE": "Désactiver le fournisseur",
"TEST": "Testez votre fournisseur",
"TYPE": "Type",
"DIALOG": {
"ACTIVATED": "La configuration SMTP a été activée",
@ -2261,7 +2264,6 @@
"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",
"NEXT_STEPS": "Prochaines étapes",
"ACTIVATE": {
"TITLE": "Activez votre fournisseur SMTP",
@ -2270,6 +2272,12 @@
"DEACTIVATE": {
"TITLE": "Désactivez votre fournisseur SMTP",
"DESCRIPTION": "Si vous désactivez l'option SMTP, vous ne pourrez pas vous connecter à l'application, le dossier sera alors désactivé."
},
"SAVE_SETTINGS": "Enregistrez vos paramètres",
"TEST": {
"TITLE": "Testez vos paramètres",
"DESCRIPTION": "Vous pouvez tester les paramètres de votre fournisseur SMTP et vérifier le résultat du test avant de les enregistrer",
"RESULT": "Votre email a été envoyé avec succès"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "Avanti",
"MORE": "azioni",
"STEP": "Passo",
"SETUP": "Setup",
"TEST": "Test",
"UNSAVED": {
"DIALOG": {
"DESCRIPTION": "Sei sicuro di voler eliminare questa nuova azione? La tua azione andrà persa",
@ -2238,6 +2240,7 @@
"ACTIVATED": "Attivato",
"ACTIVATE": "Attiva fornitore",
"DEACTIVATE": "Disattiva fornitore",
"TEST": "Metti alla prova il tuo fornitore",
"TYPE": "Tipo",
"DIALOG": {
"ACTIVATED": "La configurazione SMTP è stata attivata",
@ -2261,7 +2264,6 @@
"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",
"NEXT_STEPS": "Prossimi passi",
"ACTIVATE": {
"TITLE": "Attiva il tuo provider SMTP",
@ -2270,6 +2272,12 @@
"DEACTIVATE": {
"TITLE": "Disattiva il tuo provider SMTP",
"DESCRIPTION": "Dopo aver disattivato l'archivio SMTP, la schermata non è disponibile per l'utente, il documento è nuovo e non è attivo."
},
"SAVE_SETTINGS": "Salva le tue impostazioni",
"TEST": {
"TITLE": "Metti alla prova le tue impostazioni",
"DESCRIPTION": "Puoi testare le impostazioni del tuo provider SMTP e controllare il risultato del test prima di salvarle",
"RESULT": "La tua email è stata inviata correttamente"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "さらに",
"STEP": "ステップ",
"SETUP": "セットアップ",
"TEST": "テスト",
"UNSAVEDCHANGES": "未保存の変更",
"UNSAVED": {
"DIALOG": {
@ -2230,6 +2231,7 @@
"ACTIVATED": "アクティブ化された",
"ACTIVATE": "プロバイダーをアクティブ化する",
"DEACTIVATE": "プロバイダーを非アクティブ化する",
"TEST": "プロバイダーをテストする",
"TYPE": "タイプ",
"DIALOG": {
"ACTIVATED": "SMTP設定が有効化されました",
@ -2253,7 +2255,6 @@
"CURRENT_DESC_TITLE": "これらは SMTP 設定です",
"PROVIDER_SETTINGS": "SMTPプロバイダーの設定",
"SENDER_SETTINGS": "送信者の設定",
"TEST_SETTINGS": "SMTP設定をテストする",
"NEXT_STEPS": "次のステップ",
"ACTIVATE": {
"TITLE": "SMTP プロバイダーをアクティブ化する",
@ -2262,6 +2263,12 @@
"DEACTIVATE": {
"TITLE": "SMTPプロバイダーを非アクティブ化します",
"DESCRIPTION": "この SMTP プロバイダーを非アクティブ化すると、再度アクティブ化するまで、Zitadel はそれを使用して通知を送信できなくなります。"
},
"SAVE_SETTINGS": "設定を保存する",
"TEST": {
"TITLE": "設定をテストする",
"DESCRIPTION": "SMTP プロバイダーの設定をテストし、保存する前にテスト結果を確認できます。",
"RESULT": "あなたの電子メールが正常に送信されました"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "повеќе",
"STEP": "Чекор",
"SETUP": "Подесување",
"TEST": "Тест",
"UNSAVEDCHANGES": "Незачувани промени",
"UNSAVED": {
"DIALOG": {
@ -2235,6 +2236,7 @@
"ACTIVATED": "Активиран",
"ACTIVATE": "Активирајте го провајдерот",
"DEACTIVATE": "Деактивирајте го провајдерот",
"TEST": "Тестирајте го вашиот провајдер",
"TYPE": "Тип",
"DIALOG": {
"ACTIVATED": "SMTP конфигурацијата е активирана",
@ -2258,7 +2260,6 @@
"CURRENT_DESC_TITLE": "Ова се вашите поставки за SMTP",
"PROVIDER_SETTINGS": "Поставки на провајдерот SMTP",
"SENDER_SETTINGS": "Поставки на испраќачот",
"TEST_SETTINGS": "Тестирајте ги поставките за SMTP",
"NEXT_STEPS": "Следните чекори",
"ACTIVATE": {
"TITLE": "Активирајте го вашиот SMTP провајдер",
@ -2267,6 +2268,12 @@
"DEACTIVATE": {
"TITLE": "Деактивирајте го вашиот SMTP провајдер",
"DESCRIPTION": "Ако го деактивирате овој SMTP провајдер, ZITADEL не може да го користи за испраќање известувања додека не го активирате повторно."
},
"SAVE_SETTINGS": "Зачувајте ги вашите поставки",
"TEST": {
"TITLE": "Тестирајте ги вашите поставки",
"DESCRIPTION": "Можете да ги тестирате поставките на провајдерот SMTP и да го проверите резултатот од тестот пред да ги зачувате",
"RESULT": "Вашата е-пошта беше успешно испратена"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "meer",
"STEP": "Stap",
"SETUP": "Instellen",
"TEST": "Test",
"UNSAVEDCHANGES": "Niet-opgeslagen wijzigingen",
"UNSAVED": {
"DIALOG": {
@ -2256,6 +2257,7 @@
"ACTIVATED": "Geactiveerd",
"ACTIVATE": "Aanbieder activeren",
"DEACTIVATE": "Aanbieder deactiveren",
"TEST": "Test uw aanbieder",
"TYPE": "Type",
"DIALOG": {
"ACTIVATED": "SMTP-configuratie is geactiveerd",
@ -2279,7 +2281,6 @@
"CURRENT_DESC_TITLE": "Dit zijn uw SMTP-instellingen",
"PROVIDER_SETTINGS": "SMTP-providerinstellingen",
"SENDER_SETTINGS": "Afzenderinstellingen",
"TEST_SETTINGS": "SMTP-instellingen testen",
"NEXT_STEPS": "Volgende stappen",
"ACTIVATE": {
"TITLE": "Activeer uw SMTP-provider",
@ -2288,6 +2289,12 @@
"DEACTIVATE": {
"TITLE": "Deactiveer uw SMTP-provider",
"DESCRIPTION": "Als u deze SMTP-provider deactiveert, kan ZITADEL deze niet gebruiken om meldingen te verzenden totdat u deze opnieuw activeert."
},
"SAVE_SETTINGS": "Sla uw instellingen op",
"TEST": {
"TITLE": "Test uw instellingen",
"DESCRIPTION": "U kunt de instellingen van uw SMTP-provider testen en het testresultaat controleren voordat u deze opslaat",
"RESULT": "Je email is succesvol verzonden"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "więcej",
"STEP": "Krok",
"UNSAVEDCHANGES": "Niezapisane zmiany",
"TEST": "Test",
"UNSAVED": {
"DIALOG": {
"DESCRIPTION": "Czy na pewno chcesz odrzucić to nowe działanie? Twoje działanie zostanie utracone",
@ -2238,6 +2239,7 @@
"ACTIVATED": "Aktywowany",
"ACTIVATE": "Aktywuj dostawcę",
"DEACTIVATE": "Dezaktywuj dostawcę",
"TEST": "Przetestuj swojego dostawcę",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "Konfiguracja SMTP została aktywowana",
@ -2261,7 +2263,6 @@
"CURRENT_DESC_TITLE": "To są Twoje ustawienia SMTP",
"PROVIDER_SETTINGS": "Ustawienia dostawcy SMTP",
"SENDER_SETTINGS": "Ustawienia nadawcy",
"TEST_SETTINGS": "Przetestuj ustawienia SMTP",
"NEXT_STEPS": "Następne kroki",
"ACTIVATE": {
"TITLE": "Aktywuj swojego dostawcę SMTP",
@ -2270,6 +2271,12 @@
"DEACTIVATE": {
"TITLE": "Dezaktywuj swojego dostawcę SMTP",
"DESCRIPTION": "Jeśli dezaktywujesz tego dostawcę SMTP, ZITADEL nie będzie mógł go używać do wysyłania powiadomień, dopóki nie aktywujesz go ponownie."
},
"SAVE_SETTINGS": "Zapisz swoje ustawienia",
"TEST": {
"TITLE": "Przetestuj swoje ustawienia",
"DESCRIPTION": "Możesz przetestować ustawienia dostawcy SMTP i sprawdzić wynik testu przed ich zapisaniem",
"RESULT": "Twój email został wysłany"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "mais",
"STEP": "Passo",
"SETUP": "Configuração",
"TEST": "Teste",
"UNSAVEDCHANGES": "Alterações não salvas",
"UNSAVED": {
"DIALOG": {
@ -2233,6 +2234,7 @@
"ACTIVATED": "Ativado",
"ACTIVATE": "Ativar provedor",
"DEACTIVATE": "Desativar provedor",
"TEST": "Teste seu provedor",
"TYPE": "Tipo",
"DIALOG": {
"ACTIVATED": "A configuração SMTP foi ativada",
@ -2256,7 +2258,6 @@
"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",
"NEXT_STEPS": "Próximos passos",
"ACTIVATE": {
"TITLE": "Ative seu provedor SMTP",
@ -2265,6 +2266,12 @@
"DEACTIVATE": {
"TITLE": "Desative seu provedor SMTP",
"DESCRIPTION": "Se você desativar este provedor SMTP, a ZITADEL não poderá usá-lo para enviar notificações até que você o ative novamente."
},
"SAVE_SETTINGS": "Salve suas configurações",
"TEST": {
"TITLE": "Teste suas configurações",
"DESCRIPTION": "Você pode testar as configurações do seu provedor SMTP e verificar o resultado do teste antes de salvá-las",
"RESULT": "Seu e-mail foi enviado com sucesso"
}
}
},

View File

@ -485,6 +485,7 @@
"MORE": "больше",
"STEP": "Шаг",
"SETUP": "Настроить",
"TEST": "Тест",
"UNSAVEDCHANGES": "Несохраненные изменения",
"UNSAVED": {
"DIALOG": {
@ -2350,6 +2351,7 @@
"ACTIVATED": "Активировано",
"ACTIVATE": "Активировать провайдера",
"DEACTIVATE": "Деактивировать провайдера",
"TEST": "Проверьте своего провайдера",
"TYPE": "Тип",
"DIALOG": {
"ACTIVATED": "Конфигурация SMTP активирована",
@ -2373,7 +2375,6 @@
"CURRENT_DESC_TITLE": "Это ваши настройки SMTP",
"PROVIDER_SETTINGS": "Настройки SMTP-провайдера",
"SENDER_SETTINGS": "Настройки отправителя",
"TEST_SETTINGS": "Проверка настроек SMTP",
"NEXT_STEPS": "Следующие шаги",
"ACTIVATE": {
"TITLE": "Активируйте своего SMTP-провайдера",
@ -2382,6 +2383,12 @@
"DEACTIVATE": {
"TITLE": "Деактивируйте своего SMTP-провайдера",
"DESCRIPTION": "Если вы деактивируете этого поставщика SMTP, ZITADEL не сможет использовать его для отправки уведомлений, пока вы не активируете его снова."
},
"SAVE_SETTINGS": "Сохраните настройки",
"TEST": {
"TITLE": "Проверьте свои настройки",
"DESCRIPTION": "Вы можете проверить настройки своего провайдера SMTP и проверить результаты проверки перед их сохранением.",
"RESULT": "Ваше письмо было успешно отправлено"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "mer",
"STEP": "Steg",
"SETUP": "Inställning",
"TEST": "Testa",
"UNSAVEDCHANGES": "Osparade ändringar",
"UNSAVED": {
"DIALOG": {
@ -2259,6 +2260,7 @@
"ACTIVATED": "Aktiverad",
"ACTIVATE": "Aktivera leverantör",
"DEACTIVATE": "Inaktivera leverantör",
"TEST": "Testa din leverantör",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "SMTP-konfigurationen har aktiverats",
@ -2270,7 +2272,11 @@
"DELETE_TITLE": "Radera SMTP-konfiguration",
"DELETE_DESCRIPTION": "Du håller på att radera en konfiguration. Bekräfta denna åtgärd genom att skriva avsändarnamnet",
"DELETED": "SMTP-konfigurationen har raderats",
"SENDER": "Skriv {{value}}, för att radera denna SMTP-konfiguration."
"SENDER": "Skriv {{value}}, för att radera denna SMTP-konfiguration.",
"TEST_TITLE": "Testa din SMTP-konfiguration",
"TEST_DESCRIPTION": "Ange en e-postadress för att testa din SMTP-konfiguration för den här leverantören",
"TEST_EMAIL": "E-postadress",
"TEST_RESULT": "Testresultat"
}
},
"CREATE": {
@ -2282,7 +2288,6 @@
"CURRENT_DESC_TITLE": "Dessa är dina SMTP-inställningar",
"PROVIDER_SETTINGS": "SMTP-leverantörsinställningar",
"SENDER_SETTINGS": "Avsändarinställningar",
"TEST_SETTINGS": "Testa SMTP-inställningar",
"NEXT_STEPS": "Nästa steg",
"ACTIVATE": {
"TITLE": "Aktivera din SMTP-leverantör",
@ -2291,6 +2296,12 @@
"DEACTIVATE": {
"TITLE": "Inaktivera din SMTP-leverantör",
"DESCRIPTION": "Om du inaktiverar denna SMTP-leverantör kan ZITADEL inte använda den för att skicka meddelanden förrän du aktiverar den igen."
},
"SAVE_SETTINGS": "Spara dina inställningar",
"TEST": {
"TITLE": "Testa dina inställningar",
"DESCRIPTION": "Du kan testa inställningarna för din SMTP-leverantör och kontrollera testresultatet innan du sparar dem",
"RESULT": "Ditt e-postmeddelande har skickats"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "下一页",
"MORE": "更多",
"STEP": "步",
"SETUP": "设置",
"TEST": "测试",
"UNSAVEDCHANGES": "未保存的更改",
"UNSAVED": {
"DIALOG": {
@ -2237,6 +2239,7 @@
"ACTIVATED": "活性",
"ACTIVATE": "激活提供商",
"DEACTIVATE": "停用提供商",
"TEST": "测试您的提供商",
"TYPE": "类型",
"DIALOG": {
"ACTIVATED": "SMTP 配置已激活",
@ -2260,7 +2263,6 @@
"CURRENT_DESC_TITLE": "这些是您的 SMTP 设置",
"PROVIDER_SETTINGS": "SMTP 提供商设置",
"SENDER_SETTINGS": "发件人设置",
"TEST_SETTINGS": "测试 SMTP 设置",
"NEXT_STEPS": "下一步",
"ACTIVATE": {
"TITLE": "激活您的 SMTP 提供商",
@ -2269,6 +2271,12 @@
"DEACTIVATE": {
"TITLE": "停用您的 SMTP 提供商",
"DESCRIPTION": "如果您停用此 SMTP 提供程序Zitadel 将无法使用它发送通知,直到您再次激活它。"
},
"SAVE_SETTINGS": "保存您的设置",
"TEST": {
"TITLE": "测试您的设置",
"DESCRIPTION": "您可以测试您的 SMTP 提供商设置并在保存之前检查测试结果",
"RESULT": "您的电子邮件已成功发送"
}
}
},

View File

@ -32,7 +32,7 @@ Please check below the matrix for an overview where which scope is asserted.
| phone_verified | When requested | When requested | When requested and response_type `id_token` | No |
| preferred_username (username when Introspect) | When requested | When requested | Yes | No |
| sub | Yes | Yes | Yes | When JWT |
| urn:zitadel:iam:org:domain:primary:{domainname} | When requested | When requested | When requested | When JWT and requested |
| urn:zitadel:iam:org:domain:primary:\{domainname} | When requested | When requested | When requested | When JWT and requested |
| urn:zitadel:iam:org:project:roles | When requested | When requested | When requested or configured | When JWT and requested or configured |
| urn:zitadel:iam:user:metadata | When requested | When requested | When requested | When JWT and requested |
| urn:zitadel:iam:user:resourceowner:id | When requested | When requested | When requested | When JWT and requested |
@ -101,11 +101,11 @@ ZITADEL reserves some claims to assert certain data. Please check out the [reser
| Claims | Example | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| urn:zitadel:iam:action:{actionname}:log | `{"urn:zitadel:iam:action:appendCustomClaims:log": ["test log", "another test log"]}` | This claim is set during Actions as a log, e.g. if two custom claims with the same keys are set. |
| urn:zitadel:iam:org:domain:primary:{domainname} | `{"urn:zitadel:iam:org:domain:primary": "acme.ch"}` | This claim represents the primary domain of the organization the user belongs to. |
| urn:zitadel:iam:action:\{actionname}:log | `{"urn:zitadel:iam:action:appendCustomClaims:log": ["test log", "another test log"]}` | This claim is set during Actions as a log, e.g. if two custom claims with the same keys are set. |
| urn:zitadel:iam:org:domain:primary:\{domainname} | `{"urn:zitadel:iam:org:domain:primary": "acme.ch"}` | This claim represents the primary domain of the organization the user belongs to. |
| urn:zitadel:iam:org:project:roles | `{"urn:zitadel:iam:org:project:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on the current project (where your client belongs to). |
| urn:zitadel:iam:org:project:{projectid}:roles | `{"urn:zitadel:iam:org:project:id3:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on a specific project. |
| urn:zitadel:iam:roles:{rolename} | TBA | TBA |
| urn:zitadel:iam:org:project:\{projectid}:roles | `{"urn:zitadel:iam:org:project:id3:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on a specific project. |
| urn:zitadel:iam:roles:\{rolename} | TBA | TBA |
| urn:zitadel:iam:user:metadata | `{"urn:zitadel:iam:user:metadata": [ {"key": "VmFsdWU=" } ] }` | The metadata claim will include all metadata of a user. The values are base64 encoded. |
| urn:zitadel:iam:user:resourceowner:id | `{"urn:zitadel:iam:user:resourceowner:id": "orgid"}` | This claim represents the id of the resource owner organisation of the user. |
| urn:zitadel:iam:user:resourceowner:name | `{"urn:zitadel:iam:user:resourceowner:name": "ACME"}` | This claim represents the name of the resource owner organisation of the user. |

View File

@ -12,13 +12,13 @@ import TokenExchangeTypes from "./_token_exchange_types.mdx";
## OpenID Connect 1.0 Discovery
The OpenID Connect Discovery Endpoint is located within the issuer domain.
This would give us {your_domain}/.well-known/openid-configuration.
This would give us `{your_domain}/.well-known/openid-configuration`.
**Link to spec.** [OpenID Connect Discovery 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-discovery-1_0.html)
## authorization_endpoint
{your_domain}/oauth/v2/authorize
`{your_domain}/oauth/v2/authorize`
:::note
The authorization_endpoint is located with the login page, due to the need of accessing the same cookie domain
@ -172,7 +172,7 @@ the error will be display directly to the user on the auth server
## token_endpoint
{your_domain}/oauth/v2/token
`{your_domain}/oauth/v2/token`
The token_endpoint will as the name suggests return various tokens (access, id and refresh) depending on the used `grant_type`.
When using [`authorization_code`](#authorization-code-grant-code-exchange) flow call this endpoint after receiving the code from the authorization_endpoint.
@ -471,7 +471,7 @@ Send a `client_assertion` as JWT for us to validate the signature against the re
## introspection_endpoint
{your_domain}/oauth/v2/introspect
`{your_domain}/oauth/v2/introspect`
This endpoint enables clients to validate an `acccess_token`, either opaque or JWT. Unlike client side JWT validation,
this endpoint will check if the token is not revoked (by client or logout).
@ -554,7 +554,7 @@ If the authorization fails, an HTTP 401 with `invalid_client` will be returned.
## userinfo_endpoint
{your_domain}/oidc/v1/userinfo
`{your_domain}/oidc/v1/userinfo`
This endpoint will return information about the authorized user.
@ -577,7 +577,7 @@ If the token is invalid or expired, an HTTP 401 will be returned.
## revocation_endpoint
{your_domain}/oauth/v2/revoke
`{your_domain}/oauth/v2/revoke`
This endpoint enables clients to revoke an `access_token` or `refresh_token` they have been granted.
@ -649,7 +649,7 @@ curl --request POST \
## end_session_endpoint
{your_domain}/oidc/v1/end_session
`{your_domain}/oidc/v1/end_session`
The endpoint has to be opened in the user agent (browser) to terminate the user sessions.
@ -667,7 +667,7 @@ If both parameters are provided, they must be equal.
## jwks_uri
{your_domain}/oauth/v2/keys
`{your_domain}/oauth/v2/keys`
The endpoint returns a JSON Web Key Set (JWKS) containing the public keys that can be used to locally validate JWTs you received from ZITADEL.
The alternative would be to validate tokens with the [introspection endpoint](#introspection_endpoint).

View File

@ -134,21 +134,21 @@ Additional to the standard CRUD methods:
- ListAvailableExecutionMethods
- ListAvailableExecutionFunctions
<details><summary>action_service.proto</summary>
\<details><summary>action_service.proto</summary>
<CodeBlock language="protobuf">{ActionServiceProto}</CodeBlock>
</details>
\</details>
<details><summary>action_target.proto</summary>
\<details><summary>action_target.proto</summary>
<CodeBlock language="protobuf">{ActionTargetProto}</CodeBlock>
</details>
\</details>
<details><summary>action_execution.proto</summary>
\<details><summary>action_execution.proto</summary>
<CodeBlock language="protobuf">{ActionExecutionProto}</CodeBlock>
</details>
\</details>
<details><summary>action_query.proto</summary>
\<details><summary>action_query.proto</summary>
<CodeBlock language="protobuf">{ActionSearchProto}</CodeBlock>
</details>
\</details>
### ZITADELUsers
@ -163,29 +163,29 @@ Standard CRUD methods
- Standard CRUD and methods for all IDPs
- Resources have additional properties for reusability capabilities.
<details><summary>idp_service.proto</summary>
\<details><summary>idp_service.proto</summary>
<CodeBlock language="protobuf">{IDPServiceProto}</CodeBlock>
</details>
\</details>
<details><summary>idp.proto</summary>
\<details><summary>idp.proto</summary>
<CodeBlock language="protobuf">{IDPProto}</CodeBlock>
</details>
\</details>
<details><summary>idp_search.proto</summary>
\<details><summary>idp_search.proto</summary>
<CodeBlock language="protobuf">{IDPSearchProto}</CodeBlock>
</details>
\</details>
<details><summary>idp_gitlab.proto</summary>
\<details><summary>idp_gitlab.proto</summary>
<CodeBlock language="protobuf">{IDPGitLabProto}</CodeBlock>
</details>
\</details>
<details><summary>object.proto</summary>
\<details><summary>object.proto</summary>
<CodeBlock language="protobuf">{ObjectProto}</CodeBlock>
</details>
\</details>
<details><summary>resource_object.proto</summary>
\<details><summary>resource_object.proto</summary>
<CodeBlock language="protobuf">{ResourceObjectProto}</CodeBlock>
</details>
\</details>
### ZITADELInstances
@ -265,21 +265,21 @@ For a full proto example, have a look at the [ZITADELLanguageSettings service](#
Default language, restricted languages, supported languages
<details><summary>language_service.proto</summary>
\<details><summary>language_service.proto</summary>
<CodeBlock language="protobuf">{LanguageServiceProto}</CodeBlock>
</details>
\</details>
<details><summary>language.proto</summary>
\<details><summary>language.proto</summary>
<CodeBlock language="protobuf">{LanguageProto}</CodeBlock>
</details>
\</details>
<details><summary>object.proto</summary>
\<details><summary>object.proto</summary>
<CodeBlock language="protobuf">{ObjectProto}</CodeBlock>
</details>
\</details>
<details><summary>settings_object.proto</summary>
\<details><summary>settings_object.proto</summary>
<CodeBlock language="protobuf">{SettingsObjectProto}</CodeBlock>
</details>
\</details>
### ZITADELTextSettings

View File

@ -45,7 +45,7 @@ Go to your instance settings and then click on the Tab **Events** to open the Ev
Since everything that is available in Console can also be called with our APIs, you can access all events and audit data trough our APIs:
- [Event API Guide](/docs/guides/integrate/zitadel-apis/event-api)
- [API Documentation](/docs/category/apis/resources/admin/events)
- [API Documentation](/docs/apis/resources/admin/events)
Access to the API is possible with a [Service User](/docs/guides/integrate/service-users/authenticate-service-users) account, allowing you to integrate the events with your own business logic.

View File

@ -35,6 +35,6 @@ In some use cases, external user grants are a simple way to allow users access t
## References
* [API reference for user grants](/docs/category/apis/resources/mgmt/user-grants)
* [API reference for user grants](/docs/apis/resources/mgmt/user-grants)
* [How to manage user grants through ZITADEL's console](/docs/guides/manage/console/roles#authorizations)
* [More about multi-tenancy with ZITADEL](https://zitadel.com/blog/multi-tenancy-with-organizations)

View File

@ -75,4 +75,4 @@ To address this, ZITADEL provides generic templates that enable connection to vi
* [Detailed integration guide for many identity providers](/guides/integrate/identity-providers/introduction)
* [Setup identity providers with Console](/guides/manage/console/default-settings#identity-providers)
* [Configure identity providers with the ZITADEL API](/docs/category/apis/resources/mgmt/identity-providers)
* [Configure identity providers with the ZITADEL API](/docs/apis/resources/mgmt/identity-providers)

View File

@ -25,4 +25,4 @@ Ensure the configuration of application settings is limited to authorized users
## References
- [Configure Applications in the Console](../../guides/manage/console/applications)
- [ZITADEL API: Applications](/docs/category/apis/resources/mgmt/applications)
- [ZITADEL API: Applications](/docs/apis/resources/mgmt/applications)

View File

@ -78,5 +78,5 @@ You can use organization metadata or your own business logic to describe a hiera
## References
- [Manage users in the Console](../../guides/manage/console/users)
- [ZITADEL APIs: Users](/docs/category/apis/resources/mgmt/users)
- [ZITADEL APIs: Users](/docs/apis/resources/mgmt/users)
- [User onboarding and registration](/docs/guides/integrate/onboarding)

View File

@ -21,7 +21,7 @@ We recommend that you use [Authorization Code](/apis/openidoauth/grant-types#aut
A redirect URL is a URL in your application where ZITADEL redirects the user after they have authenticated. Set your url to the domain the proxy will be deployed to or use the default one `http://127.0.0.1:4180/oauth2/callback`.
> If you are following along with the sample project you downloaded from our templates, you should set the Allowed Callback URL to <http://localhost:4200/auth/callback>. You will also have to set dev mode to `true` as this will enable unsecure http for the moment.
> If you are following along with the sample project you downloaded from our templates, you should set the Allowed Callback URL to `http://localhost:4200/auth/callback`. You will also have to set dev mode to `true` as this will enable unsecure http for the moment.
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the post redirectURI field.

View File

@ -25,7 +25,7 @@ We recommend that you use [Proof Key for Code Exchange (PKCE)](/apis/openidoauth
The Redirect URIs field tells ZITADEL where it's allowed to redirect users after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
The Post-logout redirect send the users back to a route on your application after they have logged out.
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set the dev mode to `true`, the Redirect URIs to <http://localhost:4200/auth/callback> and Post redirect URI to <http://localhost:4200/signedout>.
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set the dev mode to `true`, the Redirect URIs to `http://localhost:4200/auth/callback` and Post redirect URI to `http://localhost:4200/signedout`.
Continue and create the application.

View File

@ -28,7 +28,7 @@ We recommend that you use [Proof Key for Code Exchange (PKCE)](/apis/openidoauth
The Redirect URIs field tells ZITADEL where it's allowed to redirect users after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
The Post-logout redirect send the users back to a route on your application after they have logged out.
> If you are following along with the [example](https://github.com/zitadel/zitadel-go), set the dev mode to `true`, the Redirect URIs to <http://localhost:8089/auth/callback> and Post-logout redirect URI to <http://localhost:8089/>.
> If you are following along with the [example](https://github.com/zitadel/zitadel-go), set the dev mode to `true`, the Redirect URIs to `http://localhost:8089/auth/callback` and Post-logout redirect URI to [http://localhost:8089/](http://localhost:8089/)>.
![Create app in console - set redirectURI](/img/go/app-create-redirect.png)

View File

@ -162,7 +162,7 @@ java \
-jar web/target/web-0.0.2-SNAPSHOT.jar
```
If you then visit on <http://localhost:18080/webapp> you should directly be redirected to your ZITADEL instance.
If you then visit on [http://localhost:18080/webapp](http://localhost:18080/webapp) you should directly be redirected to your ZITADEL instance.
After login with your existing user you will be presented the profile page:
![Profile Page](/img/java-spring/app-profile.png)

View File

@ -22,7 +22,7 @@ First we need to create an organization that holds the Vendor's users, projects
### Vendor Organization
Navigate to `https://{YourDomain}.zitadel.cloud/ui/console/orgs` (replace {YourDomain}), and click on the button "New".
Navigate to `https://{YourDomain}.zitadel.cloud/ui/console/orgs` (replace \{YourDomain}), and click on the button "New".
Toggle the setting "Use your personal account as organization owner".
Enter the name `Demo-Vendor`, and click "Create". Then click on that organization.

View File

@ -41,7 +41,7 @@ Select `CODE` in the next step. This makes sure you still get a secret. Note tha
With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set dev mode to `true` and the Redirect URIs to <http://localhost:3000/api/auth/callback/zitadel>.
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set dev mode to `true` and the Redirect URIs to `http://localhost:3000/api/auth/callback/zitadel`.
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the Post Logout URIs field.

View File

@ -18,7 +18,7 @@ Before we can start building our application, we have to do a few configuration
### Project roles
The Example expects [user roles](guides/integrate/retrieve-user-roles) to be returned after login.
The Example expects [user roles](/docs/guides/integrate/retrieve-user-roles) to be returned after login.
Symfony uses `ROLE_USER` format.
The application will take care of upper-casing and prefixing for us.
Inside ZITADEL, you can use regular lower-case role names without prefixes, if you prefer.

View File

@ -177,5 +177,5 @@ Deciding whether to configure an external Identity Provider (IdP) at the organiz
## References
- [Identity brokering in ZITADEL](/docs/concepts/features/identity-brokering)
- [The ZITADEL API reference for managing external IdPs](/docs/category/apis/resources/admin/identity-providers)
- [Handle external logins in a custom login UI](/docs/guides/integrate/login-ui/external-login)
- [The ZITADEL API reference for managing external IdPs](/docs/apis/resources/admin/identity-providers)
- [Handle external logins in a custom login UI](/docs/guides/integrate/login-ui/external-login)

View File

@ -26,7 +26,7 @@ You will have to paste it in the Keycloak Client later.
### Register a new client
1. Login to your Keycloak account and go to the clients list: <$KEYCLOAK-DOMAIN/auth/admin/$REALM/console/#/$REALM/clients>
1. Login to your Keycloak account and go to the clients list: `$KEYCLOAK-DOMAIN/auth/admin/$REALM/console/#/$REALM/clients`
2. Click on "Create Client"
3. Choose OpenID Connect as Client Type and give your client an ID
4. Enable Client authentication and the standard flow and direct access grants as authentication flow

View File

@ -23,7 +23,7 @@ import TestSetup from './_test_setup.mdx';
2. Add your App Name, your Company Page and a Logo
3. Add "Sign In with LinkedIn using OpenID Connect" by clicking "Request access"
4. Go to the Auth Settings of the App and add the following URL to the "Authorized redirect URLs"
- {your-domain}/ui/login/login/externalidp/callback
- `{your_domain}/ui/login/login/externalidp/callback`
- Example redirect url for the domain `https://acme.zitadel.cloud` would look like this: `https://acme.zitadel.cloud/ui/login/login/externalidp/callback`
5. Verify the app as your company
6. In the Auth - OAuth 2.0 scopes section you should see `openid`, `profile` and `email` listed

View File

@ -44,7 +44,7 @@ All the necessary configuration is contained in the metadata which has to be exc
### Download metadata
Normally, you would need to download the ServiceProvider metadata from ZITADEL to upload to the IdentityProvider.
They are available under [https://{CUSTOMDOMAIN}/idps/{ID of the provider in ZITADEL}/saml/metadata], but this step can be skipped due to the fact that MockSAML is only for testing purposes.
They are available under `https://${CUSTOMDOMAIN}/idps/\{ID of the provider in ZITADEL}/saml/metadata`, but this step can be skipped due to the fact that MockSAML is only for testing purposes.
### Activate IdP

View File

@ -27,7 +27,7 @@ You will have to paste it in the OKTA application later.
### Register a new client
1. Login to your OKTA Account and go to the applications list: <OKTA-DOMAIN/admin/apps/active>
1. Login to your OKTA Account and go to the applications list: `OKTA-DOMAIN/admin/apps/active^
2. Click on "Create App Integration" and choose "OIDC - OpenID Connect"
3. Choose Web application as Application type and give a name
4. [Paste the ZITADEL Callback URL you copied before](#open-the-generic-oidc-provider-template) to the Sign-in redirect URIs
@ -65,7 +65,6 @@ ZITADEL ensures that at least the `openid`-scope is always sent.
<TestSetup loginscreen="your OKTA login"/>
<!-- TODO: Image highlights Google -->
![OKTA Button](/img/guides/zitadel_login_okta.png)
![OKTA Login](/img/guides/okta_login.png)

View File

@ -41,7 +41,7 @@ After you created the SAML SP in ZITADEL, you can copy the URLs you need to conf
### Register a new client
1. Log in to your OKTA Account and go to the applications list: <OKTA-DOMAIN/admin/apps/active>
1. Log in to your OKTA Account and go to the applications list: `OKTA-DOMAIN/admin/apps/active`
2. Click on "Create App Integration" and choose "SAML 2.0"
3. Give the application a name
4. Click on the ZITADEL URLs that your SAML IDP shows since you created it in ZITADEL and paste them accordingly:

View File

@ -26,7 +26,7 @@ ZITADEL does have multiple possibilities to achieve that process.
## Onboard customers through the ZITADEL Management Console
Each ZITADEL instance does automatically bring a management console with it. The [console](/docs/guides/manage/console/overview) can be used to manage all your resources through a UI.
You can access it by calling the following URL: $CUSTOM-DOMAIN/ui/
You can access it by calling the following URL: `${CUSTOM-DOMAIN}/ui/`
Make sure that your admins have a [Manager role](/docs/guides/manage/console/managers) with permissions on an instance level such as "INSTANCE_OWNER"
### Create a customer
@ -139,7 +139,7 @@ If you want to start automating the process of onboarding your customers the fol
### Built-in register organization form
A basic form that allows a customer to enter an organization name and a user account is hosted on the following URL:
{custom-domain}/ui/login/register/org
`{custom-domain}/ui/login/register/org`
When a user registers through this form, an organization and a user are created.
The user will automatically get the role "ORG_OWNER" withing ZITADEL and is able to manage the whole organization.

View File

@ -18,8 +18,8 @@ Follow the links below to assign roles to your users.
- [Add application roles via the ZITADEL Console](/docs/guides/manage/console/roles)
- [Add manager roles via the ZITADEL Console](/docs/guides/manage/console/managers)
- [Add application roles via the ZITADEL Management API](/docs/category/apis/resources/mgmt/project-roles)
- [Add manager roles to users via the ZITADEL Management API](/category/apis/resources/mgmt/members)
- [Add application roles via the ZITADEL Management API](/docs/apis/resources/mgmt/project-roles)
- [Add manager roles to users via the ZITADEL Management API](/docs/apis/resources/mgmt/members)
## Retrieve roles
@ -210,7 +210,7 @@ https://github.com/zitadel/actions/blob/main/examples/custom_roles.js
Now we will use the auth API to retrieve roles from a logged in user using the users token
The base URL is: **https://$ZITADEL_DOMAIN/auth/v1**
Lets start with a user who has multiple roles in different organizations in a multi-tenanted set up. You can use the logged in users token or the machine users token to retrieve the authorizations using the [APIs listed under user authorizations/grants in the auth API](/docs/category/apis/resources/auth/user-authorizations-grants).
Lets start with a user who has multiple roles in different organizations in a multi-tenanted set up. You can use the logged in users token or the machine users token to retrieve the authorizations using the [APIs listed under user authorizations/grants in the auth API](/docs/apis/resources/auth/user-authorizations-grants).
**Scope used:** `openid urn:zitadel:iam:org:project:id:zitadel:aud`
@ -394,7 +394,7 @@ Now we will use the management API to retrieve user roles under an admin user.
The base URL is: **https://$CUSTOM-DOMAIN/management/v1**
In [APIs listed under user grants in the management API](/docs/category/apis/resources/mgmt/user-grants), you will see that you can use the management API to retrieve and modify user grants. The two API paths that we are interested in to fetch user roles are given below.
In [APIs listed under user grants in the management API](/docs/apis/resources/mgmt/user-grants), you will see that you can use the management API to retrieve and modify user grants. The two API paths that we are interested in to fetch user roles are given below.
**Scope used:** `openid urn:zitadel:iam:org:project:id:zitadel:aud`

View File

@ -127,7 +127,7 @@ However, [client credentials authentication](./client-credentials.md) might be c
## Further resources
* Read about the [different methods to authenticate service users](./authenticate-service-users)
* [Service User API reference](/docs/category/apis/resources/mgmt/user-machine)
* [Service User API reference](/docs/apis/resources/mgmt/user-machine)
* [OIDC JWT with private key](/docs/apis/openidoauth/authn-methods#jwt-with-private-key) authentication method reference
* [Access ZITADEL APIs](../zitadel-apis/access-zitadel-apis)
* Validate access tokens with [token introspection with private key jwt](../token-introspection/private-key-jwt.mdx)

View File

@ -100,7 +100,7 @@ By following these steps and adhering to security best practices, you can effect
## Notes
* Read about the [different methods to authenticate service users](./authenticate-service-users)
* [Service User API reference](/docs/category/apis/resources/mgmt/user-machine)
* [Service User API reference](/docs/apis/resources/mgmt/user-machine)
* [OIDC client secret basic](/docs/apis/openidoauth/authn-methods#client-secret-basic) authentication method reference
* [Access ZITADEL APIs](../zitadel-apis/access-zitadel-apis)
* Validate access tokens with [token introspection with basic auth](../token-introspection/basic-auth)

View File

@ -36,9 +36,9 @@ For Identity Provider select "Other provider" and enter a Directory Name.
Follow the wizard.
Fill in the following information:
- `Identity provider Entity ID`: {your_instance_domain}/saml/v2/metadata
- `Identity provider SSO URL`: {your_instance_domain}/saml/v2/SSO
- `Public x509 certificate`: You need to download and paste the value of the certificate from {your_instance_domain}/saml/v2/certificate
- `Identity provider Entity ID`: \{your_instance_domain}/saml/v2/metadata
- `Identity provider SSO URL`: \{your_instance_domain}/saml/v2/SSO
- `Public x509 certificate`: You need to download and paste the value of the certificate from \{your_instance_domain}/saml/v2/certificate
![Add SAML details](/img/saml/atlassian/atlassian-03.png)

View File

@ -42,7 +42,7 @@ This includes:
All the information is filled out as an example, and to connect with any other environment you only have to change the
used domain, for example "example.com" with "zitadel.cloud".
Lastly, upload the certificate used to sign the reponses, provided for you under the
URL {your_instance_domain}/saml/v2/certificate.
URL \{your_instance_domain}/saml/v2/certificate.
Then just press the button "Create" and the connection on Auth0 is configured.

View File

@ -45,7 +45,7 @@ can connect to ZITADEL as a SAML2 IDP.
4. Download the ZITADEL-used certificate to sign the responses, so that AWS can validation the signature.
You can download the certificate from following
URL: {your_instance_domain}/saml/v2/certificate
URL: \{your_instance_domain}/saml/v2/certificate
5. Then upload the ".crt"-file to AWS and click "next".

View File

@ -30,7 +30,7 @@ Cloudflare will return an error "User email was not returned. API permissions ar
1. On the Cloudflare dashboard go to Zero Trust, click settings, and then select "Authentication"
2. Add a new login method with the type "OpenID Connect"
3. Fill in the required information. Check the discovery endpoint of your instance (https://{your_domain}/.well-known/openid-configuration) for the urls. As mentioned in the Cloudflare docs the Certificate Url is jwks_uri.
3. Fill in the required information. Check the discovery endpoint of your instance `https://{your_domain}/.well-known/openid-configuration` for the urls. As mentioned in the Cloudflare docs the Certificate Url is jwks_uri.
4. Disable PKCE (Cloudflare requires a client secret for PKCE, which is currently not supported)
5. Add the following claims: "openid", "profile", "email"
6. Test the connection

View File

@ -52,7 +52,7 @@ Check your application, if everything is correct, press "Create".
Complete the configuration as follows:
- `Identity provider single sign-on URL`: $CUSTOM-DOMAIN/saml/v2/SSO
- `Certificate fingerprint`: You need to download the certificate from {your_instance_domain}/saml/v2/certificate and create a SHA1 fingerprint
- `Certificate fingerprint`: You need to download the certificate from \{your_instance_domain}/saml/v2/certificate and create a SHA1 fingerprint
Save the changes.

View File

@ -68,8 +68,8 @@ Create a new .xml file with the following minimal SAML metadata contents:
Set or replace the variables with the values from the next screen as follows:
- `${ENTITYID}`: google.com/a/<your_domain>
- `${ACSURL}`: https://www.google.com/a/<your_domain>/acs
- `${ENTITYID}`: `google.com/a/<your_domain>`
- `${ACSURL}`: `https://www.google.com/a/<your_domain>/acs`
`<your_domain>` is the domain you have verified in Google Workspace.
@ -103,7 +103,7 @@ Save the settings.
Now you should be all set to verify your setup:
- Open Gmail in an incognito session with the following link: https://mail.google.com/a/<your_domain>
- Open Gmail in an incognito session with the following link: `https://mail.google.com/a/<your_domain>`
- Enter your username and credentials
- You should be redirected to Gmail and logged in
@ -165,8 +165,8 @@ Create a new .xml file with the following minimal SAML metadata contents:
Set or replace the variables with the values from the next screen as follows:
- `${ENTITYID}`: https://accounts.google.com/samlrp/metadata?rpid=<your_value>
- `${ACSURL}`: https://accounts.google.com/samlrp/acs?rpid=<your_value>
- `${ENTITYID}`: `https://accounts.google.com/samlrp/metadata?rpid=<your_value>`
- `${ACSURL}`: `https://accounts.google.com/samlrp/acs?rpid=<your_value>`
Replace `<your_value>` with the values from the [SSO profile](#entity-id-and-acs-url).
@ -200,7 +200,7 @@ Save the settings.
Now you should be all set to verify your setup:
- Open Gmail in an incognito session with the following link: https://mail.google.com/a/<your_domain>
- Open Gmail in an incognito session with the following link: `https://mail.google.com/a/<your_domain>`
- Enter your username and credentials
- You should be redirected to Gmail and logged in

View File

@ -40,7 +40,7 @@ With the following parameters
| Parameter | Description | Example value|
|---|---|---|
| OIDCProviderMetadataURL | Is the url to the discovery endpoint, which is typically located at {your-domain}/.well-known/openid-configuration| https://<your_domain>.zitadel.cloud/.well-known/openid-configuration |
| OIDCProviderMetadataURL | Is the url to the discovery endpoint, which is typically located at `{your-domain}/.well-known/openid-configuration`| `https://<your_domain>.zitadel.cloud/.well-known/openid-configuration` |
| OIDCClientID | Is the ID of the zitadel application. You can find it on the settings page of the application. | 123456789123@apache_test |
| OIDCRedirectURI | Users will be redirected to this page after successful login. If you are using localhost or any other non-https endpoint, make sure to enable development mode in ZITADEL. | https://mysecureapp.io/secure/callback |
| OIDCCryptoPassphrase | Create a secure passphrase. Consult the module's documentation for more details. | ... |

View File

@ -107,6 +107,14 @@ To configure your custom SMTP please fill the following fields:
<img src="/docs/img/guides/console/smtp.png" alt="SMTP" width="800px" />
While you create/update a SMTP provider you have the chance to test your SMTP configuration
<img src="/docs/img/guides/console/smtp_test.png" alt="SMTP" width="800px" />
In the SMTP providers table you can hover on a provider row to show buttons that allow you to activate/deactivate a provider, test your smtp settings and delete a provider
<img src="/docs/img/guides/console/smtp_table.png" alt="SMTP" width="800px" />
### SMS
No default provider is configured to send some SMS to your users. If you like to validate the phone numbers of your users make sure to add your twilio configuration by adding your Sid, Token and Sender Number.
@ -139,7 +147,7 @@ The Login Policy defines how the login process should look like and which authen
The Default Redirect URI will be used, if a user calls the login page directly.
More specifically, typically a client will initiate login with an auth request.
The auth request contains a client-id and a redirect uri, that must match the configuration in ZITADEL.
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/
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:
@ -148,7 +156,7 @@ Reasons why ZITADEL doesn't have a redirect URI:
We recommend setting your own default redirect URI, if you do not want end users to access ZITADEL console.
Change default redirect url of instance: https://<custom_domain>/ui/console/settings?id=login
Change default redirect url of instance: `https://<custom_domain>/ui/console/settings?id=login`
<img
src="/docs//img/guides/solution-scenarios/console-default-redirect.png"

View File

@ -18,7 +18,7 @@ You would have to create roles for administration and your clients in this very
## Create a project
To create a project, navigate to your organization, then projects or directly via <https://{your_domain}.zitadel.cloud/ui/console/projects>, and then click the button to create a new project.
To create a project, navigate to your organization, then projects or directly via `https://{your_domain}.zitadel.cloud/ui/console/projects`, and then click the button to create a new project.
<img
alt="Empty Project"

View File

@ -4,7 +4,7 @@ title: Feature Restrictions
New self-hosted and [ZITADEL Cloud instances](https://zitadel.com/signin) are unrestricted by default.
Self-hosters can change this default using the DefaultInstance.Restrictions configuration section.
Users with the role IAM_OWNER can change the restrictions of their instance using the [Feature Restrictions Admin API](/category/apis/resources/admin/feature-restrictions).
Users with the role IAM_OWNER can change the restrictions of their instance using the [Feature Restrictions Admin API](/apis/resources/admin/feature-restrictions).
Currently, the following restrictions are available:
- *Disallow public organization registrations* - If restricted, only users with the role IAM_OWNERS can create new organizations. The endpoint */ui/login/register/org* returns HTTP status 404 on GET requests, and 409 on POST requests.

View File

@ -232,4 +232,4 @@ The user that calls the management service must have [manager permissions](/docs
A user can be either a human user or a service user.
You can get [metadata of a user filtered by your query](/docs/apis/resources/mgmt/management-service-list-user-metadata) or [get a metadata object from a user by a specific key](/docs/apis/resources/mgmt/management-service-get-user-metadata).
The management service allows you to set and delete metadata, see the [API documentation for users](/docs/category/apis/resources/mgmt/users).
The management service allows you to set and delete metadata, see the [API documentation for users](/docs/apis/resources/mgmt/users).

View File

@ -220,7 +220,7 @@ Use metadata to store additional attributes of the users, such as organizational
:::info
Metadata must be added to users after the users were created. Currently metadata can't be added during user creation.
[API reference: User Metadata](/docs/category/apis/resources/mgmt/user-metadata)
[API reference: User Metadata](/docs/apis/resources/mgmt/user-metadata)
:::
Request metadata from the userinfo endpoint by passing the required [reserved scope](/docs/apis/openidoauth/scopes#reserved-scopes) in your auth request.
@ -232,5 +232,5 @@ You can assign roles from owned or granted projects to a user.
:::info
Authorizations must be added to users after the users were created. Currently metadata can't be added during user creation.
[API reference: User Authorization / Grants](/docs/category/apis/resources/auth/user-authorizations-grants)
[API reference: User Authorization / Grants](/docs/apis/resources/auth/user-authorizations-grants)
:::

View File

@ -94,8 +94,8 @@ We use third-party services to provide the website and our offers. An up-to-date
This website uses external payment service providers through whose platforms users and we can make payment transactions. For example via
- Stripe (<https://stripe.com/ch/privacy>)
- Bexio AG (<https://www.bexio.com/de-CH/datenschutz>)
- [Stripe](https://stripe.com/ch/privacy)
- [Bexio AG](https://www.bexio.com/de-CH/datenschutz)
As an alternative, we offer customers the option to pay by invoice instead of using external payment providers. However, this may require a positive credit check in advance.

View File

@ -18,9 +18,9 @@ The setup is tested against Docker version 20.10.17 and Docker Compose version v
By executing the commands below, you will download the following file:
<details><summary>docker-compose.yaml</summary>
\<details><summary>docker-compose.yaml</summary>
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
</details>
\</details>
```bash
# Download the docker compose example configuration.
@ -41,9 +41,9 @@ docker compose up --detach
By executing the commands below, you will download the following file:
<details><summary>docker-compose-sa.yaml</summary>
\<details><summary>docker-compose-sa.yaml</summary>
<CodeBlock language="yaml">{DockerComposeSaSource}</CodeBlock>
</details>
\</details>
```bash
# Download the docker compose example configuration.

View File

@ -21,21 +21,21 @@ The setup is tested against Docker version 20.10.17 and Docker Compose version v
By executing the commands below, you will download the following files:
<details><summary>docker-compose.yaml</summary>
\<details><summary>docker-compose.yaml</summary>
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
</details>
<details><summary>example-traefik.yaml</summary>
\</details>
\<details><summary>example-traefik.yaml</summary>
<CodeBlock language="yaml">{ExampleTraefikSource}</CodeBlock>
</details>
<details><summary>example-zitadel-config.yaml</summary>
\</details>
\<details><summary>example-zitadel-config.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELConfigSource}</CodeBlock>
</details>
<details><summary>example-zitadel-secrets.yaml</summary>
\</details>
\<details><summary>example-zitadel-secrets.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELSecretsSource}</CodeBlock>
</details>
<details><summary>example-zitadel-init-steps.yaml</summary>
\</details>
\<details><summary>example-zitadel-init-steps.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELInitStepsSource}</CodeBlock>
</details>
\</details>
```bash
# Download the docker compose example configuration.

View File

@ -8,18 +8,18 @@ The docker compose example mounts the example zitadel configuration files to the
By executing the commands below, you will download the following files:
<details><summary>docker-compose.yaml</summary>
\<details><summary>docker-compose.yaml</summary>
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
</details>
<details><summary>example-zitadel-config.yaml</summary>
\</details>
\<details><summary>example-zitadel-config.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELConfigSource}</CodeBlock>
</details>
<details><summary>example-zitadel-secrets.yaml</summary>
\</details>
\<details><summary>example-zitadel-secrets.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELSecretsSource}</CodeBlock>
</details>
<details><summary>example-zitadel-init-steps.yaml</summary>
\</details>
\<details><summary>example-zitadel-init-steps.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELInitStepsSource}</CodeBlock>
</details>
\</details>
```bash
# Download the docker compose example configuration.

View File

@ -9,12 +9,12 @@ For a secure installation with Docker Compose, [go to the loadbalancing example]
By executing the commands below, you will download the following files:
<details><summary>example-zitadel-values.yaml</summary>
\<details><summary>example-zitadel-values.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELValuesSource}</CodeBlock>
</details>
<details><summary>example-zitadel-values-secrets.yaml</summary>
\</details>
\<details><summary>example-zitadel-values-secrets.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELValuesSecretsSource}</CodeBlock>
</details>
\</details>
```bash
# Download and adjust the example configuration file containing standard configuration

View File

@ -7,15 +7,15 @@ import ExampleZITADELInitStepsSource from '!!raw-loader!./example-zitadel-init-s
By executing the commands below, you will download the following files:
<details><summary>example-zitadel-config.yaml</summary>
\<details><summary>example-zitadel-config.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELConfigSource}</CodeBlock>
</details>
<details><summary>example-zitadel-secrets.yaml</summary>
\</details>
\<details><summary>example-zitadel-secrets.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELSecretsSource}</CodeBlock>
</details>
<details><summary>example-zitadel-init-steps.yaml</summary>
\</details>
\<details><summary>example-zitadel-init-steps.yaml</summary>
<CodeBlock language="yaml">{ExampleZITADELInitStepsSource}</CodeBlock>
</details>
\</details>
```bash
# Download and adjust the example configuration file containing standard configuration

View File

@ -19,11 +19,9 @@ import Postgres from './_postgres.mdx'
>
<TabItem value="pg">
<Postgres/>
<More/>
</TabItem>
<TabItem value="crdb">
<Cockroach/>
<More/>
</TabItem>
</Tabs>

View File

@ -5,6 +5,7 @@ sidebar_label: Apache httpd
import ProxyGuideOverview from '../_proxy_guide_overview.mdx';
import ProxyGuideTLSMode from '../_proxy_guide_tls_mode.mdx';
import ProxyGuideMore from '../_proxy_guide_more.mdx';
import Compose from "!!raw-loader!./docker-compose.yaml";
import ConfigDisabled from "!!raw-loader!./httpd-disabled-tls.conf";
import ConfigExternal from "!!raw-loader!./httpd-external-tls.conf";

View File

@ -5,6 +5,7 @@ sidebar_label: NGINX
import ProxyGuideOverview from '../_proxy_guide_overview.mdx';
import ProxyGuideTLSMode from '../_proxy_guide_tls_mode.mdx';
import ProxyGuideMore from '../_proxy_guide_more.mdx';
import Compose from "!!raw-loader!./docker-compose.yaml";
import ConfigDisabled from "!!raw-loader!./nginx-disabled-tls.conf";
import ConfigExternal from "!!raw-loader!./nginx-external-tls.conf";

View File

@ -5,6 +5,7 @@ sidebar_label: Traefik
import ProxyGuideOverview from '../_proxy_guide_overview.mdx';
import ProxyGuideTLSMode from '../_proxy_guide_tls_mode.mdx';
import ProxyGuideMore from '../_proxy_guide_more.mdx';
import Compose from "!!raw-loader!./docker-compose.yaml";
import ConfigDisabled from "!!raw-loader!./traefik-disabled-tls.yaml";
import ConfigExternal from "!!raw-loader!./traefik-external-tls.yaml";

View File

@ -9,7 +9,7 @@ The usage control features are currently limited to the instance level only.
## Block Instances
You can block an instance using the [system API](/category/apis/resources/system/limits).
You can block an instance using the [system API](/apis/resources/system/limits).
Most requests to a blocked instance are rejected with the HTTP status *429 Too Many Requests* or the gRPC status *8 Resource Exhausted*.
However, requests to the [system API](/apis/introduction#system) are still allowed.
@ -55,7 +55,7 @@ DefaultInstance:
AuditLogRetention: # ZITADEL_DEFAULTINSTANCE_LIMITS_AUDITLOGRETENTION
```
You can also set a limit for [a specific virtual instance](/concepts/structure/instance#multiple-virtual-instances) using the [system API](/category/apis/resources/system/limits).
You can also set a limit for [a specific virtual instance](/concepts/structure/instance#multiple-virtual-instances) using the [system API](/apis/resources/system/limits).
## Quotas
@ -85,7 +85,7 @@ Quotas:
MaxBulkSize: 0 # ZITADEL_QUOTAS_EXECUTION_DEBOUNCE_MAXBULKSIZE
```
Once you have activated the quotas feature, you can configure quotas [for your virtual instances](/concepts/structure/instance#multiple-virtual-instances) using the [system API](/category/apis/resources/system/quotas) or the *DefaultInstances.Quotas* section.
Once you have activated the quotas feature, you can configure quotas [for your virtual instances](/concepts/structure/instance#multiple-virtual-instances) using the [system API](/apis/resources/system/quotas) or the *DefaultInstances.Quotas* section.
The following snippets shows the defaults:
```yaml

View File

@ -4,8 +4,9 @@ module.exports = {
trailingSlash: false,
url: "https://zitadel.com",
baseUrl: "/docs",
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
onBrokenLinks: "warn",
onBrokenAnchors: "warn",
onBrokenMarkdownLinks: "throw",
favicon: "img/favicon.ico",
organizationName: "zitadel",
projectName: "zitadel",
@ -203,6 +204,11 @@ module.exports = {
syntax: 'typescript',
tsx: true,
},
transform: {
react: {
runtime: 'automatic',
},
},
target: 'es2017',
},
module: {
@ -223,7 +229,7 @@ module.exports = {
showLastUpdateTime: true,
editUrl: "https://github.com/zitadel/zitadel/edit/main/docs/",
remarkPlugins: [require("mdx-mermaid")],
docLayoutComponent: "@theme/DocPage",
docItemComponent: '@theme/ApiItem'
},
theme: {
@ -245,6 +251,7 @@ module.exports = {
outputDir: "docs/apis/resources/auth",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
mgmt: {
@ -252,6 +259,7 @@ module.exports = {
outputDir: "docs/apis/resources/mgmt",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
admin: {
@ -259,6 +267,7 @@ module.exports = {
outputDir: "docs/apis/resources/admin",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
system: {
@ -266,6 +275,7 @@ module.exports = {
outputDir: "docs/apis/resources/system",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
user: {
@ -273,6 +283,7 @@ module.exports = {
outputDir: "docs/apis/resources/user_service",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
session: {
@ -280,6 +291,7 @@ module.exports = {
outputDir: "docs/apis/resources/session_service",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
oidc: {
@ -287,6 +299,7 @@ module.exports = {
outputDir: "docs/apis/resources/oidc_service",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
settings: {
@ -294,6 +307,7 @@ module.exports = {
outputDir: "docs/apis/resources/settings_service",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
user_schema: {
@ -301,6 +315,7 @@ module.exports = {
outputDir: "docs/apis/resources/user_schema_service_v3",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
user_v3: {
@ -308,6 +323,7 @@ module.exports = {
outputDir: "docs/apis/resources/user_service_v3",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
action_v3: {
@ -315,6 +331,7 @@ module.exports = {
outputDir: "docs/apis/resources/action_service_v3",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
feature_v2: {
@ -322,6 +339,7 @@ module.exports = {
outputDir: "docs/apis/resources/feature_service_v2",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
},
},
},

View File

@ -5,39 +5,45 @@
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"start:api": "yarn generate && docusaurus start",
"build": "yarn generate && docusaurus build",
"start:api": "yarn run generate && docusaurus start",
"build": "yarn run generate && docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"generate": "yarn generate:grpc && yarn generate:apidocs && yarn generate:configdocs",
"generate": "yarn run generate:grpc && yarn run generate:apidocs && yarn run generate:configdocs",
"generate:grpc": "buf generate ../proto",
"generate:apidocs": "docusaurus clean-api-docs all && docusaurus gen-api-docs all",
"generate:configdocs": "cp -r ../cmd/defaults.yaml ./docs/self-hosting/manage/configure/ && cp -r ../cmd/setup/steps.yaml ./docs/self-hosting/manage/configure/"
"generate:apidocs": "docusaurus gen-api-docs all",
"generate:configdocs": "cp -r ../cmd/defaults.yaml ./docs/self-hosting/manage/configure/ && cp -r ../cmd/setup/steps.yaml ./docs/self-hosting/manage/configure/",
"generate:re-gen": "yarn clean-all && yarn gen-all",
"generate:clean-all": "docusaurus clean-api-docs all"
},
"dependencies": {
"@bufbuild/buf": "^1.14.0",
"@docusaurus/core": "2.2.0",
"@docusaurus/preset-classic": "2.2.0",
"@docusaurus/theme-search-algolia": "2.2.0",
"@docusaurus/core": "3.4.0",
"@docusaurus/preset-classic": "3.4.0",
"@docusaurus/theme-mermaid": "3.4.0",
"@docusaurus/theme-search-algolia": "3.4.0",
"@headlessui/react": "^1.7.4",
"@heroicons/react": "^2.0.13",
"@mdx-js/react": "^3.0.0",
"@saucelabs/theme-github-codeblock": "^0.2.3",
"@swc/core": "^1.3.74",
"autoprefixer": "^10.4.13",
"clsx": "^1.2.1",
"docusaurus-plugin-image-zoom": "^1.0.1",
"docusaurus-plugin-openapi-docs": "^1.7.3",
"docusaurus-theme-openapi-docs": "^1.7.3",
"mdx-mermaid": "^1.1.0",
"docusaurus-plugin-openapi-docs": "3.0.0-beta.10",
"docusaurus-theme-openapi-docs": "3.0.0-beta.10",
"mdx-mermaid": "^2.0.0",
"mermaid": "^10.9.1",
"postcss": "^8.4.31",
"prism-react-renderer": "^2.1.0",
"raw-loader": "^4.0.2",
"react": "17.0.2",
"react": "^18.2.0",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "17.0.2",
"react-dom": "^18.2.0",
"react-player": "^2.15.1",
"sitemap": "7.1.1",
"swc-loader": "^0.2.3",
@ -56,7 +62,9 @@
]
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.2.0",
"@docusaurus/module-type-aliases": "3.4.0",
"@docusaurus/types": "3.4.0",
"tailwindcss": "^3.2.4"
}
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

View File

@ -585,7 +585,7 @@ module.exports = {
description:
"The authentication API (aka Auth API) is used for all operations on the currently logged in user. The user id is taken from the sub claim in the token.",
},
items: require("./docs/apis/resources/auth/sidebar.js"),
items: require("./docs/apis/resources/auth/sidebar.ts"),
},
{
type: "category",
@ -597,7 +597,7 @@ module.exports = {
description:
"The management API is as the name states the interface where systems can mutate IAM objects like, organizations, projects, clients, users and so on if they have the necessary access rights. To identify the current organization you can send a header x-zitadel-orgid or if no header is set, the organization of the authenticated user is set.",
},
items: require("./docs/apis/resources/mgmt/sidebar.js"),
items: require("./docs/apis/resources/mgmt/sidebar.ts"),
},
{
type: "category",
@ -609,7 +609,7 @@ module.exports = {
description:
"This API is intended to configure and manage one ZITADEL instance itself.",
},
items: require("./docs/apis/resources/admin/sidebar.js"),
items: require("./docs/apis/resources/admin/sidebar.ts"),
},
{
type: "category",
@ -623,7 +623,7 @@ module.exports = {
"\n" +
"Checkout the guide how to access the ZITADEL System API.",
},
items: require("./docs/apis/resources/system/sidebar.js"),
items: require("./docs/apis/resources/system/sidebar.ts"),
},
],
},
@ -648,7 +648,7 @@ module.exports = {
"\n" +
"This project is in beta state. It can AND will continue breaking until the services provide the same functionality as the current login.",
},
items: require("./docs/apis/resources/user_service/sidebar.js"),
items: require("./docs/apis/resources/user_service/sidebar.ts"),
},
{
type: "category",
@ -662,7 +662,7 @@ module.exports = {
"\n" +
"This project is in beta state. It can AND will continue breaking until the services provide the same functionality as the current login.",
},
items: require("./docs/apis/resources/session_service/sidebar.js"),
items: require("./docs/apis/resources/session_service/sidebar.ts"),
},
{
type: "category",
@ -676,7 +676,7 @@ module.exports = {
"\n" +
"This project is in beta state. It can AND will continue breaking until the services provide the same functionality as the current login.",
},
items: require("./docs/apis/resources/oidc_service/sidebar.js"),
items: require("./docs/apis/resources/oidc_service/sidebar.ts"),
},
{
type: "category",
@ -690,7 +690,7 @@ module.exports = {
"\n" +
"This project is in beta state. It can AND will continue to break until the services provide the same functionality as the current login.",
},
items: require("./docs/apis/resources/settings_service/sidebar.js"),
items: require("./docs/apis/resources/settings_service/sidebar.ts"),
},
{
type: "category",
@ -704,7 +704,7 @@ module.exports = {
"\n" +
"This project is in beta state. It can AND will continue breaking until a stable version is released.",
},
items: require("./docs/apis/resources/feature_service_v2/sidebar.js"),
items: require("./docs/apis/resources/feature_service_v2/sidebar.ts"),
},
],
},
@ -729,7 +729,7 @@ module.exports = {
"\n" +
"This project is in Preview state. It can AND will continue breaking until the service provides the same functionality as the v1 and v2 user services.",
},
items: require("./docs/apis/resources/user_schema_service_v3/sidebar.js"),
items: require("./docs/apis/resources/user_schema_service_v3/sidebar.ts"),
},
{
type: "category",
@ -743,7 +743,7 @@ module.exports = {
"\n" +
"This project is in Preview state. It can AND will continue breaking until the service provides the same functionality as the v1 and v2 user services.",
},
items: require("./docs/apis/resources/user_service_v3/sidebar.js"),
items: require("./docs/apis/resources/user_service_v3/sidebar.ts"),
},
{
type: "category",
@ -757,7 +757,7 @@ module.exports = {
"\n" +
"This project is in Preview state. It can AND will continue breaking until the services provide the same functionality as the current actions.",
},
items: require("./docs/apis/resources/action_service_v3/sidebar.js"),
items: require("./docs/apis/resources/action_service_v3/sidebar.ts"),
},
],
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -19,6 +19,7 @@
],
"redirects": [
{ "source": "/", "destination": "/docs" },
{ "source": "/docs/category/apis/:slug*", "destination": "/docs/apis/:slug*", "permanent": true },
{ "source": "/docs/apis/mgmt/:slug*", "destination": "/docs/apis/resources/mgmt/:slug*", "permanent": true },
{ "source": "/docs/apis/auth/:slug*", "destination": "/docs/apis/resources/auth/:slug*", "permanent": true },
{ "source": "/docs/apis/system/:slug*", "destination": "/docs/apis/resources/system/:slug*", "permanent": true },

File diff suppressed because it is too large Load Diff

View File

@ -26,10 +26,11 @@ describe('instance notifications', () => {
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org: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('[data-e2e="continue-to-2nd-form"]').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="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="close-button"]').click();
@ -44,12 +45,13 @@ describe('instance notifications', () => {
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('[data-e2e="continue-to-2nd-form"]').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="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="close-button"]').click();
@ -77,10 +79,11 @@ describe('instance notifications', () => {
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('[data-e2e="continue-to-2nd-form"]').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="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="close-button"]').click();
@ -140,10 +143,11 @@ describe('instance notifications', () => {
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org: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('[data-e2e="continue-to-2nd-form"]').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="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="activate-button"]').click();
@ -159,6 +163,7 @@ describe('instance notifications', () => {
let rowSelector = `tr:contains('mailgun')`;
cy.visit(smtpPath);
cy.get(rowSelector).click();
cy.get('[data-e2e="continue-to-2nd-form"]').click();
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();

2
go.mod
View File

@ -179,7 +179,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 // indirect
github.com/muesli/kmeans v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.54.0 // indirect

View File

@ -0,0 +1,492 @@
//go:build integration
package admin_test
import (
"testing"
"time"
"github.com/brianvoe/gofakeit/v6"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/admin"
"github.com/zitadel/zitadel/pkg/grpc/management"
v1 "github.com/zitadel/zitadel/pkg/grpc/v1"
)
func TestServer_ImportData(t *testing.T) {
orgIDs := generateIDs(10)
projectIDs := generateIDs(10)
userIDs := generateIDs(10)
grantIDs := generateIDs(10)
tests := []struct {
name string
req *admin.ImportDataRequest
want *admin.ImportDataResponse
wantErr bool
}{
{
name: "success",
req: &admin.ImportDataRequest{
Data: &admin.ImportDataRequest_DataOrgs{
DataOrgs: &admin.ImportDataOrg{
Orgs: []*admin.DataOrg{
{
OrgId: orgIDs[0],
Org: &management.AddOrgRequest{
Name: gofakeit.ProductName(),
},
Projects: []*v1.DataProject{
{
ProjectId: projectIDs[0],
Project: &management.AddProjectRequest{
Name: gofakeit.AppName(),
ProjectRoleAssertion: true,
},
},
{
ProjectId: projectIDs[1],
Project: &management.AddProjectRequest{
Name: gofakeit.AppName(),
ProjectRoleAssertion: false,
},
},
},
ProjectRoles: []*management.AddProjectRoleRequest{
{
ProjectId: projectIDs[0],
RoleKey: "role1",
DisplayName: "role1",
},
{
ProjectId: projectIDs[0],
RoleKey: "role2",
DisplayName: "role2",
},
{
ProjectId: projectIDs[1],
RoleKey: "role3",
DisplayName: "role3",
},
{
ProjectId: projectIDs[1],
RoleKey: "role4",
DisplayName: "role4",
},
},
HumanUsers: []*v1.DataHumanUser{
{
UserId: userIDs[0],
User: &management.ImportHumanUserRequest{
UserName: gofakeit.Username(),
Profile: &management.ImportHumanUserRequest_Profile{
FirstName: gofakeit.FirstName(),
LastName: gofakeit.LastName(),
DisplayName: gofakeit.Username(),
PreferredLanguage: gofakeit.LanguageBCP(),
},
Email: &management.ImportHumanUserRequest_Email{
Email: gofakeit.Email(),
IsEmailVerified: true,
},
},
},
{
UserId: userIDs[1],
User: &management.ImportHumanUserRequest{
UserName: gofakeit.Username(),
Profile: &management.ImportHumanUserRequest_Profile{
FirstName: gofakeit.FirstName(),
LastName: gofakeit.LastName(),
DisplayName: gofakeit.Username(),
PreferredLanguage: gofakeit.LanguageBCP(),
},
Email: &management.ImportHumanUserRequest_Email{
Email: gofakeit.Email(),
IsEmailVerified: true,
},
},
},
},
ProjectGrants: []*v1.DataProjectGrant{
{
GrantId: grantIDs[0],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[0],
GrantedOrgId: orgIDs[1],
RoleKeys: []string{"role1", "role2"},
},
},
{
GrantId: grantIDs[1],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[1],
GrantedOrgId: orgIDs[1],
RoleKeys: []string{"role3", "role4"},
},
},
{
GrantId: grantIDs[2],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[0],
GrantedOrgId: orgIDs[2],
RoleKeys: []string{"role1", "role2"},
},
},
{
GrantId: grantIDs[3],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[1],
GrantedOrgId: orgIDs[2],
RoleKeys: []string{"role3", "role4"},
},
},
},
},
{
OrgId: orgIDs[1],
Org: &management.AddOrgRequest{
Name: gofakeit.ProductName(),
},
UserGrants: []*management.AddUserGrantRequest{
{
UserId: userIDs[0],
ProjectId: projectIDs[0],
ProjectGrantId: grantIDs[0],
},
{
UserId: userIDs[0],
ProjectId: projectIDs[1],
ProjectGrantId: grantIDs[1],
},
},
},
{
OrgId: orgIDs[2],
Org: &management.AddOrgRequest{
Name: gofakeit.ProductName(),
},
UserGrants: []*management.AddUserGrantRequest{
{
UserId: userIDs[1],
ProjectId: projectIDs[0],
ProjectGrantId: grantIDs[2],
},
{
UserId: userIDs[1],
ProjectId: projectIDs[1],
ProjectGrantId: grantIDs[3],
},
},
},
},
},
},
Timeout: time.Minute.String(),
},
want: &admin.ImportDataResponse{
Success: &admin.ImportDataSuccess{
Orgs: []*admin.ImportDataSuccessOrg{
{
OrgId: orgIDs[0],
ProjectIds: projectIDs[0:2],
ProjectRoles: []string{
projectIDs[0] + "_role1",
projectIDs[0] + "_role2",
projectIDs[1] + "_role3",
projectIDs[1] + "_role4",
},
HumanUserIds: userIDs[0:2],
ProjectGrants: []*admin.ImportDataSuccessProjectGrant{
{
GrantId: grantIDs[0],
ProjectId: projectIDs[0],
OrgId: orgIDs[1],
},
{
GrantId: grantIDs[1],
ProjectId: projectIDs[1],
OrgId: orgIDs[1],
},
{
GrantId: grantIDs[2],
ProjectId: projectIDs[0],
OrgId: orgIDs[2],
},
{
GrantId: grantIDs[3],
ProjectId: projectIDs[1],
OrgId: orgIDs[2],
},
},
},
{
OrgId: orgIDs[1],
UserGrants: []*admin.ImportDataSuccessUserGrant{
{
ProjectId: projectIDs[0],
UserId: userIDs[0],
},
{
UserId: userIDs[0],
ProjectId: projectIDs[1],
},
},
},
{
OrgId: orgIDs[2],
UserGrants: []*admin.ImportDataSuccessUserGrant{
{
ProjectId: projectIDs[0],
UserId: userIDs[1],
},
{
UserId: userIDs[1],
ProjectId: projectIDs[1],
},
},
},
},
},
},
},
{
name: "duplicate project grant error",
req: &admin.ImportDataRequest{
Data: &admin.ImportDataRequest_DataOrgs{
DataOrgs: &admin.ImportDataOrg{
Orgs: []*admin.DataOrg{
{
OrgId: orgIDs[3],
Org: &management.AddOrgRequest{
Name: gofakeit.ProductName(),
},
Projects: []*v1.DataProject{
{
ProjectId: projectIDs[2],
Project: &management.AddProjectRequest{
Name: gofakeit.AppName(),
ProjectRoleAssertion: true,
},
},
{
ProjectId: projectIDs[3],
Project: &management.AddProjectRequest{
Name: gofakeit.AppName(),
ProjectRoleAssertion: false,
},
},
},
ProjectRoles: []*management.AddProjectRoleRequest{
{
ProjectId: projectIDs[2],
RoleKey: "role1",
DisplayName: "role1",
},
{
ProjectId: projectIDs[2],
RoleKey: "role2",
DisplayName: "role2",
},
{
ProjectId: projectIDs[3],
RoleKey: "role3",
DisplayName: "role3",
},
{
ProjectId: projectIDs[3],
RoleKey: "role4",
DisplayName: "role4",
},
},
ProjectGrants: []*v1.DataProjectGrant{
{
GrantId: grantIDs[4],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[2],
GrantedOrgId: orgIDs[4],
RoleKeys: []string{"role1", "role2"},
},
},
{
GrantId: grantIDs[4],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[2],
GrantedOrgId: orgIDs[4],
RoleKeys: []string{"role1", "role2"},
},
},
},
},
},
},
},
Timeout: time.Minute.String(),
},
want: &admin.ImportDataResponse{
Errors: []*admin.ImportDataError{
{
Type: "project_grant",
Id: orgIDs[3] + "_" + projectIDs[2] + "_" + orgIDs[4],
Message: "ID=V3-DKcYh Message=Errors.Project.Grant.AlreadyExists Parent=(ERROR: duplicate key value violates unique constraint \"unique_constraints_pkey\" (SQLSTATE 23505))",
},
},
Success: &admin.ImportDataSuccess{
Orgs: []*admin.ImportDataSuccessOrg{
{
OrgId: orgIDs[3],
ProjectIds: projectIDs[2:4],
ProjectRoles: []string{
projectIDs[2] + "_role1",
projectIDs[2] + "_role2",
projectIDs[3] + "_role3",
projectIDs[3] + "_role4",
},
ProjectGrants: []*admin.ImportDataSuccessProjectGrant{
{
GrantId: grantIDs[4],
ProjectId: projectIDs[2],
OrgId: orgIDs[4],
},
},
},
},
},
},
},
{
name: "duplicate project grant member error",
req: &admin.ImportDataRequest{
Data: &admin.ImportDataRequest_DataOrgs{
DataOrgs: &admin.ImportDataOrg{
Orgs: []*admin.DataOrg{
{
OrgId: orgIDs[5],
Org: &management.AddOrgRequest{
Name: gofakeit.ProductName(),
},
Projects: []*v1.DataProject{
{
ProjectId: projectIDs[4],
Project: &management.AddProjectRequest{
Name: gofakeit.AppName(),
ProjectRoleAssertion: true,
},
},
},
ProjectRoles: []*management.AddProjectRoleRequest{
{
ProjectId: projectIDs[4],
RoleKey: "role1",
DisplayName: "role1",
},
},
HumanUsers: []*v1.DataHumanUser{
{
UserId: userIDs[2],
User: &management.ImportHumanUserRequest{
UserName: gofakeit.Username(),
Profile: &management.ImportHumanUserRequest_Profile{
FirstName: gofakeit.FirstName(),
LastName: gofakeit.LastName(),
DisplayName: gofakeit.Username(),
PreferredLanguage: gofakeit.LanguageBCP(),
},
Email: &management.ImportHumanUserRequest_Email{
Email: gofakeit.Email(),
IsEmailVerified: true,
},
},
},
},
ProjectGrants: []*v1.DataProjectGrant{
{
GrantId: grantIDs[5],
ProjectGrant: &management.AddProjectGrantRequest{
ProjectId: projectIDs[4],
GrantedOrgId: orgIDs[6],
RoleKeys: []string{"role1", "role2"},
},
},
},
ProjectGrantMembers: []*management.AddProjectGrantMemberRequest{
{
ProjectId: projectIDs[4],
GrantId: grantIDs[5],
UserId: userIDs[2],
Roles: []string{"PROJECT_GRANT_OWNER"},
},
{
ProjectId: projectIDs[4],
GrantId: grantIDs[5],
UserId: userIDs[2],
Roles: []string{"PROJECT_GRANT_OWNER"},
},
},
},
},
},
},
Timeout: time.Minute.String(),
},
want: &admin.ImportDataResponse{
Errors: []*admin.ImportDataError{
{
Type: "project_grant_member",
Id: orgIDs[5] + "_" + projectIDs[4] + "_" + grantIDs[5] + "_" + userIDs[2],
Message: "ID=V3-DKcYh Message=Errors.Project.Member.AlreadyExists Parent=(ERROR: duplicate key value violates unique constraint \"unique_constraints_pkey\" (SQLSTATE 23505))",
},
},
Success: &admin.ImportDataSuccess{
Orgs: []*admin.ImportDataSuccessOrg{
{
OrgId: orgIDs[5],
ProjectIds: projectIDs[4:5],
ProjectRoles: []string{
projectIDs[4] + "_role1",
},
HumanUserIds: userIDs[2:3],
ProjectGrants: []*admin.ImportDataSuccessProjectGrant{
{
GrantId: grantIDs[5],
ProjectId: projectIDs[4],
OrgId: orgIDs[6],
},
},
ProjectGrantMembers: []*admin.ImportDataSuccessProjectGrantMember{
{
ProjectId: projectIDs[4],
GrantId: grantIDs[5],
UserId: userIDs[2],
},
},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.ImportData(AdminCTX, tt.req)
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
integration.EqualProto(t, tt.want, got)
})
}
}
func generateIDs(n int) []string {
ids := make([]string, n)
for i := range ids {
ids[i] = uuid.NewString()
}
return ids
}

View File

@ -5,6 +5,7 @@ import (
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/grpc/object"
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
)
@ -128,3 +129,29 @@ func (s *Server) DeactivateSMTPConfig(ctx context.Context, req *admin_pb.Deactiv
Details: object.DomainToAddDetailsPb(result),
}, nil
}
func (s *Server) TestSMTPConfigById(ctx context.Context, req *admin_pb.TestSMTPConfigByIdRequest) (*admin_pb.TestSMTPConfigByIdResponse, error) {
err := s.command.TestSMTPConfigById(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress)
if err != nil {
return nil, err
}
return &admin_pb.TestSMTPConfigByIdResponse{}, nil
}
func (s *Server) TestSMTPConfig(ctx context.Context, req *admin_pb.TestSMTPConfigRequest) (*admin_pb.TestSMTPConfigResponse, error) {
config := smtp.Config{}
config.Tls = req.Tls
config.From = req.SenderAddress
config.FromName = req.SenderName
config.SMTP.Host = req.Host
config.SMTP.User = req.User
config.SMTP.Password = req.Password
err := s.command.TestSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress, &config)
if err != nil {
return nil, err
}
return &admin_pb.TestSMTPConfigResponse{}, nil
}

View File

@ -156,7 +156,7 @@ func StartCommands(
defaultRefreshTokenLifetime: defaultRefreshTokenLifetime,
defaultRefreshTokenIdleLifetime: defaultRefreshTokenIdleLifetime,
defaultSecretGenerators: defaultSecretGenerators,
samlCertificateAndKeyGenerator: samlCertificateAndKeyGenerator(defaults.KeyConfig.Size),
samlCertificateAndKeyGenerator: samlCertificateAndKeyGenerator(defaults.KeyConfig.CertificateSize, defaults.KeyConfig.CertificateLifetime),
// always true for now until we can check with an eventlist
EventExisting: func(event string) bool { return true },
// always true for now until we can check with an eventlist
@ -223,7 +223,7 @@ func exists(ctx context.Context, filter preparation.FilterToQueryReducer, wm exi
return wm.Exists(), nil
}
func samlCertificateAndKeyGenerator(keySize int) func(id string) ([]byte, []byte, error) {
func samlCertificateAndKeyGenerator(keySize int, lifetime time.Duration) func(id string) ([]byte, []byte, error) {
return func(id string) ([]byte, []byte, error) {
priv, pub, err := crypto.GenerateKeyPair(keySize)
if err != nil {
@ -234,12 +234,15 @@ func samlCertificateAndKeyGenerator(keySize int) func(id string) ([]byte, []byte
if err != nil {
return nil, nil, err
}
now := time.Now()
template := x509.Certificate{
SerialNumber: big.NewInt(int64(serial)),
Subject: pkix.Name{
Organization: []string{"ZITADEL"},
SerialNumber: id,
},
NotBefore: now,
NotAfter: now.Add(lifetime),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,

View File

@ -17,14 +17,6 @@ func (c *Commands) AddProjectGrantWithID(ctx context.Context, grant *domain.Proj
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
existingMember, err := c.projectGrantWriteModelByID(ctx, grantID, grant.AggregateID, resourceOwner)
if err != nil && !zerrors.IsNotFound(err) {
return nil, err
}
if existingMember != nil && existingMember.State != domain.ProjectGrantStateUnspecified {
return nil, zerrors.ThrowInvalidArgument(nil, "PROJECT-2b8fs", "Errors.Project.Grant.AlreadyExisting")
}
return c.addProjectGrantWithID(ctx, grant, grantID, resourceOwner)
}

View File

@ -26,13 +26,6 @@ func (c *Commands) AddProjectGrantMember(ctx context.Context, member *domain.Pro
return nil, err
}
addedMember := NewProjectGrantMemberWriteModel(member.AggregateID, member.UserID, member.GrantID)
err = c.eventstore.FilterToQueryReducer(ctx, addedMember)
if err != nil {
return nil, err
}
if addedMember.State == domain.MemberStateActive {
return nil, zerrors.ThrowAlreadyExists(nil, "PROJECT-16dVN", "Errors.Project.Member.AlreadyExists")
}
projectAgg := ProjectAggregateFromWriteModel(&addedMember.WriteModel)
pushedEvents, err := c.eventstore.Push(
ctx,

View File

@ -104,58 +104,6 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
err: zerrors.IsPreconditionFailed,
},
},
{
name: "member already exists, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username1",
"firstname1",
"lastname1",
"nickname1",
"displayname1",
language.German,
domain.GenderMale,
"email1",
true,
),
),
),
expectFilter(
eventFromEventPusher(
project.NewProjectGrantMemberAddedEvent(context.Background(),
&project.NewAggregate("project1", "org1").Aggregate,
"user1",
"projectgrant1",
),
),
),
),
zitadelRoles: []authz.RoleMapping{
{
Role: "PROJECT_GRANT_OWNER",
},
},
},
args: args{
ctx: context.Background(),
member: &domain.ProjectGrantMember{
ObjectRoot: models.ObjectRoot{
AggregateID: "project1",
},
GrantID: "projectgrant1",
UserID: "user1",
Roles: []string{"PROJECT_GRANT_OWNER"},
},
},
res: res{
err: zerrors.IsErrorAlreadyExists,
},
},
{
name: "member add uniqueconstraint err, already exists",
fields: fields{
@ -177,7 +125,6 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
),
),
),
expectFilter(),
expectPushFailed(zerrors.ThrowAlreadyExists(nil, "ERROR", "internal"),
project.NewProjectGrantMemberAddedEvent(context.Background(),
&project.NewAggregate("project1", "").Aggregate,
@ -229,7 +176,6 @@ func TestCommandSide_AddProjectGrantMember(t *testing.T) {
),
),
),
expectFilter(),
expectPush(
project.NewProjectGrantMemberAddedEvent(context.Background(),
&project.NewAggregate("project1", "").Aggregate,

View File

@ -285,6 +285,89 @@ func (c *Commands) RemoveSMTPConfig(ctx context.Context, instanceID, id string)
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
}
func (c *Commands) TestSMTPConfig(ctx context.Context, instanceID, id, email string, config *smtp.Config) error {
password := config.SMTP.Password
if email == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-p9uy", "Errors.SMTPConfig.TestEmailNotFound")
}
if id == "" && password == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-p9kj", "Errors.SMTPConfig.TestPassword")
}
// If the password is not sent it'd mean that the password hasn't been changed for
// the stored configuration identified by its id so we can try to retrieve it
if id != "" && password == "" {
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
if err != nil {
return err
}
if !smtpConfigWriteModel.State.Exists() {
return zerrors.ThrowNotFound(nil, "SMTP-p9cc", "Errors.SMTPConfig.NotFound")
}
password, err = crypto.DecryptString(smtpConfigWriteModel.Password, c.smtpEncryption)
if err != nil {
return err
}
}
config.SMTP.Password = password
// Try to send an email
err := smtp.TestConfiguration(config, email)
if err != nil {
return err
}
return nil
}
func (c *Commands) TestSMTPConfigById(ctx context.Context, instanceID, id, email string) error {
if id == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-99oki", "Errors.IDMissing")
}
if email == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-99yth", "Errors.SMTPConfig.TestEmailNotFound")
}
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
if err != nil {
return err
}
if !smtpConfigWriteModel.State.Exists() {
return zerrors.ThrowNotFound(nil, "SMTP-99klw", "Errors.SMTPConfig.NotFound")
}
password, err := crypto.DecryptString(smtpConfigWriteModel.Password, c.smtpEncryption)
if err != nil {
return err
}
smtpConfig := &smtp.Config{
Description: smtpConfigWriteModel.Description,
Tls: smtpConfigWriteModel.TLS,
From: smtpConfigWriteModel.SenderAddress,
FromName: smtpConfigWriteModel.SenderName,
SMTP: smtp.SMTP{
Host: smtpConfigWriteModel.Host,
User: smtpConfigWriteModel.User,
Password: password,
},
}
// Try to send an email
err = smtp.TestConfiguration(smtpConfig, email)
if err != nil {
return err
}
return nil
}
func checkSenderAddress(writeModel *IAMSMTPConfigWriteModel) error {
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
return nil

View File

@ -1196,6 +1196,329 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
}
}
func TestCommandSide_TestSMTPConfig(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
alg crypto.EncryptionAlgorithm
}
type args struct {
ctx context.Context
instanceID string
id string
email string
config smtp.Config
}
type res struct {
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: "email empty, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
instanceID: "INSTANCE",
id: "id",
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "if password is empty, smtp id must not",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
id: "",
email: "email",
config: smtp.Config{
From: "test@example,com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "",
Host: "example.com:2525",
},
},
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "password empty and smtp config not found, error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
id: "id",
email: "email",
config: smtp.Config{
From: "test@example,com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "",
Host: "example.com:2525",
},
},
},
res: res{
err: zerrors.IsNotFound,
},
},
{
name: "valid new smtp config, wrong auth, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
email: "email",
config: smtp.Config{
From: "test@example.com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "password",
Host: "mail.smtp2go.com:2525",
},
},
},
res: res{
err: zerrors.IsInternal,
},
},
{
name: "valid smtp config using stored password, wrong auth, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewSMTPConfigAddedEvent(
context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
"ID",
"test",
true,
"from",
"name",
"",
"mail.smtp2go.com:2525",
"user",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("password"),
},
),
),
),
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
email: "email",
id: "ID",
config: smtp.Config{
From: "test@example.com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "",
Host: "mail.smtp2go.com:2525",
},
},
},
res: res{
err: zerrors.IsInternal,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
smtpEncryption: tt.fields.alg,
}
err := r.TestSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.email, &tt.args.config)
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)
}
})
}
}
func TestCommandSide_TestSMTPConfigById(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
alg crypto.EncryptionAlgorithm
}
type args struct {
ctx context.Context
instanceID string
id string
email string
}
type res struct {
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: "email empty, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
instanceID: "INSTANCE",
id: "id",
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "smtp config not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
id: "id",
email: "email",
},
res: res{
err: zerrors.IsNotFound,
},
},
{
name: "valid smtp config, wrong auth, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewSMTPConfigAddedEvent(
context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
"ID",
"test",
true,
"from",
"name",
"",
"mail.smtp2go.com:2525",
"user",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("password"),
},
),
),
),
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
id: "ID",
instanceID: "INSTANCE",
email: "test@example.com",
},
res: res{
err: zerrors.IsInternal,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
smtpEncryption: tt.fields.alg,
}
err := r.TestSMTPConfigById(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.email)
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)
}
})
}
}
func newSMTPConfigChangedEvent(ctx context.Context, id, description string, tls bool, fromAddress, fromName, replyTo, host, user string) *instance.SMTPConfigChangedEvent {
changes := []instance.SMTPConfigChanges{
instance.ChangeSMTPConfigDescription(description),

View File

@ -4,7 +4,10 @@ import (
"testing"
"time"
"github.com/pmezard/go-difflib/difflib"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
@ -71,3 +74,36 @@ func AssertListDetails[D ListDetailsMsg](t testing.TB, expected, actual D) {
assert.WithinRange(t, gotCD, wantCD.Add(-time.Minute), wantCD.Add(time.Minute))
}
}
// EqualProto is inspired by [assert.Equal], only that it tests equality of a proto message.
// A message diff is printed on the error test log if the messages are not equal.
//
// As [assert.Equal] is based on reflection, comparing 2 proto messages sometimes fails,
// due to their internal state.
// Expected messages are usually with a vanilla state, eg only exported fields contain data.
// Actual messages obtained from the gRPC client had unexported fields with data.
// This makes them hard to compare.
func EqualProto(t testing.TB, expected, actual proto.Message) bool {
t.Helper()
if proto.Equal(expected, actual) {
return true
}
t.Errorf("Proto messages not equal: %s", diffProto(expected, actual))
return false
}
func diffProto(expected, actual proto.Message) string {
diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
A: difflib.SplitLines(protojson.Format(expected)),
B: difflib.SplitLines(protojson.Format(actual)),
FromFile: "Expected",
FromDate: "",
ToFile: "Actual",
ToDate: "",
Context: 1,
})
if err != nil {
panic(err)
}
return "\n\nDiff:\n" + diff
}

View File

@ -41,22 +41,22 @@ func (email *Email) HandleMessage(message channels.Message) error {
defer email.smtpClient.Close()
emailMsg, ok := message.(*messages.Email)
if !ok {
return zerrors.ThrowInternal(nil, "EMAIL-s8JLs", "message is not EmailMessage")
return zerrors.ThrowInternal(nil, "EMAIL-s8JLs", "Errors.SMTP.NotEmailMessage")
}
if emailMsg.Content == "" || emailMsg.Subject == "" || len(emailMsg.Recipients) == 0 {
return zerrors.ThrowInternalf(nil, "EMAIL-zGemZ", "subject, recipients and content must be set but got subject %s, recipients length %d and content length %d", emailMsg.Subject, len(emailMsg.Recipients), len(emailMsg.Content))
return zerrors.ThrowInternal(nil, "EMAIL-zGemZ", "Errors.SMTP.RequiredAttributes")
}
emailMsg.SenderEmail = email.senderAddress
emailMsg.SenderName = email.senderName
emailMsg.ReplyToAddress = email.replyToAddress
// To && From
if err := email.smtpClient.Mail(emailMsg.SenderEmail); err != nil {
return zerrors.ThrowInternalf(err, "EMAIL-s3is3", "could not set sender: %v", emailMsg.SenderEmail)
return zerrors.ThrowInternal(err, "EMAIL-s3is3", "Errors.SMTP.CouldNotSetSender")
}
for _, recp := range append(append(emailMsg.Recipients, emailMsg.CC...), emailMsg.BCC...) {
if err := email.smtpClient.Rcpt(recp); err != nil {
return zerrors.ThrowInternalf(err, "EMAIL-s4is4", "could not set recipient: %v", recp)
return zerrors.ThrowInternal(err, "EMAIL-s4is4", "Errors.SMTP.CouldNotSetRecipient")
}
}
@ -87,7 +87,7 @@ func (email *Email) HandleMessage(message channels.Message) error {
func (smtpConfig SMTP) connectToSMTP(tlsRequired bool) (client *smtp.Client, err error) {
host, _, err := net.SplitHostPort(smtpConfig.Host)
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-spR56", "could not split host and port for connect to smtp")
return nil, zerrors.ThrowInternal(err, "EMAIL-spR56", "Errors.SMTP.CouldNotSplit")
}
if !tlsRequired {
@ -109,7 +109,7 @@ func (smtpConfig SMTP) connectToSMTP(tlsRequired bool) (client *smtp.Client, err
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")
return nil, zerrors.ThrowInternal(err, "EMAIL-skwos", "Errors.SMTP.CouldNotDial")
}
return client, nil
}
@ -118,17 +118,17 @@ 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...")
logging.OnError(err).Warn("could not connect using normal tls. trying starttls instead...")
return smtpConfig.getSMTPClientWithStartTls(host)
}
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-sl39s", "could not make tls dial")
return nil, zerrors.ThrowInternal(err, "EMAIL-sl39s", "Errors.SMTP.CouldNotDialTLS")
}
client, err := smtp.NewClient(conn, host)
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-skwi4", "could not create smtp client")
return nil, zerrors.ThrowInternal(err, "EMAIL-skwi4", "Errors.SMTP.CouldNotCreateClient")
}
return client, err
}
@ -142,7 +142,7 @@ func (smtpConfig SMTP) getSMTPClientWithStartTls(host string) (*smtp.Client, err
if err := client.StartTLS(&tls.Config{
ServerName: host,
}); err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-guvsQ", "could not start tls")
return nil, zerrors.ThrowInternal(err, "EMAIL-guvsQ", "Errors.SMTP.CouldNotStartTLS")
}
return client, nil
}
@ -154,7 +154,56 @@ func (smtpConfig SMTP) smtpAuth(client *smtp.Client, host string) error {
// Auth
err := client.Auth(PlainOrLoginAuth(smtpConfig.User, smtpConfig.Password, host))
if err != nil {
return zerrors.ThrowInternalf(err, "EMAIL-s9kfs", "could not add smtp auth for user %s", smtpConfig.User)
return zerrors.ThrowInternal(err, "EMAIL-s9kfs", "Errors.SMTP.CouldNotAuth")
}
return nil
}
func TestConfiguration(cfg *Config, testEmail string) error {
client, err := cfg.SMTP.connectToSMTP(cfg.Tls)
if err != nil {
return err
}
defer client.Close()
message := &messages.Email{
Recipients: []string{testEmail},
Subject: "Test email",
Content: "This is a test email to check if your SMTP provider works fine",
SenderEmail: cfg.From,
SenderName: cfg.FromName,
}
if err := client.Mail(cfg.From); err != nil {
return zerrors.ThrowInternal(err, "EMAIL-s3is3", "Errors.SMTP.CouldNotSetSender")
}
if err := client.Rcpt(testEmail); err != nil {
return zerrors.ThrowInternal(err, "EMAIL-s4is4", "Errors.SMTP.CouldNotSetRecipient")
}
// Open data connection
w, err := client.Data()
if err != nil {
return err
}
// Send content
content, err := message.GetContent()
if err != nil {
return err
}
_, err = w.Write([]byte(content))
if err != nil {
return err
}
// Close IO and quit smtp connection
err = w.Close()
if err != nil {
return err
}
return client.Quit()
}

View File

@ -53,13 +53,26 @@ Errors:
NotFound: SMS конфигурацията не е намерена
AlreadyActive: SMS конфигурацията вече е активна
AlreadyDeactivated: SMS конфигурацията вече е деактивирана
SMTP:
NotEmailMessage: съобщението не е имейл съобщение
RequiredAttributes: темата, получателите и съдържанието трябва да бъдат зададени, но някои или всички са празни
CouldNotSplit: не можа да раздели хост и порт за свързване към smtp
CouldNotDial: не може да се свърже със SMTP сървъра, проверете порта, проблеми със защитната стена...
CouldNotDialTLS: не може да се свърже със SMTP сървъра чрез TLS, проверете порта, проблеми със защитната стена...
CouldNotCreateClient: не може да създаде smtp клиент
CouldNotStartTLS: не можа да стартира TLS
CouldNotAuth: не може да добави smtp auth, проверете дали потребителят и паролата ви са правилни, ако са правилни, може би вашият доставчик изисква метод за удостоверяване, който не се поддържа от ZITADEL
CouldNotSetSender: не можа да зададе подател
CouldNotSetRecipient: не можа да зададе получател
SMTPConfig:
TestPassword: Паролата за тест не е намерена
NotFound: SMTP конфигурацията не е намерена
AlreadyExists: SMTP конфигурация вече съществува
AlreadyDeactivated: SMTP конфигурацията вече е деактивирана
SenderAdressNotCustomDomain: >-
Адресът на изпращача трябва да бъде конфигуриран като персонализиран
домейн в екземпляра.
TestEmailNotFound: Имейл адресът за теста не е намерен
Notification:
NoDomain: Няма намерен домейн за съобщение
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Konfigurace SMS nebyla nalezena
AlreadyActive: Konfigurace SMS je již aktivní
AlreadyDeactivated: Konfigurace SMS je již deaktivovaná
SMTP:
NotEmailMessage: zpráva není EmailMessage
RequiredAttributes: předmět, příjemci a obsah musí být nastaveny, ale některé nebo všechny jsou prázdné
CouldNotSplit: nemohl rozdělit hostitele a port pro připojení k smtp
CouldNotDial: nelze se spojit se serverem SMTP, zkontrolovat port, problémy s firewallem...
CouldNotDialTLS: nelze se spojit se serverem SMTP pomocí TLS, zkontrolovat port, problémy s firewallem...
CouldNotCreateClient: nelze vytvořit smtp klienta
CouldNotStartTLS: nelze spustit tls
CouldNotAuth: nemohlo se přidat smtp auth, zkontrolujte, zda je váš uživatel i heslo správné, pokud jsou správné, možná váš poskytovatel vyžaduje metodu auth, kterou ZITADEL nepodporuje
CouldNotSetSender: nelze nastavit odesílatele
CouldNotSetRecipient: nelze nastavit příjemce
SMTPConfig:
TestPassword: Heslo pro test nenalezeno
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.
TestEmailNotFound: E-mailová adresa pro test nebyla nalezena
Notification:
NoDomain: Pro zprávu nebyla nalezena žádná doména
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS Konfiguration nicht gefunden
AlreadyActive: SMS Konfiguration ist bereits aktiviert
AlreadyDeactivated: SMS Konfiguration ist bereits deaktiviert
SMTP:
NotEmailMessage: Die Nachricht ist nicht EmailMessage
RequiredAttributes: Betreff, Empfänger und Inhalt müssen festgelegt werden, aber einige oder alle davon sind leer
CouldNotSplit: Host und Port konnten für die Verbindung zu SMTP nicht getrennt werden
CouldNotDial: Es konnte keine Verbindung zum SMTP-Server hergestellt werden, Port überprüfen, Firewall-Probleme ...
CouldNotDialTLS: Es konnte keine Verbindung zum SMTP-Server über TLS hergestellt werden, überprüfen Sie den Port, Firewall-Probleme ...
CouldNotCreateClient: Der SMTP-Client konnte nicht erstellt werden
CouldNotStartTLS: TLS konnte nicht gestartet werden
CouldNotAuth: Die SMTP-Authentifizierung konnte nicht hinzugefügt werden. Überprüfen Sie, ob sowohl Ihr Benutzername als auch Ihr Passwort korrekt sind. Wenn sie korrekt sind, erfordert Ihr Anbieter möglicherweise eine Authentifizierungsmethode, die von ZITADEL nicht unterstützt wird
CouldNotSetSender: Absender konnte nicht eingestellt werden
CouldNotSetRecipient: Der Empfänger konnte nicht festgelegt werden
SMTPConfig:
TestPassword: Passwort für Test nicht gefunden
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.
TestEmailNotFound: E-Mail-Adresse für den Test nicht gefunden
Notification:
NoDomain: Keine Domäne für Nachricht gefunden
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS configuration not found
AlreadyActive: SMS configuration already active
AlreadyDeactivated: SMS configuration already deactivated
SMTP:
NotEmailMessage: message is not EmailMessage
RequiredAttributes: subject, recipients and content must be set but some or all of them are empty
CouldNotSplit: could not split host and port for connect to smtp
CouldNotDial: could not contact with the SMTP server, check the port, firewall issues...
CouldNotDialTLS: could not contact with the SMTP server using TLS, check the port, firewall issues...
CouldNotCreateClient: could not create smtp client
CouldNotStartTLS: could not start tls
CouldNotAuth: could not add smtp auth, check if both your user and password are correct, if they're correct maybe your provider requires an auth method not supported by ZITADEL
CouldNotSetSender: could not set sender
CouldNotSetRecipient: could not set recipient
SMTPConfig:
TestPassword: Password for test not found
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.
TestEmailNotFound: Email address for test not found
Notification:
NoDomain: No Domain found for message
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: configuración SMS no encontrada
AlreadyActive: la configuración SMS ya está activa
AlreadyDeactivated: la configuracion SMS ya está desactivada
SMTP:
NotEmailMessage: el mensaje no es EmailMessage
RequiredAttributes: Se deben configurar el asunto, los destinatarios y el contenido, pero algunos o todos están vacíos.
CouldNotSplit: No se pudo dividir el host y el puerto para conectarse a SMTP
CouldNotDial: No se pudo contactar con el servidor SMTP, verifique el puerto, problemas con el firewall...
CouldNotDialTLS: No se pudo contactar con el servidor SMTP usando TLS, verifique el puerto, problemas con el firewall...
CouldNotCreateClient: no se pudo crear el cliente smtp
CouldNotStartTLS: no se pudo iniciar TLS
CouldNotAuth: no se pudo agregar la autenticación smtp, verifique si tanto su usuario como su contraseña son correctos, si son correctos tal vez su proveedor requiera un método de autenticación no admitido por ZITADEL
CouldNotSetSender: no se pudo configurar el remitente
CouldNotSetRecipient: No se pudo establecer el destinatario
SMTPConfig:
TestPassword: Contraseña para la prueba no encontrada
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.
TestEmailNotFound: Dirección de correo electrónico para la prueba no encontrada
Notification:
NoDomain: No se encontró el dominio para el mensaje
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Configuration SMS non trouvée
AlreadyActive: Configuration SMS déjà active
AlreadyDeactivated: Configuration SMS déjà désactivée
SMTP:
NotEmailMessage: le message n'est pas un EmailMessage
RequiredAttributes: le sujet, les destinataires et le contenu doivent être définis mais certains ou la totalité d'entre eux sont vides
CouldNotSplit: impossible de diviser l'hôte et le port pour la connexion à SMTP
CouldNotDial: impossible de contacter le serveur SMTP, vérifier le port, problèmes de pare-feu...
CouldNotDialTLS: Impossible de contacter le serveur SMTP via TLS, vérifiez le port, problèmes de pare-feu...
CouldNotCreateClient: impossible de créer un client SMTP
CouldNotStartTLS: je n'ai pas pu démarrer tls
CouldNotAuth: Impossible d'ajouter l'authentification SMTP, vérifiez si votre utilisateur et votre mot de passe sont corrects. S'ils sont corrects, votre fournisseur nécessite peut-être une méthode d'authentification non prise en charge par ZITADEL.
CouldNotSetSender: impossible de définir l'expéditeur
CouldNotSetRecipient: impossible de définir le destinataire
SMTPConfig:
TestPassword: Mot de passe pour le test introuvable
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.
TestEmailNotFound: Adresse e-mail pour le test introuvable
Notification:
NoDomain: Aucun domaine trouvé pour le message
User:

Some files were not shown because too many files have changed in this diff Show More