Merge branch 'cnsl-features' of https://github.com/zitadel/zitadel into cnsl-features

This commit is contained in:
Elio Bischof 2024-04-10 18:20:19 +02:00
commit f1466f6393
No known key found for this signature in database
GPG Key ID: 7B383FDE4DDBF1BD
77 changed files with 1538 additions and 481 deletions

View File

@ -40,13 +40,17 @@
></i>
<div
*ngIf="
!!featureData.loginDefaultOrg?.enabled && featureData.loginDefaultOrg?.source === Source.SOURCE_SYSTEM
!!featureData.loginDefaultOrg?.enabled &&
(featureData.loginDefaultOrg?.source === Source.SOURCE_SYSTEM ||
featureData.loginDefaultOrg?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot enabled"
></div>
<div
*ngIf="
!featureData.loginDefaultOrg?.enabled && featureData.loginDefaultOrg?.source === Source.SOURCE_SYSTEM
!featureData.loginDefaultOrg?.enabled &&
(featureData.loginDefaultOrg?.source === Source.SOURCE_SYSTEM ||
featureData.loginDefaultOrg?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot disabled"
></div>
@ -54,12 +58,12 @@
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.DISABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.ENABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
</div>
</mat-button-toggle>
</mat-button-toggle-group>
@ -91,14 +95,16 @@
<div
*ngIf="
!!featureData.oidcLegacyIntrospection?.enabled &&
featureData.oidcLegacyIntrospection?.source === Source.SOURCE_SYSTEM
(featureData.oidcLegacyIntrospection?.source === Source.SOURCE_SYSTEM ||
featureData.oidcLegacyIntrospection?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot enabled"
></div>
<div
*ngIf="
!featureData.oidcLegacyIntrospection?.enabled &&
featureData.oidcLegacyIntrospection?.source === Source.SOURCE_SYSTEM
(featureData.oidcLegacyIntrospection?.source === Source.SOURCE_SYSTEM ||
featureData.oidcLegacyIntrospection?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot disabled"
></div>
@ -106,12 +112,12 @@
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.DISABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.ENABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
</div>
</mat-button-toggle>
</mat-button-toggle-group>
@ -142,13 +148,16 @@
<div
*ngIf="
!!featureData.oidcTokenExchange?.enabled &&
featureData.oidcTokenExchange?.source === Source.SOURCE_SYSTEM
(featureData.oidcTokenExchange?.source === Source.SOURCE_SYSTEM ||
featureData.oidcTokenExchange?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot enabled"
></div>
<div
*ngIf="
!featureData.oidcTokenExchange?.enabled && featureData.oidcTokenExchange?.source === Source.SOURCE_SYSTEM
!featureData.oidcTokenExchange?.enabled &&
(featureData.oidcTokenExchange?.source === Source.SOURCE_SYSTEM ||
featureData.oidcTokenExchange?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot disabled"
></div>
@ -156,12 +165,12 @@
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.DISABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.ENABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
</div>
</mat-button-toggle>
</mat-button-toggle-group>
@ -192,14 +201,16 @@
<div
*ngIf="
!!featureData.oidcTriggerIntrospectionProjections?.enabled &&
featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_SYSTEM
(featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_SYSTEM ||
featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot enabled"
></div>
<div
*ngIf="
!featureData.oidcTriggerIntrospectionProjections?.enabled &&
featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_SYSTEM
(featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_SYSTEM ||
featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot disabled"
></div>
@ -207,12 +218,12 @@
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.DISABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.ENABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
</div>
</mat-button-toggle>
</mat-button-toggle-group>
@ -241,23 +252,31 @@
matTooltip="{{ 'SETTING.FEATURES.INHERITED_DESCRIPTION' | translate }}"
></i>
<div
*ngIf="!!featureData.userSchema?.enabled && featureData.userSchema?.source === Source.SOURCE_SYSTEM"
*ngIf="
!!featureData.userSchema?.enabled &&
(featureData.userSchema?.source === Source.SOURCE_SYSTEM ||
featureData.userSchema?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot enabled"
></div>
<div
*ngIf="!featureData.userSchema?.enabled && featureData.userSchema?.source === Source.SOURCE_SYSTEM"
*ngIf="
!featureData.userSchema?.enabled &&
(featureData.userSchema?.source === Source.SOURCE_SYSTEM ||
featureData.userSchema?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot disabled"
></div>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.DISABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.ENABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
</div>
</mat-button-toggle>
</mat-button-toggle-group>
@ -286,23 +305,31 @@
matTooltip="{{ 'SETTING.FEATURES.INHERITED_DESCRIPTION' | translate }}"
></i>
<div
*ngIf="!!featureData.actions?.enabled && featureData.actions?.source === Source.SOURCE_SYSTEM"
*ngIf="
!!featureData.actions?.enabled &&
(featureData.actions?.source === Source.SOURCE_SYSTEM ||
featureData.actions?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot enabled"
></div>
<div
*ngIf="!featureData.actions?.enabled && featureData.actions?.source === Source.SOURCE_SYSTEM"
*ngIf="
!featureData.actions?.enabled &&
(featureData.actions?.source === Source.SOURCE_SYSTEM ||
featureData.actions?.source === Source.SOURCE_UNSPECIFIED)
"
class="current-dot disabled"
></div>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.DISABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
</div>
</mat-button-toggle>
<mat-button-toggle [value]="ToggleState.ENABLED">
<div class="toggle-row">
<span> {{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
<span> {{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
</div>
</mat-button-toggle>
</mat-button-toggle-group>

View File

@ -103,52 +103,63 @@ export class FeaturesComponent implements OnDestroy {
}
public validateAndSave() {
console.log(this.toggleStates);
this.featureService
.resetInstanceFeatures()
.then(() => {
const req = new SetInstanceFeaturesRequest();
this.featureService.resetInstanceFeatures().then(() => {
const req = new SetInstanceFeaturesRequest();
let changed = false;
if (this.toggleStates?.loginDefaultOrg?.state !== ToggleState.INHERITED) {
req.setLoginDefaultOrg(this.toggleStates?.loginDefaultOrg?.state === ToggleState.ENABLED);
}
if (this.toggleStates?.oidcTriggerIntrospectionProjections?.state !== ToggleState.INHERITED) {
req.setOidcTriggerIntrospectionProjections(
this.toggleStates?.oidcTriggerIntrospectionProjections?.state === ToggleState.ENABLED,
);
}
if (this.toggleStates?.oidcLegacyIntrospection?.state !== ToggleState.INHERITED) {
req.setOidcLegacyIntrospection(this.toggleStates?.oidcLegacyIntrospection?.state === ToggleState.ENABLED);
}
if (this.toggleStates?.userSchema?.state !== ToggleState.INHERITED) {
req.setUserSchema(this.toggleStates?.userSchema?.state === ToggleState.ENABLED);
}
if (this.toggleStates?.oidcTokenExchange?.state !== ToggleState.INHERITED) {
req.setOidcTokenExchange(this.toggleStates?.oidcTokenExchange?.state === ToggleState.ENABLED);
}
if (this.toggleStates?.actions?.state !== ToggleState.INHERITED) {
req.setActions(this.toggleStates?.actions?.state === ToggleState.ENABLED);
}
console.log(this.toggleStates);
return this.featureService.setInstanceFeatures(req);
})
.then(() => {
this.toast.showInfo('POLICY.TOAST.SET', true);
})
.catch((error) => {
this.toast.showError(error);
});
if (this.toggleStates?.loginDefaultOrg?.state !== ToggleState.INHERITED) {
req.setLoginDefaultOrg(this.toggleStates?.loginDefaultOrg?.state === ToggleState.ENABLED);
changed = true;
}
if (this.toggleStates?.oidcTriggerIntrospectionProjections?.state !== ToggleState.INHERITED) {
req.setOidcTriggerIntrospectionProjections(
this.toggleStates?.oidcTriggerIntrospectionProjections?.state === ToggleState.ENABLED,
);
changed = true;
}
if (this.toggleStates?.oidcLegacyIntrospection?.state !== ToggleState.INHERITED) {
req.setOidcLegacyIntrospection(this.toggleStates?.oidcLegacyIntrospection?.state === ToggleState.ENABLED);
changed = true;
}
if (this.toggleStates?.userSchema?.state !== ToggleState.INHERITED) {
req.setUserSchema(this.toggleStates?.userSchema?.state === ToggleState.ENABLED);
changed = true;
}
if (this.toggleStates?.oidcTokenExchange?.state !== ToggleState.INHERITED) {
req.setOidcTokenExchange(this.toggleStates?.oidcTokenExchange?.state === ToggleState.ENABLED);
changed = true;
}
if (this.toggleStates?.actions?.state !== ToggleState.INHERITED) {
req.setActions(this.toggleStates?.actions?.state === ToggleState.ENABLED);
changed = true;
}
if (changed) {
this.featureService
.setInstanceFeatures(req)
.then(() => {
this.toast.showInfo('POLICY.TOAST.SET', true);
})
.catch((error) => {
this.toast.showError(error);
});
}
});
}
private getFeatures(inheritance: boolean) {
this.featureService.getInstanceFeatures(inheritance).then((instanceFeaturesResponse) => {
this.featureData = instanceFeaturesResponse.toObject();
console.log(this.featureData);
this.toggleStates = {
loginDefaultOrg: {
source: this.featureData.loginDefaultOrg?.source || Source.SOURCE_SYSTEM,
state:
this.featureData.loginDefaultOrg?.source === Source.SOURCE_SYSTEM
this.featureData.loginDefaultOrg?.source === Source.SOURCE_SYSTEM ||
this.featureData.loginDefaultOrg?.source === Source.SOURCE_UNSPECIFIED
? ToggleState.INHERITED
: !!this.featureData.loginDefaultOrg?.enabled
? ToggleState.ENABLED
@ -157,7 +168,8 @@ export class FeaturesComponent implements OnDestroy {
oidcTriggerIntrospectionProjections: {
source: this.featureData.oidcTriggerIntrospectionProjections?.source || Source.SOURCE_SYSTEM,
state:
this.featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_SYSTEM
this.featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_SYSTEM ||
this.featureData.oidcTriggerIntrospectionProjections?.source === Source.SOURCE_UNSPECIFIED
? ToggleState.INHERITED
: !!this.featureData.oidcTriggerIntrospectionProjections?.enabled
? ToggleState.ENABLED
@ -166,7 +178,8 @@ export class FeaturesComponent implements OnDestroy {
oidcLegacyIntrospection: {
source: this.featureData.oidcLegacyIntrospection?.source || Source.SOURCE_SYSTEM,
state:
this.featureData.oidcLegacyIntrospection?.source === Source.SOURCE_SYSTEM
this.featureData.oidcLegacyIntrospection?.source === Source.SOURCE_SYSTEM ||
this.featureData.oidcLegacyIntrospection?.source === Source.SOURCE_UNSPECIFIED
? ToggleState.INHERITED
: !!this.featureData.oidcLegacyIntrospection?.enabled
? ToggleState.ENABLED
@ -175,7 +188,8 @@ export class FeaturesComponent implements OnDestroy {
userSchema: {
source: this.featureData.userSchema?.source || Source.SOURCE_SYSTEM,
state:
this.featureData.userSchema?.source === Source.SOURCE_SYSTEM
this.featureData.userSchema?.source === Source.SOURCE_SYSTEM ||
this.featureData.userSchema?.source === Source.SOURCE_UNSPECIFIED
? ToggleState.INHERITED
: !!this.featureData.userSchema?.enabled
? ToggleState.ENABLED
@ -184,7 +198,8 @@ export class FeaturesComponent implements OnDestroy {
oidcTokenExchange: {
source: this.featureData.oidcTokenExchange?.source || Source.SOURCE_SYSTEM,
state:
this.featureData.oidcTokenExchange?.source === Source.SOURCE_SYSTEM
this.featureData.oidcTokenExchange?.source === Source.SOURCE_SYSTEM ||
this.featureData.oidcTokenExchange?.source === Source.SOURCE_UNSPECIFIED
? ToggleState.INHERITED
: !!this.featureData.oidcTokenExchange?.enabled
? ToggleState.ENABLED
@ -193,7 +208,8 @@ export class FeaturesComponent implements OnDestroy {
actions: {
source: Source.SOURCE_SYSTEM,
state:
this.featureData.actions?.source === Source.SOURCE_SYSTEM
this.featureData.actions?.source === Source.SOURCE_SYSTEM ||
this.featureData.actions?.source === Source.SOURCE_UNSPECIFIED
? ToggleState.INHERITED
: !!this.featureData.actions?.enabled
? ToggleState.ENABLED

View File

@ -15,6 +15,7 @@ import {
InitPasswordDoneScreenText,
InitPasswordScreenText,
LinkingUserDoneScreenText,
LinkingUserPromptScreenText,
LoginScreenText,
LogoutDoneScreenText,
MFAProvidersText,
@ -375,5 +376,12 @@ export function mapRequestValues(map: Partial<Map>, req: Req): Req {
r34.setUsernameLabel(map.externalRegistrationUserOverviewText?.usernameLabel ?? '');
req.setExternalRegistrationUserOverviewText(r34);
const r35 = new LinkingUserPromptScreenText();
r35.setTitle(map.linkingUserPromptText?.title ?? '');
r35.setDescription(map.linkingUserPromptText?.description ?? '');
r35.setLinkButtonText(map.linkingUserPromptText?.linkButtonText ?? '');
r35.setOtherButtonText(map.linkingUserPromptText?.otherButtonText ?? '');
req.setLinkingUserPromptText(r35);
return req;
}

View File

@ -41,6 +41,7 @@ const KeyNamesArray = [
'initPasswordText',
'initializeDoneText',
'initializeUserText',
'linkingUserPromptText',
'linkingUserDoneText',
'loginText',
'logoutText',

View File

@ -23,4 +23,12 @@
<mat-checkbox formControlName="isLinkingAllowed">{{ 'IDP.OPTIONS.ISLINKINGALLOWED' | translate }}</mat-checkbox>
</div>
</cnsl-info-section>
<cnsl-info-section class="auto-reg-info">
<p class="checkbox-desc">{{ 'IDP.OPTIONS.AUTOLINKING_DESC' | translate }}</p>
<mat-select formControlName="autoLinking">
<mat-option *ngFor="let linkingType of linkingTypes" [value]="linkingType">
{{ 'IDP.OPTIONS.AUTOLINKINGTYPE.' + linkingType | translate }}
</mat-option>
</mat-select>
</cnsl-info-section>
</form>

View File

@ -1,7 +1,8 @@
import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';
import { Options } from 'src/app/proto/generated/zitadel/idp_pb';
import { Options, AutoLinkingOption } from 'src/app/proto/generated/zitadel/idp_pb';
import { AccessTokenType } from '../../proto/generated/zitadel/user_pb';
@Component({
selector: 'cnsl-provider-options',
@ -17,8 +18,15 @@ export class ProviderOptionsComponent implements OnChanges, OnDestroy {
isAutoUpdate: new FormControl(false, []),
isCreationAllowed: new FormControl(true, []),
isLinkingAllowed: new FormControl(true, []),
autoLinking: new FormControl(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED, []),
});
public linkingTypes: AutoLinkingOption[] = [
AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED,
AutoLinkingOption.AUTO_LINKING_OPTION_USERNAME,
AutoLinkingOption.AUTO_LINKING_OPTION_EMAIL,
];
constructor() {
this.form.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
if (value) {
@ -27,6 +35,7 @@ export class ProviderOptionsComponent implements OnChanges, OnDestroy {
opt.setIsAutoUpdate(value.isAutoUpdate);
opt.setIsCreationAllowed(value.isCreationAllowed);
opt.setIsLinkingAllowed(value.isLinkingAllowed);
opt.setAutoLinking(value.autoLinking);
this.optionsChanged.emit(opt);
}
});

View File

@ -2,13 +2,22 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatSelectModule } from '@angular/material/select';
import { TranslateModule } from '@ngx-translate/core';
import { InfoSectionModule } from '../info-section/info-section.module';
import { ProviderOptionsComponent } from './provider-options.component';
@NgModule({
declarations: [ProviderOptionsComponent],
imports: [CommonModule, MatCheckboxModule, FormsModule, InfoSectionModule, ReactiveFormsModule, TranslateModule],
imports: [
CommonModule,
MatCheckboxModule,
MatSelectModule,
FormsModule,
InfoSectionModule,
ReactiveFormsModule,
TranslateModule,
],
exports: [ProviderOptionsComponent],
})
export class ProviderOptionsModule {}

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateAppleProviderRequest as AdminUpdateAppleProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddAppleProviderRequest as MgmtAddAppleProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -34,7 +34,10 @@ const MAX_ALLOWED_SIZE = 5 * 1024;
})
export class ProviderAppleComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';
// DEPRECATED: assert service$ instead

View File

@ -10,7 +10,14 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateAzureADProviderRequest as AdminUpdateAzureADProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { AzureADTenant, AzureADTenantType, IDPOwnerType, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AutoLinkingOption,
AzureADTenant,
AzureADTenantType,
IDPOwnerType,
Options,
Provider,
} from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddAzureADProviderRequest as MgmtAddAzureADProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +39,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderAzureADComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';
// DEPRECATED: assert service$ instead

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGitHubEnterpriseServerProviderRequest as AdminUpdateGitHubEnterpriseServerProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGitHubEnterpriseServerProviderRequest as MgmtAddGitHubEnterpriseServerProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderGithubESComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGitHubProviderRequest as AdminUpdateGithubProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGitHubProviderRequest as MgmtAddGithubProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderGithubComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';
// DEPRECATED: assert service$ instead

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGitLabSelfHostedProviderRequest as AdminUpdateGitLabSelfHostedProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGitLabSelfHostedProviderRequest as MgmtAddGitLabSelfHostedProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderGitlabSelfHostedComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';
// DEPRECATED: assert service$ instead

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGitLabProviderRequest as AdminUpdateGitLabProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGitLabProviderRequest as MgmtAddGitLabProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderGitlabComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';
// DEPRECATED: assert service$ instead

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGoogleProviderRequest as AdminUpdateGoogleProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGoogleProviderRequest as MgmtAddGoogleProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderGoogleComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';
// DEPRECATED: assert service$ instead

View File

@ -9,7 +9,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateJWTProviderRequest as AdminUpdateJWTProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddJWTProviderRequest as MgmtAddJWTProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderJWTComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';

View File

@ -9,7 +9,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateLDAPProviderRequest as AdminUpdateLDAPProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { LDAPAttributes, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, LDAPAttributes, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddLDAPProviderRequest as MgmtAddLDAPProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
export class ProviderLDAPComponent {
public updateBindPassword: boolean = false;
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
public attributes: LDAPAttributes = new LDAPAttributes();
// DEPRECATED: use id$ instead
public id: string | null = '';

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGenericOAuthProviderRequest as AdminUpdateGenericOAuthProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGenericOAuthProviderRequest as MgmtAddGenericOAuthProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderOAuthComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';

View File

@ -10,7 +10,7 @@ import {
GetProviderByIDRequest as AdminGetProviderByIDRequest,
UpdateGenericOIDCProviderRequest as AdminUpdateGenericOIDCProviderRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import { Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddGenericOIDCProviderRequest as MgmtAddGenericOIDCProviderRequest,
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
@ -32,7 +32,10 @@ import { ProviderNextService } from '../provider-next/provider-next.service';
})
export class ProviderOIDCComponent {
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: use id$ instead
public id: string | null = '';

View File

@ -1,6 +1,6 @@
import { Component, Injector, Type } from '@angular/core';
import { Location } from '@angular/common';
import { Options, Provider, SAMLBinding } from '../../../proto/generated/zitadel/idp_pb';
import { AutoLinkingOption, Options, Provider, SAMLBinding } from '../../../proto/generated/zitadel/idp_pb';
import { AbstractControl, FormGroup, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
import { ManagementService } from '../../../services/mgmt.service';
@ -37,7 +37,10 @@ export class ProviderSamlSpComponent {
public provider?: Provider.AsObject;
public form!: FormGroup;
public showOptional: boolean = false;
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
public options: Options = new Options()
.setIsCreationAllowed(true)
.setIsLinkingAllowed(true)
.setAutoLinking(AutoLinkingOption.AUTO_LINKING_OPTION_UNSPECIFIED);
// DEPRECATED: assert service$ instead
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
// DEPRECATED: use service$ instead

View File

@ -1608,6 +1608,7 @@
"initPasswordText": "Инициализиране на парола",
"initializeDoneText": "Инициализирането на потребителя е готово",
"initializeUserText": "Инициализирайте потребителя",
"linkingUserPromptText": "Потребителският промпт за свързване",
"linkingUserDoneText": "Свързването на потребителя е готово",
"loginText": "Влизам",
"logoutText": "Излез от профила си",
@ -2040,7 +2041,13 @@
"ISCREATIONALLOWED": "Създаването на акаунт е разрешено",
"ISCREATIONALLOWED_DESC": "Определя дали могат да се създават акаунти.",
"ISLINKINGALLOWED": "Свързването на акаунти е разрешено",
"ISLINKINGALLOWED_DESC": "Определя дали дадена самоличност може да бъде свързана със съществуващ акаунт."
"ISLINKINGALLOWED_DESC": "Определя дали дадена самоличност може да бъде свързана със съществуващ акаунт.",
"AUTOLINKING_DESC": "Определя дали идентичността ще бъде подканена да бъде свързана със съществуващ профил.",
"AUTOLINKINGTYPE": {
"0": "Изключено",
"1": "Проверка за съществуващо потребителско име",
"2": "Проверка за съществуващ имейл"
}
},
"OWNERTYPES": {
"0": "неизвестен",

View File

@ -1615,6 +1615,7 @@
"initPasswordText": "Inicializace hesla",
"initializeDoneText": "Inicializace uživatele dokončena",
"initializeUserText": "Inicializace uživatele",
"linkingUserPromptText": "Uživatelský propojovací text",
"linkingUserDoneText": "Propojení uživatele dokončeno",
"loginText": "Přihlášení",
"logoutText": "Odhlášení",
@ -2051,7 +2052,13 @@
"ISCREATIONALLOWED": "Je povoleno vytváření účtu",
"ISCREATIONALLOWED_DESC": "Určuje, zda lze vytvářet účty.",
"ISLINKINGALLOWED": "Je povoleno propojení účtů",
"ISLINKINGALLOWED_DESC": "Určuje, zda lze identitu propojit s existujícím účtem."
"ISLINKINGALLOWED_DESC": "Určuje, zda lze identitu propojit s existujícím účtem.",
"AUTOLINKING_DESC": "Určuje, zda se bude identita vyzývat k propojení se stávajícím účtem.",
"AUTOLINKINGTYPE": {
"0": "Vypnuto",
"1": "Kontrola existence uživatelského jména",
"2": "Kontrola existence e-mailu"
}
},
"OWNERTYPES": {
"0": "neznámý",

View File

@ -1614,6 +1614,7 @@
"initPasswordText": "Passwort Initialisierung",
"initializeDoneText": "Benutzereinrichtung erfolgreich",
"initializeUserText": "Benutzereinrichtung",
"linkingUserPromptText": "Aufforderung zur Benutzerverlinkung",
"linkingUserDoneText": "Benutzerverlinkung erfolgreich",
"loginText": "Anmelden",
"logoutText": "Abmelden",
@ -2041,7 +2042,13 @@
"ISCREATIONALLOWED": "Account erstellen erlaubt",
"ISCREATIONALLOWED_DESC": "Legt fest, ob Konten erstellt werden können.",
"ISLINKINGALLOWED": "Account linking erlaubt",
"ISLINKINGALLOWED_DESC": "Legt fest, ob eine Identität mit einem bestehenden Konto verknüpft werden kann."
"ISLINKINGALLOWED_DESC": "Legt fest, ob eine Identität mit einem bestehenden Konto verknüpft werden kann.",
"AUTOLINKING_DESC": "Legt fest, ob eine Identität aufgefordert wird, mit einem vorhandenen Konto verknüpft zu werden.",
"AUTOLINKINGTYPE": {
"0": "Deaktiviert",
"1": "Überprüfung auf vorhandenen Benutzernamen",
"2": "Überprüfung auf vorhandene E-Mail"
}
},
"OWNERTYPES": {
"0": "unknown",

View File

@ -1615,6 +1615,7 @@
"initPasswordText": "Initialize password",
"initializeDoneText": "Initialize user done",
"initializeUserText": "Initialize user",
"linkingUserPromptText": "Linking user prompt",
"linkingUserDoneText": "Linking user done",
"loginText": "Login",
"logoutText": "Logout",
@ -2054,7 +2055,13 @@
"ISCREATIONALLOWED": "Account creation allowed",
"ISCREATIONALLOWED_DESC": "Determines whether accounts can be created.",
"ISLINKINGALLOWED": "Account linking allowed",
"ISLINKINGALLOWED_DESC": "Determines whether an identity can be linked to an existing account."
"ISLINKINGALLOWED_DESC": "Determines whether an identity can be linked to an existing account.",
"AUTOLINKING_DESC": "Determines whether an identity will be prompted to be linked to an existing account.",
"AUTOLINKINGTYPE": {
"0": "Disabled",
"1": "Check for existing Username",
"2": "Check for existing Email"
}
},
"OWNERTYPES": {
"0": "unknown",

View File

@ -1616,6 +1616,7 @@
"initPasswordText": "Inicializar contraseña",
"initializeDoneText": "Inicializar usuario, hecho",
"initializeUserText": "Inicializar usuario",
"linkingUserPromptText": "Mensaje de enlace de usuario",
"linkingUserDoneText": "Vinculación de usuario, hecho",
"loginText": "Iniciar sesión",
"logoutText": "Cerrar sesión",
@ -2047,7 +2048,13 @@
"ISCREATIONALLOWED": "Creación de cuentas permitida",
"ISCREATIONALLOWED_DESC": "Determina si se pueden crear cuentas.",
"ISLINKINGALLOWED": "Permitida la vinculación de cuentas",
"ISLINKINGALLOWED_DESC": "Determina si una identidad puede vincularse a una cuenta existente."
"ISLINKINGALLOWED_DESC": "Determina si una identidad puede vincularse a una cuenta existente.",
"AUTOLINKING_DESC": "Determina si se pedirá a una identidad que se vincule a una cuenta existente.",
"AUTOLINKINGTYPE": {
"0": "Desactivado",
"1": "Comprobar nombre de usuario existente",
"2": "Comprobar correo electrónico existente"
}
},
"OWNERTYPES": {
"0": "desconocido",

View File

@ -1614,6 +1614,7 @@
"initPasswordText": "Initialiser le mot de passe",
"initializeDoneText": "Initialiser l'utilisateur terminé",
"initializeUserText": "Initialiser l'utilisateur",
"linkingUserPromptText": "Message de liaison utilisateur",
"linkingUserDoneText": "Lier l'utilisateur fait",
"loginText": "Connexion",
"logoutText": "Déconnexion",
@ -2045,7 +2046,13 @@
"ISCREATIONALLOWED": "la création est-elle autorisée",
"ISCREATIONALLOWED_DESC": "Détermine si des comptes peuvent être créés.",
"ISLINKINGALLOWED": "la liaison est-elle autorisée",
"ISLINKINGALLOWED_DESC": "Détermine si une identité peut être liée à un compte existant."
"ISLINKINGALLOWED_DESC": "Détermine si une identité peut être liée à un compte existant.",
"AUTOLINKING_DESC": "Détermine si une identité sera invitée à être liée à un compte existant.",
"AUTOLINKINGTYPE": {
"0": "Désactivé",
"1": "Vérification de l'existence du nom d'utilisateur",
"2": "Vérification de l'existence de l'e-mail"
}
},
"OWNERTYPES": {
"0": "inconnu",

View File

@ -1614,6 +1614,7 @@
"initPasswordText": "Inizializzazione della password",
"initializeDoneText": "Inizializzazione utente finita",
"initializeUserText": "Inizializzazione utente",
"linkingUserPromptText": "Testo di promemoria per collegare l'utente",
"linkingUserDoneText": "Collegamento dell'utente finito",
"loginText": "Accesso",
"logoutText": "Logout",
@ -2045,7 +2046,13 @@
"ISCREATIONALLOWED": "Creazione consentita",
"ISCREATIONALLOWED_DESC": "Determina se i conti possono essere creati.",
"ISLINKINGALLOWED": "Collegamento consentito",
"ISLINKINGALLOWED_DESC": "Determina se un'identità può essere collegata a un account esistente."
"ISLINKINGALLOWED_DESC": "Determina se un'identità può essere collegata a un account esistente.",
"AUTOLINKING_DESC": "Determina se un'identità verrà invitata a essere collegata a un account esistente.",
"AUTOLINKINGTYPE": {
"0": "Disabilitato",
"1": "Verifica dell'esistenza del nome utente",
"2": "Verifica dell'esistenza dell'email"
}
},
"OWNERTYPES": {
"0": "sconosciuto",

View File

@ -1610,6 +1610,7 @@
"initPasswordText": "パスワードを初期化する",
"initializeDoneText": "ユーザーの初期化が完了しました",
"initializeUserText": "ユーザーを初期化する",
"linkingUserPromptText": "ユーザーのリンクプロンプト",
"linkingUserDoneText": "ユーザーのリンクが完了しました",
"loginText": "ログイン",
"logoutText": "ログアウト",
@ -2041,7 +2042,13 @@
"ISCREATIONALLOWED": "アカウント作成を許可",
"ISCREATIONALLOWED_DESC": "アカウントを作成できるかどうかを決めます。",
"ISLINKINGALLOWED": "アカウントリンクを許可",
"ISLINKINGALLOWED_DESC": "IDを既存のアカウントにリンクできるかどうかを決めます。"
"ISLINKINGALLOWED_DESC": "IDを既存のアカウントにリンクできるかどうかを決めます。",
"AUTOLINKING_DESC": "アイデンティティが既存のアカウントにリンクされるように促されるかどうかを決定します。",
"AUTOLINKINGTYPE": {
"0": "無効",
"1": "既存のユーザー名のチェック",
"2": "既存のメールアドレスのチェック"
}
},
"OWNERTYPES": {
"0": "不明",

View File

@ -1616,6 +1616,7 @@
"initPasswordText": "Иницијализација на лозинка",
"initializeDoneText": "Иницијализацијата на корисникот е завршена",
"initializeUserText": "Иницијализација на корисник",
"linkingUserPromptText": "Поврзување на кориснички промпт",
"linkingUserDoneText": "Поврзувањето на корисникот е завршено",
"loginText": "Најава",
"logoutText": "Одјава",
@ -2049,7 +2050,13 @@
"ISCREATIONALLOWED": "Дозволено креирање на кориснички сметки",
"ISCREATIONALLOWED_DESC": "Одредува дали може да се креираат кориснички сметки.",
"ISLINKINGALLOWED": "Дозволено поврзување на кориснички сметки",
"ISLINKINGALLOWED_DESC": "Одредува дали може да се поврзе идентитет со постоечка корисничка сметка."
"ISLINKINGALLOWED_DESC": "Одредува дали може да се поврзе идентитет со постоечка корисничка сметка.",
"AUTOLINKING_DESC": "Одредува дали ќе се бара идентитетот да биде поврзан со постоечки профил.",
"AUTOLINKINGTYPE": {
"0": "Исклучено",
"1": "Проверка за постоечко корисничко име",
"2": "Проверка за постоечка е-пошта"
}
},
"OWNERTYPES": {
"0": "непознато",

View File

@ -1615,6 +1615,7 @@
"initPasswordText": "Initialiseer wachtwoord",
"initializeDoneText": "Gebruiker initialisatie voltooid",
"initializeUserText": "Initialiseer gebruiker",
"linkingUserPromptText": "Gebruiker koppelingsprompt",
"linkingUserDoneText": "Gebruiker koppeling voltooid",
"loginText": "Login",
"logoutText": "Uitloggen",
@ -2054,7 +2055,13 @@
"ISCREATIONALLOWED": "Account creatie toegestaan",
"ISCREATIONALLOWED_DESC": "Bepaalt of accounts kunnen worden aangemaakt.",
"ISLINKINGALLOWED": "Account koppeling toegestaan",
"ISLINKINGALLOWED_DESC": "Bepaalt of een identiteit kan worden gekoppeld aan een bestaand account."
"ISLINKINGALLOWED_DESC": "Bepaalt of een identiteit kan worden gekoppeld aan een bestaand account.",
"AUTOLINKING_DESC": "Bepaalt of een identiteit wordt gevraagd om te worden gekoppeld aan een bestaand account.",
"AUTOLINKINGTYPE": {
"0": "Uitgeschakeld",
"1": "Controleren op bestaande gebruikersnaam",
"2": "Controleren op bestaand e-mailadres"
}
},
"OWNERTYPES": {
"0": "onbekend",

View File

@ -1614,6 +1614,7 @@
"initPasswordText": "Inicjalizacja hasła",
"initializeDoneText": "Inicjalizacja użytkownika zakończona",
"initializeUserText": "Inicjalizacja użytkownika",
"linkingUserPromptText": "Komunikat o łączeniu użytkowników",
"linkingUserDoneText": "Łączenie użytkownika zakończone",
"loginText": "Zaloguj się",
"logoutText": "Wyloguj się",
@ -2045,7 +2046,13 @@
"ISCREATIONALLOWED": "tworzenie dozwolone",
"ISCREATIONALLOWED_DESC": "Określa, czy można tworzyć konta.",
"ISLINKINGALLOWED": "dozwolone łączenie rachunków",
"ISLINKINGALLOWED_DESC": "Określa, czy tożsamość może być powiązana z istniejącym kontem."
"ISLINKINGALLOWED_DESC": "Określa, czy tożsamość może być powiązana z istniejącym kontem.",
"AUTOLINKING_DESC": "Określa, czy tożsamość będzie proszona o połączenie z istniejącym kontem.",
"AUTOLINKINGTYPE": {
"0": "Wyłączone",
"1": "Sprawdź istniejącą nazwę użytkownika",
"2": "Sprawdź istniejący adres e-mail"
}
},
"OWNERTYPES": {
"0": "nieznany",

View File

@ -1616,6 +1616,7 @@
"initPasswordText": "Inicialização de senha",
"initializeDoneText": "Inicialização de usuário concluída",
"initializeUserText": "Inicializaçãode usuário",
"linkingUserPromptText": "Prompt de usuário para vinculação",
"linkingUserDoneText": "Vinculação de usuário concluída",
"loginText": "Login",
"logoutText": "Logout",
@ -2047,7 +2048,13 @@
"ISCREATIONALLOWED": "Criação de Conta Permitida",
"ISCREATIONALLOWED_DESC": "Determina se as contas podem ser criadas.",
"ISLINKINGALLOWED": "Vinculação de Conta Permitida",
"ISLINKINGALLOWED_DESC": "Determina se uma identidade pode ser vinculada a uma conta existente."
"ISLINKINGALLOWED_DESC": "Determina se uma identidade pode ser vinculada a uma conta existente.",
"AUTOLINKING_DESC": "Determina se uma identidade será solicitada a ser vinculada a uma conta existente.",
"AUTOLINKINGTYPE": {
"0": "Desativado",
"1": "Verificar nome de usuário existente",
"2": "Verificar e-mail existente"
}
},
"OWNERTYPES": {
"0": "desconhecido",

View File

@ -1681,6 +1681,7 @@
"initPasswordText": "Инициализировать пароль",
"initializeDoneText": "Инициализация пользователя выполнена",
"initializeUserText": "Инициализировать пользователя",
"linkingUserPromptText": "Текст приглашения к привязке пользователя",
"linkingUserDoneText": "Привязка пользователя выполнена",
"loginText": "Вход",
"logoutText": "Выход",
@ -2139,7 +2140,13 @@
"ISCREATIONALLOWED": "Создание учетной записи разрешено",
"ISCREATIONALLOWED_DESC": "Определяет, можно ли создавать учетные записи.",
"ISLINKINGALLOWED": "Привязка аккаунтов разрешена",
"ISLINKINGALLOWED_DESC": "Определяет, можно ли связать личность с существующей учетной записью."
"ISLINKINGALLOWED_DESC": "Определяет, можно ли связать личность с существующей учетной записью.",
"AUTOLINKING_DESC": "Определяет, будет ли запрошено связать идентификацию с существующим аккаунтом.",
"AUTOLINKINGTYPE": {
"0": "Отключено",
"1": "Проверка существующего имени пользователя",
"2": "Проверка существующего адреса электронной почты"
}
},
"OWNERTYPES": {
"0": "неизвестен",

View File

@ -1613,6 +1613,7 @@
"initPasswordText": "初始化密码",
"initializeDoneText": "初始化用户完成",
"initializeUserText": "初始化用户",
"linkingUserPromptText": "用户链接提示",
"linkingUserDoneText": "链接用户完成",
"loginText": "登录",
"logoutText": "登出",
@ -2044,7 +2045,13 @@
"ISCREATIONALLOWED": "是否允许创作",
"ISCREATIONALLOWED_DESC": "确定是否可以创建账户。",
"ISLINKINGALLOWED": "是否允许连接",
"ISLINKINGALLOWED_DESC": "确定一个身份是否可以与一个现有的账户相联系。"
"ISLINKINGALLOWED_DESC": "确定一个身份是否可以与一个现有的账户相联系。",
"AUTOLINKING_DESC": "确定是否提示将身份链接到现有帐户。",
"AUTOLINKINGTYPE": {
"0": "已禁用",
"1": "检查现有用户名",
"2": "检查现有电子邮件"
}
},
"OWNERTYPES": {
"0": "未知",

View File

@ -172,6 +172,7 @@ func SetLoginTextToDomain(req *admin_pb.SetCustomLoginTextsRequest) *domain.Cust
result.RegistrationUser = text.RegistrationUserScreenTextPbToDomain(req.RegistrationUserText)
result.ExternalRegistrationUserOverview = text.ExternalRegistrationUserOverviewScreenTextPbToDomain(req.ExternalRegistrationUserOverviewText)
result.RegistrationOrg = text.RegistrationOrgScreenTextPbToDomain(req.RegistrationOrgText)
result.LinkingUserPrompt = text.LinkingUserPromptScreenTextPbToDomain(req.LinkingUserPromptText)
result.LinkingUsersDone = text.LinkingUserDoneScreenTextPbToDomain(req.LinkingUserDoneText)
result.ExternalNotFound = text.ExternalUserNotFoundScreenTextPbToDomain(req.ExternalUserNotFoundText)
result.LoginSuccess = text.SuccessLoginScreenTextPbToDomain(req.SuccessLoginText)

View File

@ -1060,6 +1060,7 @@ func (s *Server) getCustomLoginTexts(ctx context.Context, org string, languages
RegistrationUserText: text_grpc.RegistrationUserScreenTextToPb(text.RegistrationUser),
ExternalRegistrationUserOverviewText: text_grpc.ExternalRegistrationUserOverviewScreenTextToPb(text.ExternalRegistrationUserOverview),
RegistrationOrgText: text_grpc.RegistrationOrgScreenTextToPb(text.RegistrationOrg),
LinkingUserPromptText: text_grpc.LinkingUserPromptScreenTextToPb(text.LinkingUserPrompt),
LinkingUserDoneText: text_grpc.LinkingUserDoneScreenTextToPb(text.LinkingUsersDone),
ExternalUserNotFoundText: text_grpc.ExternalUserNotFoundScreenTextToPb(text.ExternalNotFound),
SuccessLoginText: text_grpc.SuccessLoginScreenTextToPb(text.LoginSuccess),

View File

@ -274,6 +274,20 @@ func OptionsToCommand(options *idp_pb.Options) idp.Options {
IsLinkingAllowed: options.IsLinkingAllowed,
IsAutoCreation: options.IsAutoCreation,
IsAutoUpdate: options.IsAutoUpdate,
AutoLinkingOption: autoLinkingOptionToCommand(options.AutoLinking),
}
}
func autoLinkingOptionToCommand(linking idp_pb.AutoLinkingOption) domain.AutoLinkingOption {
switch linking {
case idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME:
return domain.AutoLinkingOptionUsername
case idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL:
return domain.AutoLinkingOptionEmail
case idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_UNSPECIFIED:
return domain.AutoLinkingOptionUnspecified
default:
return domain.AutoLinkingOptionUnspecified
}
}
@ -398,6 +412,7 @@ func configToPb(config *query.IDPTemplate) *idp_pb.ProviderConfig {
IsCreationAllowed: config.IsCreationAllowed,
IsAutoCreation: config.IsAutoCreation,
IsAutoUpdate: config.IsAutoUpdate,
AutoLinking: autoLinkingOptionToPb(config.AutoLinking),
},
}
if config.OAuthIDPTemplate != nil {
@ -451,6 +466,19 @@ func configToPb(config *query.IDPTemplate) *idp_pb.ProviderConfig {
return providerConfig
}
func autoLinkingOptionToPb(linking domain.AutoLinkingOption) idp_pb.AutoLinkingOption {
switch linking {
case domain.AutoLinkingOptionUnspecified:
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_UNSPECIFIED
case domain.AutoLinkingOptionUsername:
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME
case domain.AutoLinkingOptionEmail:
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL
default:
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_UNSPECIFIED
}
}
func oauthConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.OAuthIDPTemplate) {
providerConfig.Config = &idp_pb.ProviderConfig_Oauth{
Oauth: &idp_pb.OAuthConfig{

View File

@ -171,6 +171,7 @@ func SetLoginCustomTextToDomain(req *mgmt_pb.SetCustomLoginTextsRequest) *domain
result.RegistrationUser = text.RegistrationUserScreenTextPbToDomain(req.RegistrationUserText)
result.ExternalRegistrationUserOverview = text.ExternalRegistrationUserOverviewScreenTextPbToDomain(req.ExternalRegistrationUserOverviewText)
result.RegistrationOrg = text.RegistrationOrgScreenTextPbToDomain(req.RegistrationOrgText)
result.LinkingUserPrompt = text.LinkingUserPromptScreenTextPbToDomain(req.LinkingUserPromptText)
result.LinkingUsersDone = text.LinkingUserDoneScreenTextPbToDomain(req.LinkingUserDoneText)
result.ExternalNotFound = text.ExternalUserNotFoundScreenTextPbToDomain(req.ExternalUserNotFoundText)
result.LoginSuccess = text.SuccessLoginScreenTextPbToDomain(req.SuccessLoginText)

View File

@ -64,6 +64,7 @@ func CustomLoginTextToPb(text *domain.CustomLoginText) *text_pb.LoginCustomText
RegistrationUserText: RegistrationUserScreenTextToPb(text.RegistrationUser),
ExternalRegistrationUserOverviewText: ExternalRegistrationUserOverviewScreenTextToPb(text.ExternalRegistrationUserOverview),
RegistrationOrgText: RegistrationOrgScreenTextToPb(text.RegistrationOrg),
LinkingUserPromptText: LinkingUserPromptScreenTextToPb(text.LinkingUserPrompt),
LinkingUserDoneText: LinkingUserDoneScreenTextToPb(text.LinkingUsersDone),
ExternalUserNotFoundText: ExternalUserNotFoundScreenTextToPb(text.ExternalNotFound),
SuccessLoginText: SuccessLoginScreenTextToPb(text.LoginSuccess),
@ -422,6 +423,15 @@ func LinkingUserDoneScreenTextToPb(text domain.LinkingUserDoneScreenText) *text_
}
}
func LinkingUserPromptScreenTextToPb(text domain.LinkingUserPromptScreenText) *text_pb.LinkingUserPromptScreenText {
return &text_pb.LinkingUserPromptScreenText{
Title: text.Title,
Description: text.Description,
LinkButtonText: text.LinkButtonText,
OtherButtonText: text.OtherButtonText,
}
}
func ExternalUserNotFoundScreenTextToPb(text domain.ExternalUserNotFoundScreenText) *text_pb.ExternalUserNotFoundScreenText {
return &text_pb.ExternalUserNotFoundScreenText{
Title: text.Title,
@ -890,6 +900,15 @@ func RegistrationOrgScreenTextPbToDomain(text *text_pb.RegistrationOrgScreenText
}
}
func LinkingUserPromptScreenTextPbToDomain(text *text_pb.LinkingUserPromptScreenText) domain.LinkingUserPromptScreenText {
return domain.LinkingUserPromptScreenText{
Title: text.GetTitle(),
Description: text.GetDescription(),
LinkButtonText: text.GetLinkButtonText(),
OtherButtonText: text.GetOtherButtonText(),
}
}
func LinkingUserDoneScreenTextPbToDomain(text *text_pb.LinkingUserDoneScreenText) domain.LinkingUserDoneScreenText {
if text == nil {
return domain.LinkingUserDoneScreenText{}

View File

@ -449,6 +449,59 @@ func (l *Login) handleExternalUserAuthenticated(
callback(w, r, authReq)
}
// checkAutoLinking checks if a user with the provided information (username or email) already exists within ZITADEL.
// The decision, which information will be checked is based on the IdP template option.
// The function returns a boolean whether a user was found or not.
func (l *Login) checkAutoLinking(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, provider *query.IDPTemplate, externalUser *domain.ExternalUser) bool {
queries := make([]query.SearchQuery, 0, 2)
var user *query.NotifyUser
switch provider.AutoLinking {
case domain.AutoLinkingOptionUnspecified:
// is auto linking is disable, we shouldn't even get here, but in case we do we can directly return
return false
case domain.AutoLinkingOptionUsername:
// if we're checking for usernames there are to options:
//
// If no specific org has been requested (by id or domain scope), we'll check the provided username against
// all existing loginnames and directly use that result to either prompt or continue with other idp options.
if authReq.RequestedOrgID == "" {
user, err := l.query.GetNotifyUserByLoginName(r.Context(), false, externalUser.PreferredUsername)
if err != nil {
return false
}
l.renderLinkingUserPrompt(w, r, authReq, user, nil)
return true
}
// If a specific org has been requested, we'll check the provided username against usernames (of that org).
usernameQuery, err := query.NewUserUsernameSearchQuery(externalUser.PreferredUsername, query.TextEqualsIgnoreCase)
if err != nil {
return false
}
queries = append(queries, usernameQuery)
case domain.AutoLinkingOptionEmail:
// Email will always be checked against verified email addresses.
emailQuery, err := query.NewUserVerifiedEmailSearchQuery(string(externalUser.Email))
if err != nil {
return false
}
queries = append(queries, emailQuery)
}
// restrict the possible organization if needed (for email and usernames)
if authReq.RequestedOrgID != "" {
resourceOwnerQuery, err := query.NewUserResourceOwnerSearchQuery(authReq.RequestedOrgID, query.TextEquals)
if err != nil {
return false
}
queries = append(queries, resourceOwnerQuery)
}
user, err := l.query.GetNotifyUser(r.Context(), false, queries...)
if err != nil {
return false
}
l.renderLinkingUserPrompt(w, r, authReq, user, nil)
return true
}
// externalUserNotExisting is called if an externalAuthentication couldn't find a corresponding externalID
// possible solutions are:
//
@ -470,6 +523,13 @@ func (l *Login) externalUserNotExisting(w http.ResponseWriter, r *http.Request,
}
human, idpLink, _ := mapExternalUserToLoginUser(externalUser, orgIAMPolicy.UserLoginMustBeDomain)
// let's check if auto-linking is enabled and if the user would be found by the corresponding option
if provider.AutoLinking != domain.AutoLinkingOptionUnspecified {
if l.checkAutoLinking(w, r, authReq, provider, externalUser) {
return
}
}
// if auto creation or creation itself is disabled, send the user to the notFoundOption
if !provider.IsCreationAllowed || !provider.IsAutoCreation {
l.renderExternalNotFoundOption(w, r, authReq, orgIAMPolicy, human, idpLink, err)

View File

@ -0,0 +1,62 @@
package login
import (
"net/http"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
)
const (
tmplLinkingUserPrompt = "link_user_prompt"
)
type linkingUserPromptData struct {
userData
Username string
Linking domain.AutoLinkingOption
UserID string
}
type linkingUserPromptFormData struct {
OtherUser bool `schema:"other"`
UserID string `schema:"userID"`
}
func (l *Login) renderLinkingUserPrompt(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, user *query.NotifyUser, err error) {
var errID, errMessage string
if err != nil {
errID, errMessage = l.getErrorMessage(r, err)
}
translator := l.getTranslator(r.Context(), authReq)
identification := user.PreferredLoginName
// hide the suffix in case the option is set and the auth request has been started with the primary domain scope
if authReq.RequestedOrgDomain && authReq.LabelPolicy != nil && authReq.LabelPolicy.HideLoginNameSuffix {
identification = user.Username
}
data := &linkingUserPromptData{
Username: identification,
UserID: user.ID,
userData: l.getUserData(r, authReq, translator, "LinkingUserPrompt.Title", "LinkingUserPrompt.Description", errID, errMessage),
}
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplLinkingUserPrompt], data, nil)
}
func (l *Login) handleLinkingUserPrompt(w http.ResponseWriter, r *http.Request) {
data := new(linkingUserPromptFormData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderLogin(w, r, authReq, err)
return
}
if data.OtherUser {
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil)
return
}
err = l.authRepo.SelectUser(r.Context(), authReq.ID, data.UserID, authReq.AgentID)
if err != nil {
l.renderLogin(w, r, authReq, err)
return
}
l.renderNextStep(w, r, authReq)
}

View File

@ -83,6 +83,7 @@ func CreateRenderer(pathPrefix string, staticStorage static.Storage, cookieName
tmplLDAPLogin: "ldap_login.html",
tmplDeviceAuthUserCode: "device_usercode.html",
tmplDeviceAuthAction: "device_action.html",
tmplLinkingUserPrompt: "link_user_prompt.html",
}
funcs := map[string]interface{}{
"resourceUrl": func(file string) string {
@ -235,6 +236,9 @@ func CreateRenderer(pathPrefix string, staticStorage static.Storage, cookieName
"ldapUrl": func() string {
return path.Join(r.pathPrefix, EndpointLDAPCallback)
},
"linkingUserPromptUrl": func() string {
return path.Join(r.pathPrefix, EndpointLinkingUserPrompt)
},
}
var err error
r.Renderer, err = renderer.NewRenderer(

View File

@ -53,6 +53,8 @@ const (
EndpointDeviceAuth = "/device"
EndpointDeviceAuthAction = "/device/{action}"
EndpointLinkingUserPrompt = "/link/user"
)
var (
@ -122,5 +124,6 @@ func CreateRouter(login *Login, interceptors ...mux.MiddlewareFunc) *mux.Router
router.SkipClean(true).Handle("", http.RedirectHandler(HandlerPrefix+"/", http.StatusMovedPermanently))
router.HandleFunc(EndpointDeviceAuth, login.handleDeviceAuthUserCode).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc(EndpointDeviceAuthAction, login.handleDeviceAuthAction).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc(EndpointLinkingUserPrompt, login.handleLinkingUserPrompt).Methods(http.MethodPost)
return router
}

View File

@ -316,6 +316,11 @@ LogoutDone:
Title: Излязъл
Description: Вие излязохте успешно.
LoginButtonText: Влизам
LinkingUserPrompt:
Title: Намерен съществуващ потребител
Description: „Искате ли да свържете съществуващия си акаунт:“
LinkButtonText: Връзка
OtherButtonText: Други възможности
LinkingUsersDone:
Title: Свързване с потребители
Description: Свързването с потребители е готово.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: Byli jste úspěšně odhlášeni.
LoginButtonText: Přihlásit se
LinkingUserPrompt:
Title: Nalezen stávající uživatel
Description: "Chcete propojit svůj stávající účet:"
LinkButtonText: Odkaz
OtherButtonText: Jiné možnosti
LinkingUsersDone:
Title: Propojení uživatele
Description: Uživatel propojen.

View File

@ -324,6 +324,12 @@ LogoutDone:
Description: Du wurdest erfolgreich abgemeldet.
LoginButtonText: Anmelden
LinkingUserPrompt:
Title: Vorhandener Benutzer gefunden
Description: "Möchten Sie Ihr bestehendes Konto verknüpfen:"
LinkButtonText: Verknüpfen
OtherButtonText: Andere Optionen
LinkingUsersDone:
Title: Benutzerkonto verknpüfen
Description: Benuzterkonto verknpüft.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: You have logged out successfully.
LoginButtonText: Login
LinkingUserPrompt:
Title: Existing User Found
Description: "Do you want to link your existing account:"
LinkButtonText: Link
OtherButtonText: Other options
LinkingUsersDone:
Title: Linking User
Description: User linked.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: Cerraste la sesión con éxito.
LoginButtonText: iniciar sesión
LinkingUserPrompt:
Title: Usuario existente encontrado
Description: "¿Quieres vincular tu cuenta existente?"
LinkButtonText: Vincular
OtherButtonText: Otras opciones
LinkingUsersDone:
Title: Vinculación de usuario
Description: usuario vinculado con éxito.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: Vous vous êtes déconnecté avec succès.
LoginButtonText: connexion
LinkingUserPrompt:
Title: Utilisateur existant trouvé
Description: "Souhaitez-vous associer votre compte existant:"
LinkButtonText: Lier
OtherButtonText: Autres options
LinkingUsersDone:
Title: Userlinking
Description: Le lien avec l'utilisateur est terminé.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: Ti sei disconnesso con successo.
LoginButtonText: Accedi
LinkingUserPrompt:
Title: Utente esistente trovato
Description: "Desideri collegare il tuo account esistente:"
LinkButtonText: Collegare
OtherButtonText: Altre opzioni
LinkingUsersDone:
Title: Collegamento utente
Description: Collegamento fatto.

View File

@ -317,6 +317,12 @@ LogoutDone:
Description: 正常にログアウトしました。
LoginButtonText: ログイン
LinkingUserPrompt:
Title: 既存のユーザーが見つかりました
Description: "既存のアカウントをリンクしますか:"
LinkButtonText: リンク
OtherButtonText: その他のオプション
LinkingUsersDone:
Title: ユーザーリンク
Description: ユーザーリンクが完了しました。

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: Успешно сте одјавени.
LoginButtonText: најава
LinkingUserPrompt:
Title: Пронајден е постоечки корисник
Description: "Дали сакате да ја поврзете вашата постоечка сметка:"
LinkButtonText: Bрска
OtherButtonText: Други опции
LinkingUsersDone:
Title: Поврзување на корисници
Description: Поврзувањето на корисници е завршено.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: U heeft succesvol uitgelogd.
LoginButtonText: Inloggen
LinkingUserPrompt:
Title: Bestaande gebruiker gevonden
Description: "Wilt u uw bestaande account koppelen:"
LinkButtonText: Koppeling
OtherButtonText: Andere opties
LinkingUsersDone:
Title: Koppeling Gebruiker
Description: Gebruiker gekoppeld.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: Wylogowano pomyślnie.
LoginButtonText: Zaloguj się
LinkingUserPrompt:
Title: Znaleziono istniejącego użytkownika
Description: "Czy chcesz połączyć swoje istniejące konto:"
LinkButtonText: Połączyć
OtherButtonText: Inne opcje
LinkingUsersDone:
Title: Łączenie użytkowników
Description: Łączenie użytkowników zakończone pomyślnie.

View File

@ -321,6 +321,12 @@ LogoutDone:
Description: Você fez logout com sucesso.
LoginButtonText: login
LinkingUserPrompt:
Title: Usuário existente encontrado
Description: "Deseja vincular sua conta existente:"
LinkButtonText: Link
OtherButtonText: Outras opções
LinkingUsersDone:
Title: Vinculação de usuários
Description: Vinculação de usuários concluída.

View File

@ -324,6 +324,12 @@ LogoutDone:
Description: Вы успешно вышли из системы.
LoginButtonText: вход
LinkingUserPrompt:
Title: Существующий пользователь найден
Description: "Хотите ли вы связать существующую учетную запись:"
LinkButtonText: Связь
OtherButtonText: Другие варианты
LinkingUsersDone:
Title: Привязка пользователя
Description: Привязка пользователя выполнена.

View File

@ -325,6 +325,12 @@ LogoutDone:
Description: 您已成功退出登录。
LoginButtonText: 登录
LinkingUserPrompt:
Title: 已找到现有用户
Description: "您想关联您现有的帐户吗:"
LinkButtonText: 关联
OtherButtonText: 其他选项
LinkingUsersDone:
Title: 用户链接
Description: 用户链接完成。

View File

@ -0,0 +1,37 @@
{{template "main-top" .}}
<div class="lgn-head">
<h1>{{t "LinkingUserPrompt.Title"}}</h1>
<p>
{{t "LinkingUserPrompt.Description"}}<br>
{{.Username}}
</p>
</div>
<form action="{{ linkingUserPromptUrl }}" method="POST">
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" name="userID" value="{{ .UserID }}" />
{{template "error-message" .}}
<div class="lgn-actions lgn-reverse-order">
<a class="lgn-icon-button lgn-left-action" id="back-button" href="#">
<i class="lgn-icon-arrow-left-solid"></i>
</a>
<button class="lgn-raised-button lgn-primary lgn-initial-focus" id="submit-button" type="submit">{{t "LinkingUserPrompt.LinkButtonText"}}</button>
<span class="fill-space"></span>
<button class="lgn-stroked-button" name="other" value="true">{{t "LinkingUserPrompt.OtherButtonText"}}</button>
</div>
</form>
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
<script src="{{ resourceUrl "scripts/go_back.js" }}"></script>
{{template "main-bottom" .}}

View File

@ -19,7 +19,7 @@ type AuthRequestRepository interface {
CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *domain.ExternalUser, info *domain.BrowserInfo, migrationCheck bool) error
SetExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *domain.ExternalUser) error
SetLinkingUser(ctx context.Context, request *domain.AuthRequest, externalUser *domain.ExternalUser) error
SelectUser(ctx context.Context, id, userID, userAgentID string) error
SelectUser(ctx context.Context, authReqID, userID, userAgentID string) error
SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) error
VerifyPassword(ctx context.Context, id, userID, resourceOwner, password, userAgentID string, info *domain.BrowserInfo) error

View File

@ -304,10 +304,10 @@ func (repo *AuthRequestRepo) setLinkingUser(ctx context.Context, request *domain
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAgentID string) (err error) {
func (repo *AuthRequestRepo) SelectUser(ctx context.Context, authReqID, userID, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
}

View File

@ -42,7 +42,8 @@ func (c *Commands) createAllLoginTextEvents(ctx context.Context, agg *eventstore
events = append(events, c.createRegistrationUserEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createExternalRegistrationUserOverviewEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createRegistrationOrgEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createLinkingUserEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createLinkingUserPromptEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createLinkingUserDoneEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createExternalUserNotFoundEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createSuccessLoginEvents(ctx, agg, existingText, text, defaultText)...)
events = append(events, c.createLogoutDoneEvents(ctx, agg, existingText, text, defaultText)...)
@ -979,7 +980,28 @@ func (c *Commands) createRegistrationOrgEvents(ctx context.Context, agg *eventst
return events
}
func (c *Commands) createLinkingUserEvents(ctx context.Context, agg *eventstore.Aggregate, existingText *CustomLoginTextReadModel, text *domain.CustomLoginText, defaultText bool) []eventstore.Command {
func (c *Commands) createLinkingUserPromptEvents(ctx context.Context, agg *eventstore.Aggregate, existingText *CustomLoginTextReadModel, text *domain.CustomLoginText, defaultText bool) []eventstore.Command {
events := make([]eventstore.Command, 0)
event := c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyLinkingUserPromptTitle, existingText.LinkingUserPromptTitle, text.LinkingUserPrompt.Title, text.Language, defaultText)
if event != nil {
events = append(events, event)
}
event = c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyLinkingUserPromptDescription, existingText.LinkingUserPromptDescription, text.LinkingUserPrompt.Description, text.Language, defaultText)
if event != nil {
events = append(events, event)
}
event = c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyLinkingUserPromptLinkButtonText, existingText.LinkingUserPromptLinkButtonText, text.LinkingUserPrompt.LinkButtonText, text.Language, defaultText)
if event != nil {
events = append(events, event)
}
event = c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyLinkingUserPromptOtherButtonText, existingText.LinkingUserPromptOtherButtonText, text.LinkingUserPrompt.OtherButtonText, text.Language, defaultText)
if event != nil {
events = append(events, event)
}
return events
}
func (c *Commands) createLinkingUserDoneEvents(ctx context.Context, agg *eventstore.Aggregate, existingText *CustomLoginTextReadModel, text *domain.CustomLoginText, defaultText bool) []eventstore.Command {
events := make([]eventstore.Command, 0)
event := c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyLinkingUserDoneTitle, existingText.LinkingUserDoneTitle, text.LinkingUsersDone.Title, text.Language, defaultText)
if event != nil {

View File

@ -262,6 +262,11 @@ type CustomLoginTextReadModel struct {
RegisterOrgPrivacyLinkText string
RegisterOrgSaveButtonText string
LinkingUserPromptTitle string
LinkingUserPromptDescription string
LinkingUserPromptLinkButtonText string
LinkingUserPromptOtherButtonText string
LinkingUserDoneTitle string
LinkingUserDoneDescription string
LinkingUserDoneCancelButtonText string
@ -416,6 +421,10 @@ func (wm *CustomLoginTextReadModel) Reduce() error {
wm.handleRegistrationOrgScreenSetEvent(e)
continue
}
if strings.HasPrefix(e.Key, domain.LoginKeyLinkingUserPrompt) {
wm.handleLinkingUserPromptScreenSetEvent(e)
continue
}
if strings.HasPrefix(e.Key, domain.LoginKeyLinkingUserDone) {
wm.handleLinkingUserDoneScreenSetEvent(e)
continue
@ -556,6 +565,10 @@ func (wm *CustomLoginTextReadModel) Reduce() error {
wm.handleRegistrationOrgScreenRemoveEvent(e)
continue
}
if strings.HasPrefix(e.Key, domain.LoginKeyLinkingUserPrompt) {
wm.handleLinkingUserPromptRemoveEvent(e)
continue
}
if strings.HasPrefix(e.Key, domain.LoginKeyLinkingUserDone) {
wm.handleLinkingUserDoneRemoveEvent(e)
continue
@ -2323,6 +2336,25 @@ func (wm *CustomLoginTextReadModel) handleRegistrationOrgScreenRemoveEvent(e *po
}
}
func (wm *CustomLoginTextReadModel) handleLinkingUserPromptScreenSetEvent(e *policy.CustomTextSetEvent) {
if e.Key == domain.LoginKeyLinkingUserPromptTitle {
wm.LinkingUserPromptTitle = e.Text
return
}
if e.Key == domain.LoginKeyLinkingUserPromptDescription {
wm.LinkingUserPromptDescription = e.Text
return
}
if e.Key == domain.LoginKeyLinkingUserPromptLinkButtonText {
wm.LinkingUserPromptLinkButtonText = e.Text
return
}
if e.Key == domain.LoginKeyLinkingUserPromptOtherButtonText {
wm.LinkingUserPromptOtherButtonText = e.Text
return
}
}
func (wm *CustomLoginTextReadModel) handleLinkingUserDoneScreenSetEvent(e *policy.CustomTextSetEvent) {
if e.Key == domain.LoginKeyLinkingUserDoneTitle {
wm.LinkingUserDoneTitle = e.Text
@ -2342,6 +2374,25 @@ func (wm *CustomLoginTextReadModel) handleLinkingUserDoneScreenSetEvent(e *polic
}
}
func (wm *CustomLoginTextReadModel) handleLinkingUserPromptRemoveEvent(e *policy.CustomTextRemovedEvent) {
if e.Key == domain.LoginKeyLinkingUserPromptTitle {
wm.LinkingUserPromptTitle = ""
return
}
if e.Key == domain.LoginKeyLinkingUserPromptDescription {
wm.LinkingUserPromptDescription = ""
return
}
if e.Key == domain.LoginKeyLinkingUserPromptLinkButtonText {
wm.LinkingUserPromptLinkButtonText = ""
return
}
if e.Key == domain.LoginKeyLinkingUserPromptOtherButtonText {
wm.LinkingUserPromptOtherButtonText = ""
return
}
}
func (wm *CustomLoginTextReadModel) handleLinkingUserDoneRemoveEvent(e *policy.CustomTextRemovedEvent) {
if e.Key == domain.LoginKeyLinkingUserDoneTitle {
wm.LinkingUserDoneTitle = ""

View File

@ -676,6 +676,18 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, "Title", language.English,
),
@ -1009,6 +1021,12 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
PrivacyLinkText: "PrivacyLinkText",
SaveButtonText: "SaveButtonText",
},
LinkingUserPrompt: domain.LinkingUserPromptScreenText{
Title: "Title",
Description: "Description",
LinkButtonText: "LinkButtonText",
OtherButtonText: "OtherButtonText",
},
LinkingUsersDone: domain.LinkingUserDoneScreenText{
Title: "Title",
Description: "Description",
@ -2233,6 +2251,30 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
@ -2967,6 +3009,18 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, language.English,
),
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, language.English,
),
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, language.English,
),
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, language.English,
),
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, language.English,
),
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, language.English,
),
@ -3075,6 +3129,7 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
RegistrationUser: domain.RegistrationUserScreenText{},
ExternalRegistrationUserOverview: domain.ExternalRegistrationUserOverviewScreenText{},
RegistrationOrg: domain.RegistrationOrgScreenText{},
LinkingUserPrompt: domain.LinkingUserPromptScreenText{},
LinkingUsersDone: domain.LinkingUserDoneScreenText{},
ExternalNotFound: domain.ExternalUserNotFoundScreenText{},
LoginSuccess: domain.SuccessLoginScreenText{},
@ -4271,6 +4326,30 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextSetEvent(context.Background(),
@ -5592,6 +5671,30 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, language.English,
),
),
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewCustomTextRemovedEvent(context.Background(),
@ -6326,6 +6429,18 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
instance.NewCustomTextSetEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, "Title", language.English,
),
@ -6659,6 +6774,12 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
PrivacyLinkText: "PrivacyLinkText",
SaveButtonText: "SaveButtonText",
},
LinkingUserPrompt: domain.LinkingUserPromptScreenText{
Title: "Title",
Description: "Description",
LinkButtonText: "LinkButtonText",
OtherButtonText: "OtherButtonText",
},
LinkingUsersDone: domain.LinkingUserDoneScreenText{
Title: "Title",
Description: "Description",

View File

@ -1083,6 +1083,26 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, "Title", language.English,
@ -1464,6 +1484,12 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
PrivacyLinkText: "PrivacyLinkText",
SaveButtonText: "SaveButtonText",
},
LinkingUserPrompt: domain.LinkingUserPromptScreenText{
Title: "Title",
Description: "Description",
LinkButtonText: "LinkButtonText",
OtherButtonText: "OtherButtonText",
},
LinkingUsersDone: domain.LinkingUserDoneScreenText{
Title: "Title",
Description: "Description",
@ -2487,6 +2513,26 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, "Title", language.English,
@ -3194,6 +3240,18 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, language.English,
),
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, language.English,
),
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, language.English,
),
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, language.English,
),
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, language.English,
),
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, language.English,
),
@ -3303,6 +3361,7 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
ExternalRegistrationUserOverview: domain.ExternalRegistrationUserOverviewScreenText{},
RegistrationUser: domain.RegistrationUserScreenText{},
RegistrationOrg: domain.RegistrationOrgScreenText{},
LinkingUserPrompt: domain.LinkingUserPromptScreenText{},
LinkingUsersDone: domain.LinkingUserDoneScreenText{},
ExternalNotFound: domain.ExternalUserNotFoundScreenText{},
LoginSuccess: domain.SuccessLoginScreenText{},
@ -4297,6 +4356,26 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, "Title", language.English,
@ -5392,6 +5471,26 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, language.English,
@ -6099,6 +6198,18 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyRegisterOrgSaveButtonText, "SaveButtonText", language.English,
),
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptTitle, "Title", language.English,
),
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptDescription, "Description", language.English,
),
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptLinkButtonText, "LinkButtonText", language.English,
),
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserPromptOtherButtonText, "OtherButtonText", language.English,
),
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, domain.LoginCustomText, domain.LoginKeyLinkingUserDoneTitle, "Title", language.English,
),
@ -6432,6 +6543,12 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
PrivacyLinkText: "PrivacyLinkText",
SaveButtonText: "SaveButtonText",
},
LinkingUserPrompt: domain.LinkingUserPromptScreenText{
Title: "Title",
Description: "Description",
LinkButtonText: "LinkButtonText",
OtherButtonText: "OtherButtonText",
},
LinkingUsersDone: domain.LinkingUserDoneScreenText{
Title: "Title",
Description: "Description",

View File

@ -264,6 +264,12 @@ const (
LoginKeyRegisterOrgSaveButtonText = LoginKeyRegistrationOrg + "SaveButtonText"
LoginKeyRegisterOrgBackButtonText = LoginKeyRegistrationOrg + "BackButtonText"
LoginKeyLinkingUserPrompt = "LinkingUserPrompt."
LoginKeyLinkingUserPromptTitle = LoginKeyLinkingUserPrompt + "Title"
LoginKeyLinkingUserPromptDescription = LoginKeyLinkingUserPrompt + "Description"
LoginKeyLinkingUserPromptLinkButtonText = LoginKeyLinkingUserPrompt + "LinkButtonText"
LoginKeyLinkingUserPromptOtherButtonText = LoginKeyLinkingUserPrompt + "OtherButtonText"
LoginKeyLinkingUserDone = "LinkingUsersDone."
LoginKeyLinkingUserDoneTitle = LoginKeyLinkingUserDone + "Title"
LoginKeyLinkingUserDoneDescription = LoginKeyLinkingUserDone + "Description"
@ -336,6 +342,7 @@ type CustomLoginText struct {
RegistrationUser RegistrationUserScreenText
ExternalRegistrationUserOverview ExternalRegistrationUserOverviewScreenText
RegistrationOrg RegistrationOrgScreenText
LinkingUserPrompt LinkingUserPromptScreenText
LinkingUsersDone LinkingUserDoneScreenText
ExternalNotFound ExternalUserNotFoundScreenText
LoginSuccess SuccessLoginScreenText
@ -607,6 +614,13 @@ type RegistrationOrgScreenText struct {
SaveButtonText string
}
type LinkingUserPromptScreenText struct {
Title string
Description string
LinkButtonText string
OtherButtonText string
}
type LinkingUserDoneScreenText struct {
Title string
Description string

View File

@ -126,3 +126,11 @@ func (s IDPIntentState) Valid() bool {
func (s IDPIntentState) Exists() bool {
return s != IDPIntentStateUnspecified && s != IDPIntentStateFailed //TODO: ?
}
type AutoLinkingOption uint8
const (
AutoLinkingOptionUnspecified AutoLinkingOption = iota
AutoLinkingOptionUsername
AutoLinkingOptionEmail
)

View File

@ -409,8 +409,11 @@ func CustomTextsToLoginDomain(instanceID, aggregateID, lang string, texts *Custo
if strings.HasPrefix(text.Key, domain.LoginKeyRegistrationOrg) {
registrationOrgKeyToDomain(text, result)
}
if strings.HasPrefix(text.Key, domain.LoginKeyLinkingUserPrompt) {
linkingUserPromptKeyToDomain(text, result)
}
if strings.HasPrefix(text.Key, domain.LoginKeyLinkingUserDone) {
linkingUserKeyToDomain(text, result)
linkingUserDoneKeyToDomain(text, result)
}
if strings.HasPrefix(text.Key, domain.LoginKeyExternalNotFound) {
externalUserNotFoundKeyToDomain(text, result)
@ -1100,7 +1103,22 @@ func registrationOrgKeyToDomain(text *CustomText, result *domain.CustomLoginText
}
}
func linkingUserKeyToDomain(text *CustomText, result *domain.CustomLoginText) {
func linkingUserPromptKeyToDomain(text *CustomText, result *domain.CustomLoginText) {
if text.Key == domain.LoginKeyLinkingUserPromptTitle {
result.LinkingUserPrompt.Title = text.Text
}
if text.Key == domain.LoginKeyLinkingUserPromptDescription {
result.LinkingUserPrompt.Description = text.Text
}
if text.Key == domain.LoginKeyLinkingUserPromptLinkButtonText {
result.LinkingUserPrompt.LinkButtonText = text.Text
}
if text.Key == domain.LoginKeyLinkingUserPromptOtherButtonText {
result.LinkingUserPrompt.OtherButtonText = text.Text
}
}
func linkingUserDoneKeyToDomain(text *CustomText, result *domain.CustomLoginText) {
if text.Key == domain.LoginKeyLinkingUserDoneTitle {
result.LinkingUsersDone.Title = text.Text
}

View File

@ -16,12 +16,12 @@ import (
var (
loginPolicyIDPLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_login_policy_links5.idp_id,` +
` projections.idp_templates5.name,` +
` projections.idp_templates5.type,` +
` projections.idp_templates5.owner_type,` +
` projections.idp_templates6.name,` +
` projections.idp_templates6.type,` +
` projections.idp_templates6.owner_type,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_login_policy_links5` +
` LEFT JOIN projections.idp_templates5 ON projections.idp_login_policy_links5.idp_id = projections.idp_templates5.id AND projections.idp_login_policy_links5.instance_id = projections.idp_templates5.instance_id` +
` LEFT JOIN projections.idp_templates6 ON projections.idp_login_policy_links5.idp_id = projections.idp_templates6.id AND projections.idp_login_policy_links5.instance_id = projections.idp_templates6.instance_id` +
` RIGHT JOIN (SELECT login_policy_owner.aggregate_id, login_policy_owner.instance_id, login_policy_owner.owner_removed FROM projections.login_policies5 AS login_policy_owner` +
` WHERE (login_policy_owner.instance_id = $1 AND (login_policy_owner.aggregate_id = $2 OR login_policy_owner.aggregate_id = $3)) ORDER BY login_policy_owner.is_default LIMIT 1) AS login_policy_owner` +
` ON login_policy_owner.aggregate_id = projections.idp_login_policy_links5.resource_owner AND login_policy_owner.instance_id = projections.idp_login_policy_links5.instance_id` +

View File

@ -35,6 +35,7 @@ type IDPTemplate struct {
IsLinkingAllowed bool
IsAutoCreation bool
IsAutoUpdate bool
AutoLinking domain.AutoLinkingOption
*OAuthIDPTemplate
*OIDCIDPTemplate
*JWTIDPTemplate
@ -227,6 +228,10 @@ var (
name: projection.IDPTemplateIsAutoUpdateCol,
table: idpTemplateTable,
}
IDPTemplateAutoLinkingCol = Column{
name: projection.IDPTemplateAutoLinkingCol,
table: idpTemplateTable,
}
)
var (
@ -812,6 +817,7 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
IDPTemplateIsLinkingAllowedCol.identifier(),
IDPTemplateIsAutoCreationCol.identifier(),
IDPTemplateIsAutoUpdateCol.identifier(),
IDPTemplateAutoLinkingCol.identifier(),
// oauth
OAuthIDCol.identifier(),
OAuthClientIDCol.identifier(),
@ -1037,6 +1043,7 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
&idpTemplate.IsLinkingAllowed,
&idpTemplate.IsAutoCreation,
&idpTemplate.IsAutoUpdate,
&idpTemplate.AutoLinking,
// oauth
&oauthID,
&oauthClientID,
@ -1297,6 +1304,7 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
IDPTemplateIsLinkingAllowedCol.identifier(),
IDPTemplateIsAutoCreationCol.identifier(),
IDPTemplateIsAutoUpdateCol.identifier(),
IDPTemplateAutoLinkingCol.identifier(),
// oauth
OAuthIDCol.identifier(),
OAuthClientIDCol.identifier(),
@ -1527,6 +1535,7 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
&idpTemplate.IsLinkingAllowed,
&idpTemplate.IsAutoCreation,
&idpTemplate.IsAutoUpdate,
&idpTemplate.AutoLinking,
// oauth
&oauthID,
&oauthClientID,

View File

@ -16,128 +16,129 @@ import (
)
var (
idpTemplateQuery = `SELECT projections.idp_templates5.id,` +
` projections.idp_templates5.resource_owner,` +
` projections.idp_templates5.creation_date,` +
` projections.idp_templates5.change_date,` +
` projections.idp_templates5.sequence,` +
` projections.idp_templates5.state,` +
` projections.idp_templates5.name,` +
` projections.idp_templates5.type,` +
` projections.idp_templates5.owner_type,` +
` projections.idp_templates5.is_creation_allowed,` +
` projections.idp_templates5.is_linking_allowed,` +
` projections.idp_templates5.is_auto_creation,` +
` projections.idp_templates5.is_auto_update,` +
idpTemplateQuery = `SELECT projections.idp_templates6.id,` +
` projections.idp_templates6.resource_owner,` +
` projections.idp_templates6.creation_date,` +
` projections.idp_templates6.change_date,` +
` projections.idp_templates6.sequence,` +
` projections.idp_templates6.state,` +
` projections.idp_templates6.name,` +
` projections.idp_templates6.type,` +
` projections.idp_templates6.owner_type,` +
` projections.idp_templates6.is_creation_allowed,` +
` projections.idp_templates6.is_linking_allowed,` +
` projections.idp_templates6.is_auto_creation,` +
` projections.idp_templates6.is_auto_update,` +
` projections.idp_templates6.auto_linking,` +
// oauth
` projections.idp_templates5_oauth2.idp_id,` +
` projections.idp_templates5_oauth2.client_id,` +
` projections.idp_templates5_oauth2.client_secret,` +
` projections.idp_templates5_oauth2.authorization_endpoint,` +
` projections.idp_templates5_oauth2.token_endpoint,` +
` projections.idp_templates5_oauth2.user_endpoint,` +
` projections.idp_templates5_oauth2.scopes,` +
` projections.idp_templates5_oauth2.id_attribute,` +
` projections.idp_templates6_oauth2.idp_id,` +
` projections.idp_templates6_oauth2.client_id,` +
` projections.idp_templates6_oauth2.client_secret,` +
` projections.idp_templates6_oauth2.authorization_endpoint,` +
` projections.idp_templates6_oauth2.token_endpoint,` +
` projections.idp_templates6_oauth2.user_endpoint,` +
` projections.idp_templates6_oauth2.scopes,` +
` projections.idp_templates6_oauth2.id_attribute,` +
// oidc
` projections.idp_templates5_oidc.idp_id,` +
` projections.idp_templates5_oidc.issuer,` +
` projections.idp_templates5_oidc.client_id,` +
` projections.idp_templates5_oidc.client_secret,` +
` projections.idp_templates5_oidc.scopes,` +
` projections.idp_templates5_oidc.id_token_mapping,` +
` projections.idp_templates6_oidc.idp_id,` +
` projections.idp_templates6_oidc.issuer,` +
` projections.idp_templates6_oidc.client_id,` +
` projections.idp_templates6_oidc.client_secret,` +
` projections.idp_templates6_oidc.scopes,` +
` projections.idp_templates6_oidc.id_token_mapping,` +
// jwt
` projections.idp_templates5_jwt.idp_id,` +
` projections.idp_templates5_jwt.issuer,` +
` projections.idp_templates5_jwt.jwt_endpoint,` +
` projections.idp_templates5_jwt.keys_endpoint,` +
` projections.idp_templates5_jwt.header_name,` +
` projections.idp_templates6_jwt.idp_id,` +
` projections.idp_templates6_jwt.issuer,` +
` projections.idp_templates6_jwt.jwt_endpoint,` +
` projections.idp_templates6_jwt.keys_endpoint,` +
` projections.idp_templates6_jwt.header_name,` +
// azure
` projections.idp_templates5_azure.idp_id,` +
` projections.idp_templates5_azure.client_id,` +
` projections.idp_templates5_azure.client_secret,` +
` projections.idp_templates5_azure.scopes,` +
` projections.idp_templates5_azure.tenant,` +
` projections.idp_templates5_azure.is_email_verified,` +
` projections.idp_templates6_azure.idp_id,` +
` projections.idp_templates6_azure.client_id,` +
` projections.idp_templates6_azure.client_secret,` +
` projections.idp_templates6_azure.scopes,` +
` projections.idp_templates6_azure.tenant,` +
` projections.idp_templates6_azure.is_email_verified,` +
// github
` projections.idp_templates5_github.idp_id,` +
` projections.idp_templates5_github.client_id,` +
` projections.idp_templates5_github.client_secret,` +
` projections.idp_templates5_github.scopes,` +
` projections.idp_templates6_github.idp_id,` +
` projections.idp_templates6_github.client_id,` +
` projections.idp_templates6_github.client_secret,` +
` projections.idp_templates6_github.scopes,` +
// github enterprise
` projections.idp_templates5_github_enterprise.idp_id,` +
` projections.idp_templates5_github_enterprise.client_id,` +
` projections.idp_templates5_github_enterprise.client_secret,` +
` projections.idp_templates5_github_enterprise.authorization_endpoint,` +
` projections.idp_templates5_github_enterprise.token_endpoint,` +
` projections.idp_templates5_github_enterprise.user_endpoint,` +
` projections.idp_templates5_github_enterprise.scopes,` +
` projections.idp_templates6_github_enterprise.idp_id,` +
` projections.idp_templates6_github_enterprise.client_id,` +
` projections.idp_templates6_github_enterprise.client_secret,` +
` projections.idp_templates6_github_enterprise.authorization_endpoint,` +
` projections.idp_templates6_github_enterprise.token_endpoint,` +
` projections.idp_templates6_github_enterprise.user_endpoint,` +
` projections.idp_templates6_github_enterprise.scopes,` +
// gitlab
` projections.idp_templates5_gitlab.idp_id,` +
` projections.idp_templates5_gitlab.client_id,` +
` projections.idp_templates5_gitlab.client_secret,` +
` projections.idp_templates5_gitlab.scopes,` +
` projections.idp_templates6_gitlab.idp_id,` +
` projections.idp_templates6_gitlab.client_id,` +
` projections.idp_templates6_gitlab.client_secret,` +
` projections.idp_templates6_gitlab.scopes,` +
// gitlab self hosted
` projections.idp_templates5_gitlab_self_hosted.idp_id,` +
` projections.idp_templates5_gitlab_self_hosted.issuer,` +
` projections.idp_templates5_gitlab_self_hosted.client_id,` +
` projections.idp_templates5_gitlab_self_hosted.client_secret,` +
` projections.idp_templates5_gitlab_self_hosted.scopes,` +
` projections.idp_templates6_gitlab_self_hosted.idp_id,` +
` projections.idp_templates6_gitlab_self_hosted.issuer,` +
` projections.idp_templates6_gitlab_self_hosted.client_id,` +
` projections.idp_templates6_gitlab_self_hosted.client_secret,` +
` projections.idp_templates6_gitlab_self_hosted.scopes,` +
// google
` projections.idp_templates5_google.idp_id,` +
` projections.idp_templates5_google.client_id,` +
` projections.idp_templates5_google.client_secret,` +
` projections.idp_templates5_google.scopes,` +
` projections.idp_templates6_google.idp_id,` +
` projections.idp_templates6_google.client_id,` +
` projections.idp_templates6_google.client_secret,` +
` projections.idp_templates6_google.scopes,` +
// saml
` projections.idp_templates5_saml.idp_id,` +
` projections.idp_templates5_saml.metadata,` +
` projections.idp_templates5_saml.key,` +
` projections.idp_templates5_saml.certificate,` +
` projections.idp_templates5_saml.binding,` +
` projections.idp_templates5_saml.with_signed_request,` +
` projections.idp_templates6_saml.idp_id,` +
` projections.idp_templates6_saml.metadata,` +
` projections.idp_templates6_saml.key,` +
` projections.idp_templates6_saml.certificate,` +
` projections.idp_templates6_saml.binding,` +
` projections.idp_templates6_saml.with_signed_request,` +
// ldap
` projections.idp_templates5_ldap2.idp_id,` +
` projections.idp_templates5_ldap2.servers,` +
` projections.idp_templates5_ldap2.start_tls,` +
` projections.idp_templates5_ldap2.base_dn,` +
` projections.idp_templates5_ldap2.bind_dn,` +
` projections.idp_templates5_ldap2.bind_password,` +
` projections.idp_templates5_ldap2.user_base,` +
` projections.idp_templates5_ldap2.user_object_classes,` +
` projections.idp_templates5_ldap2.user_filters,` +
` projections.idp_templates5_ldap2.timeout,` +
` projections.idp_templates5_ldap2.id_attribute,` +
` projections.idp_templates5_ldap2.first_name_attribute,` +
` projections.idp_templates5_ldap2.last_name_attribute,` +
` projections.idp_templates5_ldap2.display_name_attribute,` +
` projections.idp_templates5_ldap2.nick_name_attribute,` +
` projections.idp_templates5_ldap2.preferred_username_attribute,` +
` projections.idp_templates5_ldap2.email_attribute,` +
` projections.idp_templates5_ldap2.email_verified,` +
` projections.idp_templates5_ldap2.phone_attribute,` +
` projections.idp_templates5_ldap2.phone_verified_attribute,` +
` projections.idp_templates5_ldap2.preferred_language_attribute,` +
` projections.idp_templates5_ldap2.avatar_url_attribute,` +
` projections.idp_templates5_ldap2.profile_attribute,` +
` projections.idp_templates6_ldap2.idp_id,` +
` projections.idp_templates6_ldap2.servers,` +
` projections.idp_templates6_ldap2.start_tls,` +
` projections.idp_templates6_ldap2.base_dn,` +
` projections.idp_templates6_ldap2.bind_dn,` +
` projections.idp_templates6_ldap2.bind_password,` +
` projections.idp_templates6_ldap2.user_base,` +
` projections.idp_templates6_ldap2.user_object_classes,` +
` projections.idp_templates6_ldap2.user_filters,` +
` projections.idp_templates6_ldap2.timeout,` +
` projections.idp_templates6_ldap2.id_attribute,` +
` projections.idp_templates6_ldap2.first_name_attribute,` +
` projections.idp_templates6_ldap2.last_name_attribute,` +
` projections.idp_templates6_ldap2.display_name_attribute,` +
` projections.idp_templates6_ldap2.nick_name_attribute,` +
` projections.idp_templates6_ldap2.preferred_username_attribute,` +
` projections.idp_templates6_ldap2.email_attribute,` +
` projections.idp_templates6_ldap2.email_verified,` +
` projections.idp_templates6_ldap2.phone_attribute,` +
` projections.idp_templates6_ldap2.phone_verified_attribute,` +
` projections.idp_templates6_ldap2.preferred_language_attribute,` +
` projections.idp_templates6_ldap2.avatar_url_attribute,` +
` projections.idp_templates6_ldap2.profile_attribute,` +
// apple
` projections.idp_templates5_apple.idp_id,` +
` projections.idp_templates5_apple.client_id,` +
` projections.idp_templates5_apple.team_id,` +
` projections.idp_templates5_apple.key_id,` +
` projections.idp_templates5_apple.private_key,` +
` projections.idp_templates5_apple.scopes` +
` FROM projections.idp_templates5` +
` LEFT JOIN projections.idp_templates5_oauth2 ON projections.idp_templates5.id = projections.idp_templates5_oauth2.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_oauth2.instance_id` +
` LEFT JOIN projections.idp_templates5_oidc ON projections.idp_templates5.id = projections.idp_templates5_oidc.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_oidc.instance_id` +
` LEFT JOIN projections.idp_templates5_jwt ON projections.idp_templates5.id = projections.idp_templates5_jwt.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_jwt.instance_id` +
` LEFT JOIN projections.idp_templates5_azure ON projections.idp_templates5.id = projections.idp_templates5_azure.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_azure.instance_id` +
` LEFT JOIN projections.idp_templates5_github ON projections.idp_templates5.id = projections.idp_templates5_github.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_github.instance_id` +
` LEFT JOIN projections.idp_templates5_github_enterprise ON projections.idp_templates5.id = projections.idp_templates5_github_enterprise.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_github_enterprise.instance_id` +
` LEFT JOIN projections.idp_templates5_gitlab ON projections.idp_templates5.id = projections.idp_templates5_gitlab.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_gitlab.instance_id` +
` LEFT JOIN projections.idp_templates5_gitlab_self_hosted ON projections.idp_templates5.id = projections.idp_templates5_gitlab_self_hosted.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_gitlab_self_hosted.instance_id` +
` LEFT JOIN projections.idp_templates5_google ON projections.idp_templates5.id = projections.idp_templates5_google.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_google.instance_id` +
` LEFT JOIN projections.idp_templates5_saml ON projections.idp_templates5.id = projections.idp_templates5_saml.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_saml.instance_id` +
` LEFT JOIN projections.idp_templates5_ldap2 ON projections.idp_templates5.id = projections.idp_templates5_ldap2.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_ldap2.instance_id` +
` LEFT JOIN projections.idp_templates5_apple ON projections.idp_templates5.id = projections.idp_templates5_apple.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_apple.instance_id` +
` projections.idp_templates6_apple.idp_id,` +
` projections.idp_templates6_apple.client_id,` +
` projections.idp_templates6_apple.team_id,` +
` projections.idp_templates6_apple.key_id,` +
` projections.idp_templates6_apple.private_key,` +
` projections.idp_templates6_apple.scopes` +
` FROM projections.idp_templates6` +
` LEFT JOIN projections.idp_templates6_oauth2 ON projections.idp_templates6.id = projections.idp_templates6_oauth2.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_oauth2.instance_id` +
` LEFT JOIN projections.idp_templates6_oidc ON projections.idp_templates6.id = projections.idp_templates6_oidc.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_oidc.instance_id` +
` LEFT JOIN projections.idp_templates6_jwt ON projections.idp_templates6.id = projections.idp_templates6_jwt.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_jwt.instance_id` +
` LEFT JOIN projections.idp_templates6_azure ON projections.idp_templates6.id = projections.idp_templates6_azure.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_azure.instance_id` +
` LEFT JOIN projections.idp_templates6_github ON projections.idp_templates6.id = projections.idp_templates6_github.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_github.instance_id` +
` LEFT JOIN projections.idp_templates6_github_enterprise ON projections.idp_templates6.id = projections.idp_templates6_github_enterprise.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_github_enterprise.instance_id` +
` LEFT JOIN projections.idp_templates6_gitlab ON projections.idp_templates6.id = projections.idp_templates6_gitlab.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_gitlab.instance_id` +
` LEFT JOIN projections.idp_templates6_gitlab_self_hosted ON projections.idp_templates6.id = projections.idp_templates6_gitlab_self_hosted.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_gitlab_self_hosted.instance_id` +
` LEFT JOIN projections.idp_templates6_google ON projections.idp_templates6.id = projections.idp_templates6_google.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_google.instance_id` +
` LEFT JOIN projections.idp_templates6_saml ON projections.idp_templates6.id = projections.idp_templates6_saml.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_saml.instance_id` +
` LEFT JOIN projections.idp_templates6_ldap2 ON projections.idp_templates6.id = projections.idp_templates6_ldap2.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_ldap2.instance_id` +
` LEFT JOIN projections.idp_templates6_apple ON projections.idp_templates6.id = projections.idp_templates6_apple.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_apple.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
idpTemplateCols = []string{
"id",
@ -153,6 +154,7 @@ var (
"is_linking_allowed",
"is_auto_creation",
"is_auto_update",
"auto_linking",
// oauth config
"idp_id",
"client_id",
@ -250,129 +252,130 @@ var (
"private_key",
"scopes",
}
idpTemplatesQuery = `SELECT projections.idp_templates5.id,` +
` projections.idp_templates5.resource_owner,` +
` projections.idp_templates5.creation_date,` +
` projections.idp_templates5.change_date,` +
` projections.idp_templates5.sequence,` +
` projections.idp_templates5.state,` +
` projections.idp_templates5.name,` +
` projections.idp_templates5.type,` +
` projections.idp_templates5.owner_type,` +
` projections.idp_templates5.is_creation_allowed,` +
` projections.idp_templates5.is_linking_allowed,` +
` projections.idp_templates5.is_auto_creation,` +
` projections.idp_templates5.is_auto_update,` +
idpTemplatesQuery = `SELECT projections.idp_templates6.id,` +
` projections.idp_templates6.resource_owner,` +
` projections.idp_templates6.creation_date,` +
` projections.idp_templates6.change_date,` +
` projections.idp_templates6.sequence,` +
` projections.idp_templates6.state,` +
` projections.idp_templates6.name,` +
` projections.idp_templates6.type,` +
` projections.idp_templates6.owner_type,` +
` projections.idp_templates6.is_creation_allowed,` +
` projections.idp_templates6.is_linking_allowed,` +
` projections.idp_templates6.is_auto_creation,` +
` projections.idp_templates6.is_auto_update,` +
` projections.idp_templates6.auto_linking,` +
// oauth
` projections.idp_templates5_oauth2.idp_id,` +
` projections.idp_templates5_oauth2.client_id,` +
` projections.idp_templates5_oauth2.client_secret,` +
` projections.idp_templates5_oauth2.authorization_endpoint,` +
` projections.idp_templates5_oauth2.token_endpoint,` +
` projections.idp_templates5_oauth2.user_endpoint,` +
` projections.idp_templates5_oauth2.scopes,` +
` projections.idp_templates5_oauth2.id_attribute,` +
` projections.idp_templates6_oauth2.idp_id,` +
` projections.idp_templates6_oauth2.client_id,` +
` projections.idp_templates6_oauth2.client_secret,` +
` projections.idp_templates6_oauth2.authorization_endpoint,` +
` projections.idp_templates6_oauth2.token_endpoint,` +
` projections.idp_templates6_oauth2.user_endpoint,` +
` projections.idp_templates6_oauth2.scopes,` +
` projections.idp_templates6_oauth2.id_attribute,` +
// oidc
` projections.idp_templates5_oidc.idp_id,` +
` projections.idp_templates5_oidc.issuer,` +
` projections.idp_templates5_oidc.client_id,` +
` projections.idp_templates5_oidc.client_secret,` +
` projections.idp_templates5_oidc.scopes,` +
` projections.idp_templates5_oidc.id_token_mapping,` +
` projections.idp_templates6_oidc.idp_id,` +
` projections.idp_templates6_oidc.issuer,` +
` projections.idp_templates6_oidc.client_id,` +
` projections.idp_templates6_oidc.client_secret,` +
` projections.idp_templates6_oidc.scopes,` +
` projections.idp_templates6_oidc.id_token_mapping,` +
// jwt
` projections.idp_templates5_jwt.idp_id,` +
` projections.idp_templates5_jwt.issuer,` +
` projections.idp_templates5_jwt.jwt_endpoint,` +
` projections.idp_templates5_jwt.keys_endpoint,` +
` projections.idp_templates5_jwt.header_name,` +
` projections.idp_templates6_jwt.idp_id,` +
` projections.idp_templates6_jwt.issuer,` +
` projections.idp_templates6_jwt.jwt_endpoint,` +
` projections.idp_templates6_jwt.keys_endpoint,` +
` projections.idp_templates6_jwt.header_name,` +
// azure
` projections.idp_templates5_azure.idp_id,` +
` projections.idp_templates5_azure.client_id,` +
` projections.idp_templates5_azure.client_secret,` +
` projections.idp_templates5_azure.scopes,` +
` projections.idp_templates5_azure.tenant,` +
` projections.idp_templates5_azure.is_email_verified,` +
` projections.idp_templates6_azure.idp_id,` +
` projections.idp_templates6_azure.client_id,` +
` projections.idp_templates6_azure.client_secret,` +
` projections.idp_templates6_azure.scopes,` +
` projections.idp_templates6_azure.tenant,` +
` projections.idp_templates6_azure.is_email_verified,` +
// github
` projections.idp_templates5_github.idp_id,` +
` projections.idp_templates5_github.client_id,` +
` projections.idp_templates5_github.client_secret,` +
` projections.idp_templates5_github.scopes,` +
` projections.idp_templates6_github.idp_id,` +
` projections.idp_templates6_github.client_id,` +
` projections.idp_templates6_github.client_secret,` +
` projections.idp_templates6_github.scopes,` +
// github enterprise
` projections.idp_templates5_github_enterprise.idp_id,` +
` projections.idp_templates5_github_enterprise.client_id,` +
` projections.idp_templates5_github_enterprise.client_secret,` +
` projections.idp_templates5_github_enterprise.authorization_endpoint,` +
` projections.idp_templates5_github_enterprise.token_endpoint,` +
` projections.idp_templates5_github_enterprise.user_endpoint,` +
` projections.idp_templates5_github_enterprise.scopes,` +
` projections.idp_templates6_github_enterprise.idp_id,` +
` projections.idp_templates6_github_enterprise.client_id,` +
` projections.idp_templates6_github_enterprise.client_secret,` +
` projections.idp_templates6_github_enterprise.authorization_endpoint,` +
` projections.idp_templates6_github_enterprise.token_endpoint,` +
` projections.idp_templates6_github_enterprise.user_endpoint,` +
` projections.idp_templates6_github_enterprise.scopes,` +
// gitlab
` projections.idp_templates5_gitlab.idp_id,` +
` projections.idp_templates5_gitlab.client_id,` +
` projections.idp_templates5_gitlab.client_secret,` +
` projections.idp_templates5_gitlab.scopes,` +
` projections.idp_templates6_gitlab.idp_id,` +
` projections.idp_templates6_gitlab.client_id,` +
` projections.idp_templates6_gitlab.client_secret,` +
` projections.idp_templates6_gitlab.scopes,` +
// gitlab self hosted
` projections.idp_templates5_gitlab_self_hosted.idp_id,` +
` projections.idp_templates5_gitlab_self_hosted.issuer,` +
` projections.idp_templates5_gitlab_self_hosted.client_id,` +
` projections.idp_templates5_gitlab_self_hosted.client_secret,` +
` projections.idp_templates5_gitlab_self_hosted.scopes,` +
` projections.idp_templates6_gitlab_self_hosted.idp_id,` +
` projections.idp_templates6_gitlab_self_hosted.issuer,` +
` projections.idp_templates6_gitlab_self_hosted.client_id,` +
` projections.idp_templates6_gitlab_self_hosted.client_secret,` +
` projections.idp_templates6_gitlab_self_hosted.scopes,` +
// google
` projections.idp_templates5_google.idp_id,` +
` projections.idp_templates5_google.client_id,` +
` projections.idp_templates5_google.client_secret,` +
` projections.idp_templates5_google.scopes,` +
` projections.idp_templates6_google.idp_id,` +
` projections.idp_templates6_google.client_id,` +
` projections.idp_templates6_google.client_secret,` +
` projections.idp_templates6_google.scopes,` +
// saml
` projections.idp_templates5_saml.idp_id,` +
` projections.idp_templates5_saml.metadata,` +
` projections.idp_templates5_saml.key,` +
` projections.idp_templates5_saml.certificate,` +
` projections.idp_templates5_saml.binding,` +
` projections.idp_templates5_saml.with_signed_request,` +
` projections.idp_templates6_saml.idp_id,` +
` projections.idp_templates6_saml.metadata,` +
` projections.idp_templates6_saml.key,` +
` projections.idp_templates6_saml.certificate,` +
` projections.idp_templates6_saml.binding,` +
` projections.idp_templates6_saml.with_signed_request,` +
// ldap
` projections.idp_templates5_ldap2.idp_id,` +
` projections.idp_templates5_ldap2.servers,` +
` projections.idp_templates5_ldap2.start_tls,` +
` projections.idp_templates5_ldap2.base_dn,` +
` projections.idp_templates5_ldap2.bind_dn,` +
` projections.idp_templates5_ldap2.bind_password,` +
` projections.idp_templates5_ldap2.user_base,` +
` projections.idp_templates5_ldap2.user_object_classes,` +
` projections.idp_templates5_ldap2.user_filters,` +
` projections.idp_templates5_ldap2.timeout,` +
` projections.idp_templates5_ldap2.id_attribute,` +
` projections.idp_templates5_ldap2.first_name_attribute,` +
` projections.idp_templates5_ldap2.last_name_attribute,` +
` projections.idp_templates5_ldap2.display_name_attribute,` +
` projections.idp_templates5_ldap2.nick_name_attribute,` +
` projections.idp_templates5_ldap2.preferred_username_attribute,` +
` projections.idp_templates5_ldap2.email_attribute,` +
` projections.idp_templates5_ldap2.email_verified,` +
` projections.idp_templates5_ldap2.phone_attribute,` +
` projections.idp_templates5_ldap2.phone_verified_attribute,` +
` projections.idp_templates5_ldap2.preferred_language_attribute,` +
` projections.idp_templates5_ldap2.avatar_url_attribute,` +
` projections.idp_templates5_ldap2.profile_attribute,` +
` projections.idp_templates6_ldap2.idp_id,` +
` projections.idp_templates6_ldap2.servers,` +
` projections.idp_templates6_ldap2.start_tls,` +
` projections.idp_templates6_ldap2.base_dn,` +
` projections.idp_templates6_ldap2.bind_dn,` +
` projections.idp_templates6_ldap2.bind_password,` +
` projections.idp_templates6_ldap2.user_base,` +
` projections.idp_templates6_ldap2.user_object_classes,` +
` projections.idp_templates6_ldap2.user_filters,` +
` projections.idp_templates6_ldap2.timeout,` +
` projections.idp_templates6_ldap2.id_attribute,` +
` projections.idp_templates6_ldap2.first_name_attribute,` +
` projections.idp_templates6_ldap2.last_name_attribute,` +
` projections.idp_templates6_ldap2.display_name_attribute,` +
` projections.idp_templates6_ldap2.nick_name_attribute,` +
` projections.idp_templates6_ldap2.preferred_username_attribute,` +
` projections.idp_templates6_ldap2.email_attribute,` +
` projections.idp_templates6_ldap2.email_verified,` +
` projections.idp_templates6_ldap2.phone_attribute,` +
` projections.idp_templates6_ldap2.phone_verified_attribute,` +
` projections.idp_templates6_ldap2.preferred_language_attribute,` +
` projections.idp_templates6_ldap2.avatar_url_attribute,` +
` projections.idp_templates6_ldap2.profile_attribute,` +
// apple
` projections.idp_templates5_apple.idp_id,` +
` projections.idp_templates5_apple.client_id,` +
` projections.idp_templates5_apple.team_id,` +
` projections.idp_templates5_apple.key_id,` +
` projections.idp_templates5_apple.private_key,` +
` projections.idp_templates5_apple.scopes,` +
` projections.idp_templates6_apple.idp_id,` +
` projections.idp_templates6_apple.client_id,` +
` projections.idp_templates6_apple.team_id,` +
` projections.idp_templates6_apple.key_id,` +
` projections.idp_templates6_apple.private_key,` +
` projections.idp_templates6_apple.scopes,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_templates5` +
` LEFT JOIN projections.idp_templates5_oauth2 ON projections.idp_templates5.id = projections.idp_templates5_oauth2.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_oauth2.instance_id` +
` LEFT JOIN projections.idp_templates5_oidc ON projections.idp_templates5.id = projections.idp_templates5_oidc.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_oidc.instance_id` +
` LEFT JOIN projections.idp_templates5_jwt ON projections.idp_templates5.id = projections.idp_templates5_jwt.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_jwt.instance_id` +
` LEFT JOIN projections.idp_templates5_azure ON projections.idp_templates5.id = projections.idp_templates5_azure.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_azure.instance_id` +
` LEFT JOIN projections.idp_templates5_github ON projections.idp_templates5.id = projections.idp_templates5_github.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_github.instance_id` +
` LEFT JOIN projections.idp_templates5_github_enterprise ON projections.idp_templates5.id = projections.idp_templates5_github_enterprise.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_github_enterprise.instance_id` +
` LEFT JOIN projections.idp_templates5_gitlab ON projections.idp_templates5.id = projections.idp_templates5_gitlab.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_gitlab.instance_id` +
` LEFT JOIN projections.idp_templates5_gitlab_self_hosted ON projections.idp_templates5.id = projections.idp_templates5_gitlab_self_hosted.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_gitlab_self_hosted.instance_id` +
` LEFT JOIN projections.idp_templates5_google ON projections.idp_templates5.id = projections.idp_templates5_google.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_google.instance_id` +
` LEFT JOIN projections.idp_templates5_saml ON projections.idp_templates5.id = projections.idp_templates5_saml.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_saml.instance_id` +
` LEFT JOIN projections.idp_templates5_ldap2 ON projections.idp_templates5.id = projections.idp_templates5_ldap2.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_ldap2.instance_id` +
` LEFT JOIN projections.idp_templates5_apple ON projections.idp_templates5.id = projections.idp_templates5_apple.idp_id AND projections.idp_templates5.instance_id = projections.idp_templates5_apple.instance_id` +
` FROM projections.idp_templates6` +
` LEFT JOIN projections.idp_templates6_oauth2 ON projections.idp_templates6.id = projections.idp_templates6_oauth2.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_oauth2.instance_id` +
` LEFT JOIN projections.idp_templates6_oidc ON projections.idp_templates6.id = projections.idp_templates6_oidc.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_oidc.instance_id` +
` LEFT JOIN projections.idp_templates6_jwt ON projections.idp_templates6.id = projections.idp_templates6_jwt.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_jwt.instance_id` +
` LEFT JOIN projections.idp_templates6_azure ON projections.idp_templates6.id = projections.idp_templates6_azure.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_azure.instance_id` +
` LEFT JOIN projections.idp_templates6_github ON projections.idp_templates6.id = projections.idp_templates6_github.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_github.instance_id` +
` LEFT JOIN projections.idp_templates6_github_enterprise ON projections.idp_templates6.id = projections.idp_templates6_github_enterprise.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_github_enterprise.instance_id` +
` LEFT JOIN projections.idp_templates6_gitlab ON projections.idp_templates6.id = projections.idp_templates6_gitlab.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_gitlab.instance_id` +
` LEFT JOIN projections.idp_templates6_gitlab_self_hosted ON projections.idp_templates6.id = projections.idp_templates6_gitlab_self_hosted.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_gitlab_self_hosted.instance_id` +
` LEFT JOIN projections.idp_templates6_google ON projections.idp_templates6.id = projections.idp_templates6_google.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_google.instance_id` +
` LEFT JOIN projections.idp_templates6_saml ON projections.idp_templates6.id = projections.idp_templates6_saml.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_saml.instance_id` +
` LEFT JOIN projections.idp_templates6_ldap2 ON projections.idp_templates6.id = projections.idp_templates6_ldap2.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_ldap2.instance_id` +
` LEFT JOIN projections.idp_templates6_apple ON projections.idp_templates6.id = projections.idp_templates6_apple.idp_id AND projections.idp_templates6.instance_id = projections.idp_templates6_apple.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
idpTemplatesCols = []string{
"id",
@ -388,6 +391,7 @@ var (
"is_linking_allowed",
"is_auto_creation",
"is_auto_update",
"auto_linking",
// oauth config
"idp_id",
"client_id",
@ -538,6 +542,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
"idp-id",
"client_id",
@ -651,6 +656,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
OAuthIDPTemplate: &OAuthIDPTemplate{
IDPID: "idp-id",
ClientID: "client_id",
@ -684,6 +690,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -797,6 +804,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
OIDCIDPTemplate: &OIDCIDPTemplate{
IDPID: "idp-id",
Issuer: "issuer",
@ -828,6 +836,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -941,6 +950,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
JWTIDPTemplate: &JWTIDPTemplate{
IDPID: "idp-id",
Issuer: "issuer",
@ -971,6 +981,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1084,6 +1095,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
GitHubIDPTemplate: &GitHubIDPTemplate{
IDPID: "idp-id",
ClientID: "client_id",
@ -1113,6 +1125,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1226,6 +1239,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
GitLabIDPTemplate: &GitLabIDPTemplate{
IDPID: "idp-id",
ClientID: "client_id",
@ -1255,6 +1269,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1368,6 +1383,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
GitLabSelfHostedIDPTemplate: &GitLabSelfHostedIDPTemplate{
IDPID: "idp-id",
Issuer: "issuer",
@ -1398,6 +1414,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1511,6 +1528,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
GoogleIDPTemplate: &GoogleIDPTemplate{
IDPID: "idp-id",
ClientID: "client_id",
@ -1540,6 +1558,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1653,6 +1672,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
SAMLIDPTemplate: &SAMLIDPTemplate{
IDPID: "idp-id",
Metadata: []byte("metadata"),
@ -1684,6 +1704,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1797,6 +1818,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
LDAPIDPTemplate: &LDAPIDPTemplate{
IDPID: "idp-id",
Servers: []string{"server"},
@ -1846,6 +1868,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -1959,6 +1982,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
AppleIDPTemplate: &AppleIDPTemplate{
IDPID: "idp-id",
ClientID: "client_id",
@ -1990,6 +2014,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -2103,6 +2128,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
},
},
{
@ -2162,6 +2188,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -2281,6 +2308,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
LDAPIDPTemplate: &LDAPIDPTemplate{
IDPID: "idp-id",
Servers: []string{"server"},
@ -2333,6 +2361,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -2452,6 +2481,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
},
},
},
@ -2478,6 +2508,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -2589,6 +2620,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -2700,6 +2732,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -2811,6 +2844,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
"idp-id-oauth",
"client_id",
@ -2922,6 +2956,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -3033,6 +3068,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
true,
true,
true,
domain.AutoLinkingOptionUsername,
// oauth
nil,
nil,
@ -3152,6 +3188,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
LDAPIDPTemplate: &LDAPIDPTemplate{
IDPID: "idp-id-ldap",
Servers: []string{"server"},
@ -3193,6 +3230,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
SAMLIDPTemplate: &SAMLIDPTemplate{
IDPID: "idp-id-saml",
Metadata: []byte("metadata"),
@ -3216,6 +3254,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
GoogleIDPTemplate: &GoogleIDPTemplate{
IDPID: "idp-id-google",
ClientID: "client_id",
@ -3238,6 +3277,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
OAuthIDPTemplate: &OAuthIDPTemplate{
IDPID: "idp-id-oauth",
ClientID: "client_id",
@ -3263,6 +3303,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
OIDCIDPTemplate: &OIDCIDPTemplate{
IDPID: "idp-id-oidc",
Issuer: "issuer",
@ -3286,6 +3327,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
IsLinkingAllowed: true,
IsAutoCreation: true,
IsAutoUpdate: true,
AutoLinking: domain.AutoLinkingOptionUsername,
JWTIDPTemplate: &JWTIDPTemplate{
IDPID: "idp-id-jwt",
Issuer: "issuer",

View File

@ -14,14 +14,14 @@ import (
var (
idpUserLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_user_links3.idp_id,` +
` projections.idp_user_links3.user_id,` +
` projections.idp_templates5.name,` +
` projections.idp_templates6.name,` +
` projections.idp_user_links3.external_user_id,` +
` projections.idp_user_links3.display_name,` +
` projections.idp_templates5.type,` +
` projections.idp_templates6.type,` +
` projections.idp_user_links3.resource_owner,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_user_links3` +
` LEFT JOIN projections.idp_templates5 ON projections.idp_user_links3.idp_id = projections.idp_templates5.id AND projections.idp_user_links3.instance_id = projections.idp_templates5.instance_id` +
` LEFT JOIN projections.idp_templates6 ON projections.idp_user_links3.idp_id = projections.idp_templates6.id AND projections.idp_user_links3.instance_id = projections.idp_templates6.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
idpUserLinksCols = []string{
"idp_id",

View File

@ -17,7 +17,7 @@ import (
)
const (
IDPTemplateTable = "projections.idp_templates5"
IDPTemplateTable = "projections.idp_templates6"
IDPTemplateOAuthTable = IDPTemplateTable + "_" + IDPTemplateOAuthSuffix
IDPTemplateOIDCTable = IDPTemplateTable + "_" + IDPTemplateOIDCSuffix
IDPTemplateJWTTable = IDPTemplateTable + "_" + IDPTemplateJWTSuffix
@ -59,6 +59,7 @@ const (
IDPTemplateIsLinkingAllowedCol = "is_linking_allowed"
IDPTemplateIsAutoCreationCol = "is_auto_creation"
IDPTemplateIsAutoUpdateCol = "is_auto_update"
IDPTemplateAutoLinkingCol = "auto_linking"
OAuthIDCol = "idp_id"
OAuthInstanceIDCol = "instance_id"
@ -197,6 +198,7 @@ func (*idpTemplateProjection) Init() *old_handler.Check {
handler.NewColumn(IDPTemplateIsLinkingAllowedCol, handler.ColumnTypeBool, handler.Default(false)),
handler.NewColumn(IDPTemplateIsAutoCreationCol, handler.ColumnTypeBool, handler.Default(false)),
handler.NewColumn(IDPTemplateIsAutoUpdateCol, handler.ColumnTypeBool, handler.Default(false)),
handler.NewColumn(IDPTemplateAutoLinkingCol, handler.ColumnTypeEnum, handler.Default(0)),
},
handler.NewPrimaryKey(IDPTemplateInstanceIDCol, IDPTemplateIDCol),
handler.WithIndex(handler.NewIndex("resource_owner", []string{IDPTemplateResourceOwnerCol})),
@ -700,6 +702,7 @@ func (p *idpTemplateProjection) reduceOAuthIDPAdded(event eventstore.Event) (*ha
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -792,6 +795,7 @@ func (p *idpTemplateProjection) reduceOIDCIDPAdded(event eventstore.Event) (*han
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -873,6 +877,7 @@ func (p *idpTemplateProjection) reduceOIDCIDPMigratedAzureAD(event eventstore.Ev
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
[]handler.Condition{
handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
@ -924,6 +929,7 @@ func (p *idpTemplateProjection) reduceOIDCIDPMigratedGoogle(event eventstore.Eve
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
[]handler.Condition{
handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
@ -982,6 +988,7 @@ func (p *idpTemplateProjection) reduceJWTIDPAdded(event eventstore.Event) (*hand
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1070,6 +1077,7 @@ func (p *idpTemplateProjection) reduceOldConfigAdded(event eventstore.Event) (*h
handler.NewCol(IDPTemplateIsLinkingAllowedCol, true),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.AutoRegister),
handler.NewCol(IDPTemplateIsAutoUpdateCol, false),
handler.NewCol(IDPTemplateAutoLinkingCol, domain.AutoLinkingOptionUnspecified),
},
), nil
}
@ -1328,6 +1336,7 @@ func (p *idpTemplateProjection) reduceAzureADIDPAdded(event eventstore.Event) (*
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1418,6 +1427,7 @@ func (p *idpTemplateProjection) reduceGitHubIDPAdded(event eventstore.Event) (*h
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1465,6 +1475,7 @@ func (p *idpTemplateProjection) reduceGitHubEnterpriseIDPAdded(event eventstore.
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1597,6 +1608,7 @@ func (p *idpTemplateProjection) reduceGitLabIDPAdded(event eventstore.Event) (*h
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1685,6 +1697,7 @@ func (p *idpTemplateProjection) reduceGitLabSelfHostedIDPAdded(event eventstore.
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1774,6 +1787,7 @@ func (p *idpTemplateProjection) reduceGoogleIDPAdded(event eventstore.Event) (*h
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1862,6 +1876,7 @@ func (p *idpTemplateProjection) reduceLDAPIDPAdded(event eventstore.Event) (*han
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -1970,6 +1985,7 @@ func (p *idpTemplateProjection) reduceSAMLIDPAdded(event eventstore.Event) (*han
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -2061,6 +2077,7 @@ func (p *idpTemplateProjection) reduceAppleIDPAdded(event eventstore.Event) (*ha
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
},
),
handler.AddCreateStatement(
@ -2191,6 +2208,9 @@ func reduceIDPChangedTemplateColumns(name *string, creationDate time.Time, seque
if optionChanges.IsAutoUpdate != nil {
cols = append(cols, handler.NewCol(IDPTemplateIsAutoUpdateCol, *optionChanges.IsAutoUpdate))
}
if optionChanges.AutoLinkingOption != nil {
cols = append(cols, handler.NewCol(IDPTemplateAutoLinkingCol, *optionChanges.AutoLinkingOption))
}
return append(cols,
handler.NewCol(IDPTemplateChangeDateCol, creationDate),
handler.NewCol(IDPTemplateSequenceCol, sequence),

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,25 @@
package idp
import (
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/zerrors"
)
type Options struct {
IsCreationAllowed bool `json:"isCreationAllowed,omitempty"`
IsLinkingAllowed bool `json:"isLinkingAllowed,omitempty"`
IsAutoCreation bool `json:"isAutoCreation,omitempty"`
IsAutoUpdate bool `json:"isAutoUpdate,omitempty"`
IsCreationAllowed bool `json:"isCreationAllowed,omitempty"`
IsLinkingAllowed bool `json:"isLinkingAllowed,omitempty"`
IsAutoCreation bool `json:"isAutoCreation,omitempty"`
IsAutoUpdate bool `json:"isAutoUpdate,omitempty"`
AutoLinkingOption domain.AutoLinkingOption `json:"autoLinkingOption,omitempty"`
}
type OptionChanges struct {
IsCreationAllowed *bool `json:"isCreationAllowed,omitempty"`
IsLinkingAllowed *bool `json:"isLinkingAllowed,omitempty"`
IsAutoCreation *bool `json:"isAutoCreation,omitempty"`
IsAutoUpdate *bool `json:"isAutoUpdate,omitempty"`
IsCreationAllowed *bool `json:"isCreationAllowed,omitempty"`
IsLinkingAllowed *bool `json:"isLinkingAllowed,omitempty"`
IsAutoCreation *bool `json:"isAutoCreation,omitempty"`
IsAutoUpdate *bool `json:"isAutoUpdate,omitempty"`
AutoLinkingOption *domain.AutoLinkingOption `json:"autoLinkingOption,omitempty"`
}
func (o *Options) Changes(options Options) OptionChanges {
@ -33,6 +36,9 @@ func (o *Options) Changes(options Options) OptionChanges {
if o.IsAutoUpdate != options.IsAutoUpdate {
opts.IsAutoUpdate = &options.IsAutoUpdate
}
if o.AutoLinkingOption != options.AutoLinkingOption {
opts.AutoLinkingOption = &options.AutoLinkingOption
}
return opts
}
@ -49,10 +55,13 @@ func (o *Options) ReduceChanges(changes OptionChanges) {
if changes.IsAutoUpdate != nil {
o.IsAutoUpdate = *changes.IsAutoUpdate
}
if changes.AutoLinkingOption != nil {
o.AutoLinkingOption = *changes.AutoLinkingOption
}
}
func (o *OptionChanges) IsZero() bool {
return o.IsCreationAllowed == nil && o.IsLinkingAllowed == nil && o.IsAutoCreation == nil && o.IsAutoUpdate == nil
return o.IsCreationAllowed == nil && o.IsLinkingAllowed == nil && o.IsAutoCreation == nil && o.IsAutoUpdate == nil && o.AutoLinkingOption == nil
}
type RemovedEvent struct {

View File

@ -7494,6 +7494,7 @@ message SetCustomLoginTextsRequest {
zitadel.text.v1.PasswordlessRegistrationScreenText passwordless_registration_text = 33;
zitadel.text.v1.PasswordlessRegistrationDoneScreenText passwordless_registration_done_text = 34;
zitadel.text.v1.ExternalRegistrationUserOverviewScreenText external_registration_user_overview_text = 35;
zitadel.text.v1.LinkingUserPromptScreenText linking_user_prompt_text = 36;
}
message SetCustomLoginTextsResponse {

View File

@ -515,6 +515,21 @@ message Options {
description: "Enable if a the ZITADEL account fields should be updated automatically on each login.";
}
];
AutoLinkingOption auto_linking = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Enable if users should get prompted to link an existing ZITADEL user to an external account if the selected attribute matches.";
}
];
}
enum AutoLinkingOption {
// AUTO_LINKING_OPTION_UNSPECIFIED disables the auto linking prompt.
AUTO_LINKING_OPTION_UNSPECIFIED = 0;
// AUTO_LINKING_OPTION_USERNAME will use the username of the external user to check for a corresponding ZITADEL user.
AUTO_LINKING_OPTION_USERNAME = 1;
// AUTO_LINKING_OPTION_EMAIL will use the email of the external user to check for a corresponding ZITADEL user with the same verified email
// Note that in case multiple users match, no prompt will be shown.
AUTO_LINKING_OPTION_EMAIL = 2;
}
message LDAPAttributes {

View File

@ -10948,6 +10948,7 @@ message SetCustomLoginTextsRequest {
zitadel.text.v1.PasswordlessRegistrationScreenText passwordless_registration_text = 33;
zitadel.text.v1.PasswordlessRegistrationDoneScreenText passwordless_registration_done_text = 34;
zitadel.text.v1.ExternalRegistrationUserOverviewScreenText external_registration_user_overview_text = 35;
zitadel.text.v1.LinkingUserPromptScreenText linking_user_prompt_text = 36;
}
message SetCustomLoginTextsResponse {

View File

@ -92,6 +92,7 @@ message LoginCustomText {
PasswordlessRegistrationDoneScreenText passwordless_registration_done_text = 34;
ExternalRegistrationUserOverviewScreenText external_registration_user_overview_text = 35;
bool is_default = 36;
LinkingUserPromptScreenText linking_user_prompt_text = 37;
}
message SelectAccountScreenText {
@ -357,6 +358,13 @@ message RegistrationOrgScreenText {
string save_button_text = 19 [(validate.rules).string = {max_len: 200}];
}
message LinkingUserPromptScreenText {
string title = 1 [(validate.rules).string = {max_len: 200}];
string description = 2 [(validate.rules).string = {max_len: 500}];
string link_button_text = 3 [(validate.rules).string = {max_len: 100}];
string other_button_text = 4 [(validate.rules).string = {max_len: 100}];
}
message LinkingUserDoneScreenText {
string title = 1 [(validate.rules).string = {max_len: 200}];
string description = 2 [(validate.rules).string = {max_len: 500}];